Proxy.isProxyClass scalability

Mandy Chung mandy.chung at oracle.com
Wed Apr 17 05:31:37 UTC 2013


On 4/16/2013 7:18 AM, Peter Levart wrote:
> Hi Mandy,
>
> I prepared a preview variant of j.l.r.Proxy using WeakCache (turned 
> into an interface and a special FlattenedWeakCache implementation in 
> anticipation to create another variant using two-levels of 
> ConcurrentHashMaps for backing storage, but with same API) just to 
> compare performance:
>
> https://dl.dropboxusercontent.com/u/101777488/jdk8-tl/proxy-wc/webrev.01/index.html
>


thanks for getting this prototype done quickly.

> As the values (Class objects of proxy classes) must be wrapped in a 
> WeakReference, the same instance of WeakReference can be re-used as a 
> key in another ConcurrentHashMap to implement quick look-up for 
> Proxy.isProxyClass() method eliminating the need to use ClassValue, 
> which is quite space-hungry.
>

I also think maintaining another ConcurrentHashMap is a good replacement 
with the use of ClassValue to avoid its memory overhead.

> Comparing the performance, here's a summary of all 3 variants 
> (original, patched using a field in ClassLoader and this variant):
>
> [...]
>
> The improvement is still quite satisfactory, although a little slower 
> than the direct-field variant. The scalability is the same as with 
> direct-field variant.
>

Agree - the improvement is quite good.

> Space consumption of cache structure, calculated as deep-size of the 
> structure, ignoring interned Strings, Class and ClassLoader objects 
> unsing single non-bootstrap ClassLoader for defining the proxy classes 
> and using 32 bit addressing is the following:
>
> [...]
>
> So with new ConcurrentHashMap the patched Proxy uses about 32 bytes 
> more per proxy class.
>
> Is this satisfactory or should we also try a variant with two-levels 
> of ConcurrentHashMaps?
>

The overhead seems okay to trade off the scalability.

Since you have prepared for doing another variant, it'd be good to 
compare two prototypes if this doesn't bring too much work :)  I would 
imagine that there might be slight difference in your measurement when 
comparing with proxies defined by a single class loader but the code 
might be simpler (might not be if you keep the same API but different 
implementation).

Regardless of which approach to use - you have added a general purpose 
WeakCache and the implementation class in the sun.misc package.  While 
it's good to have such class for other jdk class to use, I am more 
comfortable in keeping it as a private class for proxy implementation to 
use.  We need existing applications to migrate away from sun.misc and 
other private APIs to prepare for modularization.

Nits: can you wrap the lines around 80 columns including comments? 
try-catch-finally statements need some formatting fixes.  Our convention 
is to have 'catch', or 'finally' following the closing bracket '}' in 
the same line.  Your editor breaks 'catch' or 'finally' into the next line.

>
> Even without SecurityManager installed the performance of native 
> getClassLoader0 was a hog. I don't know why? Isn't there an implicit 
> reference to defining ClassLoader from every Class object?

That's right - it looks for the caller class only if the security 
manager is installed.   The defining class loader is kept in the VM's 
Klass object (language-level Class instance representation in the VM) 
and there is no computation needed to obtain a defining class loader of 
a given Class object.  I can only think of the Java <-> native 
transition overhead that could be one factor. Class.getClassLoader0 is 
not intrinsified.  I'll find out (others on this mailing list may 
probably know).

Mandy



More information about the core-libs-dev mailing list