On Wed, 6 Jan 2021 01:20:40 GMT, Claes Redestad <[email protected]> wrote:

>> I refactored and optimized the lookup code further, getting rid of a number 
>> of bottlenecks:
>> 
>> - Cache Constructors in Provider.Service instead of via a ClassValue.
>> - Also cache the impl Class, wrap Class and Constructor in WeakReference if 
>> not loaded by the null classloader (many builtins will be)
>> - Cache EngineDescription in Service, avoiding a lookup on the hot path
>> - We were hitting a synchronized method in ProviderConfig.getProvider(). The 
>> provider field is volatile already, so I used the double-check idiom here to 
>> avoid synchronization on the hot path
>> - ServiceKey.hashCode using Objects.hash was cause for allocation, 
>> simplified and optimized it.
>> 
>> Benchmark                                                      
>> (digesterName)  Mode  Cnt     Score    Error   Units
>> GetMessageDigest.getInstance                                              
>> MD5  avgt   30   143.803 ±  5.431   ns/op
>> GetMessageDigest.getInstance:·gc.alloc.rate.norm                          
>> MD5  avgt   30   280.015 ±  0.001    B/op
>
> Since much of the cost is now the creation of the MessageDigest itself, I 
> added a microbenchmark to stat this overhead:
> 
> Benchmark                                                        
> (digesterName)  Mode  Cnt     Score     Error   Units
> GetMessageDigest.cloneInstance                                              
> MD5  avgt   30   124.922 ±   5.412   ns/op
> GetMessageDigest.cloneInstance:·gc.alloc.rate.norm                          
> MD5  avgt   30   280.015 ±   0.001    B/op
> 
> That means there's no added allocation overhead of calling 
> `MessageDigest.getInstance(digesterName)` compared to cloning an existing 
> instance - which means we get almost all of the benefits without resorting to 
> tricks as caching and cloning an instance at call sites such as the one in 
> `UUID::nameUUIDFromBytes`. The remaining 20ns/op difference should be 
> negligible.

Nice speedup for all `MessageDigest.getInstance` and `Provider.getService` 
invocations and improves on removing the scalability bottlenecks of 
`Provider.getService` beyond 
[JDK-7092821](https://bugs.openjdk.java.net/browse/JDK-7092821) (and related 
[JDK-8080273](https://bugs.openjdk.java.net/browse/JDK-8080273) & 
[JDK-8172827](https://bugs.openjdk.java.net/browse/JDK-8172827)). This will 
also allow removing some longstanding `MessageDigest#clone` workarounds such as 
in Guava https://github.com/google/guava/issues/1197 .

-------------

PR: https://git.openjdk.java.net/jdk/pull/1933

Reply via email to