>
>> HashArray.java:
>>    82             Integer.highestOneBit(expectedMaxSize +
>> (expectedMaxSize << 1))
>>
>>
>> This effectively multiples expectedMaxSize by 3, I guess you meant >>
>> instead.
>>
>
> The intention of capacity(int expectedMaxSize) is to return the smallest
> power of 2 number that is greater than 3 * expectedMaxSize / 2.
>

The method is copied from IdentityHashMap, so I'm sure it does it right ;-)
>
> Indeed it does so, it can lead to almost 3x times (i.e. fill factor of
.33) waste for some numbers (11, 22, 43) . But I supposed it's a good
tradeoff.



>  Perhaps extra a method about effective capacity?
>>
>
> Don't know what you mean by effective capacity? The capacity() is meant to
> size the initial array. And it behaves correctly even for large requested
> expectedMaxSize values that would cause an overflow in naively written code.
>
> I meant to "extract" (not extra) a method for  s + (s >> 1)  but it's used
once only, so please disregard this part.


There is some code duplication in the different impl. of consolidate()  but
trying to refactor it (in a static method) would cause some performance
degradation (I don't think there is an intrinsic for the native
Class.isInterface()). So, I guess it can be left that way, as it's not too
much.


Stanimir


>> On Wed, Nov 5, 2014 at 6:58 PM, Peter Levart <peter.lev...@gmail.com>
>> wrote:
>>
>>  On 11/01/2014 06:49 PM, Peter Levart wrote:
>>>
>>>  On 10/30/2014 07:13 PM, Martin Buchholz wrote: Which is why I was
>>>>
>>>>> expecting to have to write an adaptive
>>>>> data structure that switches from linear search to hash-based when
>>>>> some threshold is exceeded.
>>>>>
>>>>>  ...or two data structures. Since I have already arranged so that
>>>> construction of MethodTable gets an upper limit on the total number of
>>>> possible Method(s) that can be added to it, we can have two MethodTable
>>>> implementations and switch based on this number:
>>>>
>>>> http://cr.openjdk.java.net/~plevart/jdk9-dev/Class.getMethods/webrev.05/
>>>>
>>>>  Hi,
>>>
>>> I made some progress on this front. I created new MethodTable
>>> implementation (the third one) with similar performance as HashMap based,
>>> but producing half the garbage. I also added some optimizations to
>>> getMethod(), getMethods() and MethodTable in general that deal with
>>> special
>>> cases / parameter types comparison and have measurable impact on
>>> performance (for example loading all rt.jar classes and calling
>>> getMethods() for them):
>>>
>>> Original:
>>>
>>> 19658 classes loaded in 2.003623648 seconds.
>>> 494392 methods obtained in 0.932151066 seconds.
>>> 494392 methods obtained in 0.968247076 seconds.
>>> 494392 methods obtained in 0.989218185 seconds.
>>> 494392 methods obtained in 1.018700179 seconds.
>>> 494392 methods obtained in 0.945078767 seconds.
>>> 494392 methods obtained in 0.930856897 seconds.
>>> 494392 methods obtained in 0.905420555 seconds.
>>> 494392 methods obtained in 0.89253006 seconds.
>>> 494392 methods obtained in 0.914590141 seconds.
>>> 494392 methods obtained in 0.891616716 seconds.
>>> 494392 methods obtained in 0.891839815 seconds.
>>> 494392 methods obtained in 0.892863985 seconds.
>>> 494392 methods obtained in 0.960643274 seconds.
>>> 494392 methods obtained in 0.959266392 seconds.
>>> 494392 methods obtained in 0.894688322 seconds.
>>> 494392 methods obtained in 0.892751891 seconds.
>>> 494392 methods obtained in 0.912542838 seconds.
>>> 494392 methods obtained in 0.912219636 seconds.
>>> 494392 methods obtained in 0.895791468 seconds.
>>> 494392 methods obtained in 0.891673959 seconds.
>>>
>>> Patched:
>>>
>>> 19658 classes loaded in 2.145270948 seconds.
>>> 494398 methods obtained in 0.722630874 seconds.
>>> 494398 methods obtained in 0.697521755 seconds.
>>> 494398 methods obtained in 0.689642554 seconds.
>>> 494398 methods obtained in 0.742724992 seconds.
>>> 494398 methods obtained in 0.695693313 seconds.
>>> 494398 methods obtained in 0.685169108 seconds.
>>> 494398 methods obtained in 0.663012634 seconds.
>>> 494398 methods obtained in 0.666446935 seconds.
>>> 494398 methods obtained in 0.675662884 seconds.
>>> 494398 methods obtained in 0.65369404 seconds.
>>> 494398 methods obtained in 0.656608178 seconds.
>>> 494398 methods obtained in 0.668384051 seconds.
>>> 494398 methods obtained in 0.657548957 seconds.
>>> 494398 methods obtained in 0.672332234 seconds.
>>> 494398 methods obtained in 0.655699295 seconds.
>>> 494398 methods obtained in 0.671819628 seconds.
>>> 494398 methods obtained in 0.657232183 seconds.
>>> 494398 methods obtained in 0.654462137 seconds.
>>> 494398 methods obtained in 0.659630473 seconds.
>>> 494398 methods obtained in 0.674219391 seconds.
>>>
>>> (the difference in method count is expected - patched code contains new
>>> methods in existing rt.jar classes ;-)
>>>
>>> Here's new webrev:
>>>
>>> http://cr.openjdk.java.net/~plevart/jdk9-dev/Class.getMethods/webrev.06/
>>>
>>>
>>> The optimizations made from webrev.05 are:
>>>
>>> - getMethod() skips construction of MethodTable if there are no
>>> (super)interfaces.
>>> - getMethods() returns just declared public methods if there are no
>>> superclass and no (super)interfaces.
>>> - comparing method parameter types is optimized by adding two methods to
>>> Method/LangReflectAccess/ReflectionFactory.
>>>
>>> New MethodTable implementation based on a linear-probe hash table is a
>>> space/garbage improvement. I took IdentityHashMap, removed unneeded stuff
>>> and modified it's API. The result is a HashArray. It's API is similar in
>>> function and form to java.util.Map, but doesn't use separate keys and
>>> values. An element of HashArray is a key and a value at the same time.
>>> Elements are always non-null, so the method return values are
>>> unambiguous.
>>> As HashArray is a linear-probe hash table and there are no Map.Entry
>>> objects involved, the underlying data structure is very simple and memory
>>> efficient. It is just a sparse array of elements with length that is
>>> always
>>> a power of two and larger than 3 * size / 2. It also features
>>> overriddable
>>> element equals/hashCode methods. I made it a separate generic class
>>> because
>>> I think it can find it's usage elsewhere (for example as a
>>> cannonicalizing
>>> cache).
>>>
>>> Since HashArray based MethodTable is more space-efficient I moved the
>>> line
>>> between simple array based and HashArray based MethodTable down to 20
>>> elements to minimize the worst-case scenario effect. Calling getMethods()
>>> on all rt.jar classes now constructs about 3/4 simple array based and 1/4
>>> HashArray based MethodTables.
>>>
>>> Here's also Martin's ManyMethodsBenchmark:
>>>
>>> Original:
>>>
>>> Base class load time: 129.95 ms
>>> getDeclaredMethods: 65521 methods, 36.58 ms total time, 0.0006 ms per
>>> method
>>> getMethods        : 65530 methods, 47.43 ms total time, 0.0007 ms per
>>> method
>>> Derived class load time: 32216.09 ms
>>> getDeclaredMethods: 65521 methods, 35.05 ms total time, 0.0005 ms per
>>> method
>>> getMethods        : 65530 methods, 8068.66 ms total time, 0.1231 ms per
>>> method
>>>
>>>
>>> Patched (using HashArray based MethodTable):
>>>
>>> Base class load time: 126.00 ms
>>> getDeclaredMethods: 65521 methods, 36.83 ms total time, 0.0006 ms per
>>> method
>>> getMethods        : 65530 methods, 45.08 ms total time, 0.0007 ms per
>>> method
>>> Derived class load time: 31865.27 ms
>>> getDeclaredMethods: 65521 methods, 35.01 ms total time, 0.0005 ms per
>>> method
>>> getMethods        : 65530 methods, 78.05 ms total time, 0.0012 ms per
>>> method
>>>
>>>
>>> All 86 jtreg test in java.lang/Class/ and java/lang/reflect/ still pass.
>>>
>>>
>>> Regards, Peter
>>>
>>>
>>>
>

Reply via email to