Tbh I have a hard time understand what you are trying to convey. Please write grammatically correct sentences with clear structure.
I notice you attach benchmark results but I don't see what was benchmarked to produce those results. Another point is that Value classes has not been delivered yet, so there are potential performance uplifts of Optional in the future. This may not be possible if Optional is polymorphic. Thanks On Mon, 28 Aug 2023 at 18:27, Oleksii Kucheruk <iselo+open...@raccoons.co> wrote: > Thank you Quân. > > All you saying guys make sense. > Yes there is a difference calling methods by pointer and involving vtable. > But one thing didn't came out of my head: > If virtual dispatch dispatch is 10-time more expensive and polymorphism is > a performance killer so how combinations of "return optional - isPresent- > get" or "return empty - isEmpty" with virtual dispatch and memory > allocation for every empty or sole but polymorph empty could perform > equally or even beat the near zero-cost abstraction of Value classes > according to JMH? > > Maybe private final static nested EmptyOptional invokevirtual bytecode refers > a final methods and it need not have a vtable slot allocated. This means > that, after linking, an invokevirtual bytecode might in fact collapse into > the equivalent of an invokestatic bytecode. > The question of full dynamic with anonymous overloading is still unclear > to me. > > Benchmark Mode Cnt > Score Error Units > > *OptionalComboIsPresentGet.opDynamicAnonymous thrpt 30 > 1059868995.937 ± 51273067.116 ops/s* > > OptionalComboIsPresentGet.opJdk thrpt 30 > 1017505800.567 > ± 16007847.872 ops/s > > OptionalComboIsPresentGet.opNestedStatic thrpt 30 > 951493332.957 > ± 12167812.398 ops/s > > > OptionalComboOfIsPresentGetTest.opDynamicAnonymous thrpt 30 > 1426348334.485 > ± 20889455.433 ops/s > > *OptionalComboOfIsPresentGetTest.opJdk thrpt 30 > 1435570789.822 ± 16587538.659 ops/s* > > OptionalComboOfIsPresentGetTest.opNestedStatic thrpt 30 > 1418853644.215 > ± 27755398.645 ops/s > > > *OptionalComboOfNullableIsEmptyTest.opDynamicAnonymous thrpt 30 > 1434399595.592 ± 14749443.903 ops/s* > > OptionalComboOfNullableIsEmptyTest.opJdk thrpt 30 > 1255375023.531 > ± 107403119.573 ops/s > > OptionalComboOfNullableIsEmptyTest.opNestedStatic thrpt 30 > 1415705702.964 > ± 26328318.672 ops/s > > > OptionalEmptyTest.opDynamicAnonymous thrpt 30 > 1417895521.763 > ± 26311640.557 ops/s > > *OptionalEmptyTest.opJdk thrpt 30 > 1423940087.962 ± 18515297.860 ops/s* > > OptionalEmptyTest.opNestedStatic thrpt 30 > 1424779162.084 > ± 20288793.337 ops/s > > > OptionalGetTest.emDynamicAnonymous thrpt 30 > 569132.235 > ± 11089.903 ops/s > > *OptionalGetTest.emJdk thrpt 30 > 549764.038 ± 14768.566 ops/s* > > OptionalGetTest.emNestedStatic thrpt 30 > 568308.722 > ± 6075.671 ops/s > > > OptionalGetTest.opDynamicAnonymous thrpt 30 > 953788065.414 > ± 7043419.784 ops/s > > *OptionalGetTest.opJdk thrpt 30 > 1015679232.049 ± 11726562.032 ops/s* > > OptionalGetTest.opNestedStatic thrpt 30 > 944209513.151 > ± 17718342.519 ops/s > > > OptionalIsPresentTest.emDynamicAnonymous thrpt 30 > 869086292.481 > ± 11668636.886 ops/s > > *OptionalIsPresentTest.emJdk thrpt 30 > 977042244.447 ± 44558020.220 ops/s* > > OptionalIsPresentTest.emNestedStatic thrpt 30 > 953424664.631 > ± 8448564.963 ops/s > > > OptionalIsPresentTest.opDynamicAnonymous thrpt 30 > 953285872.799 > ± 6562894.941 ops/s > > *OptionalIsPresentTest.opJdk thrpt 30 > 1006926903.885 ± 18055487.689 ops/s* > > OptionalIsPresentTest.opNestedStatic thrpt 30 > 954121471.431 > ± 6829528.708 ops/s > > > OptionalOfNullableTest.emDynamicAnonymous thrpt 30 > 1422939780.266 > ± 21693247.354 ops/s > > *OptionalOfNullableTest.emJdk thrpt 30 > 1423340184.237 ± 21296444.017 ops/s* > > OptionalOfNullableTest.emNestedStatic thrpt 30 > 1414965236.385 > ± 26021734.344 ops/s > > > OptionalOfNullableTest.opDynamicAnonymous thrpt 30 > 1412594454.538 > ± 28123612.298 ops/s > > *OptionalOfNullableTest.opJdk thrpt 30 > 1427924599.589 ± 23469517.835 ops/s* > > OptionalOfNullableTest.opNestedStatic thrpt 30 > 1420053175.637 > ± 21170929.571 ops/s > > > OptionalOfTest.emDynamicAnonymous thrpt 30 > 549907.559 > ± 14560.954 ops/s > > OptionalOfTest.emJdk thrpt 30 > 557858.903 > ± 2851.076 ops/s > > *OptionalOfTest.emNestedStatic thrpt 30 > 548655.854 ± 10875.674 ops/s* > > > OptionalOfTest.opDynamicAnonymous thrpt 30 > 1411307270.435 > ± 19832207.408 ops/s > > OptionalOfTest.opJdk thrpt 30 > 1400651442.726 > ± 23641065.234 ops/s > > *OptionalOfTest.opNestedStatic thrpt 30 > 1433953744.298 ± 21414147.936 ops/s* > > > On Mon, Aug 28, 2023 at 11:13 AM Quân Anh Mai <anh...@gmail.com> wrote: > >> Hi, >> >> Polymorphism is a performance killer. Normally this does not matter much, >> but for thin wrappers such as Optional, this is one of the most important >> factor. >> >> Behaviour polymorphism requires virtual dispatch and prevents inlining. >> This is really detrimental, as simple operations such as a getter which is >> previously only consisted of a memory load, in the presence of polymorphism >> would have to go through a 10-time more expensive virtual dispatch. >> Function calls, especially virtual ones, are also opaque and prohibit >> compiler optimisations. >> >> Layout polymorphism prevents direct accesses and requires indirection. >> This means that for every instance of Optional created a memory allocation >> is required. Optional is expected to be a near zero-cost abstraction in the >> presence of Value classes, so making it polymorphic is unacceptable. >> >> Thanks. >> >> On Wed, 23 Aug 2023 at 22:43, Oleksii Kucheruk <iselo+open...@raccoons.co> >> wrote: >> >>> Hi there. >>> I have found that `java.util.Optional` is written procedural style and >>> has `ifnonnull` checks in each method. I propose to refactor `Optional` in >>> accordance to OOP-style. This will eliminates all unnecessary >>> `if`-statements, removes duplications and reduces bytecode size more then >>> twice. >>> >>> I have two solutions: >>> 1. Completely dynamic that avoids single static `EMPTY` instance and >>> unchecked casting of each `Optional.empty()` >>> 2. Preserving original single static `EMPTY` per VM. >>> >>> Also there are couple methods that throws NPE due to calling methods on >>> null-objects and requires to add `Objects.requireNonNull(...)`. >>> >>> OptionalInt, OptionalDouble, OptionalLong could be refactored same way >>> even with remove of additional boolean variable `isPresent`. >>> >>> Since I'm new here any guidance will be helpful. >>> Thank you in advance. >>> >>