RFE: Refactor java.util.Optional and add NonNull checks

Oleksii Kucheruk iselo+openjdk at raccoons.co
Mon Aug 28 12:17:23 UTC 2023


Now it is clear. Sorry for the inconvenience. Thank you for your time. I
appreciate.

On Mon, 28 Aug 2023 at 2:03 PM Quân Anh Mai <anhmdq at gmail.com> wrote:

> 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+openjdk at 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 <anhmdq at 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+openjdk at 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.
>>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20230828/832e3d98/attachment-0001.htm>


More information about the core-libs-dev mailing list