Proxy.isProxyClass scalability
Peter Levart
peter.levart at gmail.com
Sat Apr 20 16:37:18 UTC 2013
On 04/20/2013 09:31 AM, Peter Levart wrote:
> Hi Mandy,
>
> I have another idea. Before jumping to implement it, I will first ask
> what do you think of it. For example:
>
> - have an optimal interface names key calculated from interfaces.
> - visibility of interfaces and other validations are pushed to
> slow-path (inside ProxyClassFactory.apply)
> - the proxy Class object returned from WeakCache.get() is
> post-validated with a check like:
>
> for (Class<?> intf : interfaces) {
> if (!intf.isAssignableFrom(proxyClass)) {
> throw new IllegalArgumentException();
> }
> }
> // return post-validated proxyClass from getProxyClass0()...
I just did it:
http://dl.dropboxusercontent.com/u/101777488/jdk8-tl/proxy-wc/webrev.03/index.html
I also incorporated the expunging optimization that I talked about in
one of previous mails.
And the keys, composed of interface names, are now more space-friendly too:
- a key for 0 interface proxy is a singleton Object
- a key for 1 interface proxy is the name of the interface itself (an
already interned String)
- a key for 2 interface proxy is a special class with 2 references to
interned Strings
- a key for 3+ interface proxy is a special class wrapping an array of
interned Strings
The performance is screaming again (WeakCache+post-validation):
ns/op WeakCache+ WeakCache+
Test Threads Original pre-valid. post-valid.
======================= ======= =========== =========== ===========
Proxy_getProxyClass 1 2,420.99 2,258.00 211.04
4 3,075.39 2,644.26 282.93
8 5,374.45 5,159.71 432.14
Proxy_isProxyClassTrue 1 97.75 45.37 42.67
4 2,505.92 42.59 42.77
8 5,042.61 75.44 73.20
Proxy_isProxyClassFalse 1 89.20 1.40 1.40
4 2,548.61 1.40 1.40
8 4,901.56 2.82 2.80
Annotation_equals 1 224.39 201.82 202.97
4 2,046.21 200.61 204.89
8 3,564.78 347.27 344.57
And the space savings are now even greater. Patched code is always
better space-wise. The savings are:
32 bit addressing:
- 56 bytes per proxy class implementing 1 interface
- 32 bytes per proxy class implementing 2 interfaces
- 16 bytes per proxy class implementing 3 or more interfaces
64 bit addressing:
- 80 bytes per proxy class implementing 1 interface
- 56 bytes per proxy class implementing 2 interfaces
- 24 bytes per proxy class implementing 3 or more interfaces
Regards, Peter
P.S. Details:
32 bit addressing:
** Original j.l.r.Proxy
** 0 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 400 400
1 1 760 360
2 9 1072 312
-------- -------- -------- --------
** Original j.l.r.Proxy
** 1 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 400 400
1 1 768 368
1 2 920 152
1 3 1072 152
1 4 1224 152
1 5 1376 152
1 6 1528 152
1 7 1680 152
1 8 1832 152
2 9 2152 320
2 10 2304 152
2 11 2456 152
2 12 2672 216
2 13 2824 152
2 14 2976 152
2 15 3128 152
2 16 3280 152
-------- -------- -------- --------
** Original j.l.r.Proxy
** 2 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 400 400
1 1 768 368
1 2 920 152
1 3 1072 152
1 4 1224 152
1 5 1376 152
1 6 1528 152
1 7 1680 152
1 8 1832 152
2 9 2152 320
2 10 2304 152
2 11 2456 152
2 12 2672 216
2 13 2824 152
2 14 2976 152
2 15 3128 152
2 16 3280 152
-------- -------- -------- --------
** Original j.l.r.Proxy
** 3 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 400 400
1 1 776 376
1 2 936 160
1 3 1096 160
1 4 1256 160
1 5 1416 160
1 6 1576 160
1 7 1736 160
1 8 1896 160
2 9 2224 328
2 10 2384 160
2 11 2544 160
2 12 2768 224
2 13 2928 160
2 14 3088 160
2 15 3248 160
2 16 3408 160
-------- -------- -------- --------
** Original j.l.r.Proxy
** 4 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 400 400
1 1 776 376
1 2 936 160
1 3 1096 160
1 4 1256 160
1 5 1416 160
1 6 1576 160
1 7 1736 160
1 8 1896 160
2 9 2224 328
2 10 2384 160
2 11 2544 160
2 12 2768 224
2 13 2928 160
2 14 3088 160
2 15 3248 160
2 16 3408 160
-------- -------- -------- --------
** Patched j.l.r.Proxy
** 0 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 240 240
1 1 768 528
2 9 1072 304
-------- -------- -------- --------
** Patched j.l.r.Proxy
** 1 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 240 240
1 1 752 512
1 2 848 96
1 3 944 96
1 4 1040 96
1 5 1136 96
1 6 1232 96
1 7 1328 96
1 8 1424 96
2 9 1728 304
2 10 1824 96
2 11 1920 96
2 12 2080 160
2 13 2176 96
2 14 2272 96
2 15 2368 96
2 16 2464 96
-------- -------- -------- --------
** Patched j.l.r.Proxy
** 2 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 240 240
1 1 776 536
1 2 896 120
1 3 1016 120
1 4 1136 120
1 5 1256 120
1 6 1376 120
1 7 1496 120
1 8 1616 120
2 9 1944 328
2 10 2064 120
2 11 2184 120
2 12 2368 184
2 13 2488 120
2 14 2608 120
2 15 2728 120
2 16 2848 120
-------- -------- -------- --------
** Patched j.l.r.Proxy
** 3 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 240 240
1 1 800 560
1 2 944 144
1 3 1088 144
1 4 1232 144
1 5 1376 144
1 6 1520 144
1 7 1664 144
1 8 1808 144
2 9 2160 352
2 10 2304 144
2 11 2448 144
2 12 2656 208
2 13 2800 144
2 14 2944 144
2 15 3088 144
2 16 3232 144
-------- -------- -------- --------
** Patched j.l.r.Proxy
** 4 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 240 240
1 1 800 560
1 2 944 144
1 3 1088 144
1 4 1232 144
1 5 1376 144
1 6 1520 144
1 7 1664 144
1 8 1808 144
2 9 2160 352
2 10 2304 144
2 11 2448 144
2 12 2656 208
2 13 2800 144
2 14 2944 144
2 15 3088 144
2 16 3232 144
-------- -------- -------- --------
64 bit addressing:
** Original j.l.r.Proxy
** 0 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 632 632
1 1 1208 576
2 9 1728 520
-------- -------- -------- --------
** Original j.l.r.Proxy
** 1 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 632 632
1 1 1216 584
1 2 1448 232
1 3 1680 232
1 4 1912 232
1 5 2144 232
1 6 2376 232
1 7 2608 232
1 8 2840 232
2 9 3368 528
2 10 3600 232
2 11 3832 232
2 12 4192 360
2 13 4424 232
2 14 4656 232
2 15 4888 232
2 16 5120 232
-------- -------- -------- --------
** Original j.l.r.Proxy
** 2 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 632 632
1 1 1224 592
1 2 1464 240
1 3 1704 240
1 4 1944 240
1 5 2184 240
1 6 2424 240
1 7 2664 240
1 8 2904 240
2 9 3440 536
2 10 3680 240
2 11 3920 240
2 12 4288 368
2 13 4528 240
2 14 4768 240
2 15 5008 240
2 16 5248 240
-------- -------- -------- --------
** Original j.l.r.Proxy
** 3 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 632 632
1 1 1232 600
1 2 1480 248
1 3 1728 248
1 4 1976 248
1 5 2224 248
1 6 2472 248
1 7 2720 248
1 8 2968 248
2 9 3512 544
2 10 3760 248
2 11 4008 248
2 12 4384 376
2 13 4632 248
2 14 4880 248
2 15 5128 248
2 16 5376 248
-------- -------- -------- --------
** Original j.l.r.Proxy
** 4 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 632 632
1 1 1240 608
1 2 1496 256
1 3 1752 256
1 4 2008 256
1 5 2264 256
1 6 2520 256
1 7 2776 256
1 8 3032 256
2 9 3584 552
2 10 3840 256
2 11 4096 256
2 12 4480 384
2 13 4736 256
2 14 4992 256
2 15 5248 256
2 16 5504 256
-------- -------- -------- --------
** Patched j.l.r.Proxy
** 0 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 336 336
1 1 1216 880
2 9 1720 504
-------- -------- -------- --------
** Patched j.l.r.Proxy
** 1 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 336 336
1 1 1200 864
1 2 1352 152
1 3 1504 152
1 4 1656 152
1 5 1808 152
1 6 1960 152
1 7 2112 152
1 8 2264 152
2 9 2768 504
2 10 2920 152
2 11 3072 152
2 12 3352 280
2 13 3504 152
2 14 3656 152
2 15 3808 152
2 16 3960 152
-------- -------- -------- --------
** Patched j.l.r.Proxy
** 2 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 336 336
1 1 1232 896
1 2 1416 184
1 3 1600 184
1 4 1784 184
1 5 1968 184
1 6 2152 184
1 7 2336 184
1 8 2520 184
2 9 3056 536
2 10 3240 184
2 11 3424 184
2 12 3736 312
2 13 3920 184
2 14 4104 184
2 15 4288 184
2 16 4472 184
-------- -------- -------- --------
** Patched j.l.r.Proxy
** 3 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 336 336
1 1 1272 936
1 2 1496 224
1 3 1720 224
1 4 1944 224
1 5 2168 224
1 6 2392 224
1 7 2616 224
1 8 2840 224
2 9 3416 576
2 10 3640 224
2 11 3864 224
2 12 4216 352
2 13 4440 224
2 14 4664 224
2 15 4888 224
2 16 5112 224
-------- -------- -------- --------
** Patched j.l.r.Proxy
** 4 interfaces / proxy class
class proxy size of delta to
loaders classes caches prev.ln.
-------- -------- -------- --------
0 0 336 336
1 1 1280 944
1 2 1512 232
1 3 1744 232
1 4 1976 232
1 5 2208 232
1 6 2440 232
1 7 2672 232
1 8 2904 232
2 9 3488 584
2 10 3720 232
2 11 3952 232
2 12 4312 360
2 13 4544 232
2 14 4776 232
2 15 5008 232
2 16 5240 232
-------- -------- -------- --------
On 04/20/2013 09:31 AM, Peter Levart wrote:
> Hi Mandy,
>
> I have another idea. Before jumping to implement it, I will first ask
> what do you think of it. For example:
>
> - have an optimal interface names key calculated from interfaces.
> - visibility of interfaces and other validations are pushed to
> slow-path (inside ProxyClassFactory.apply)
> - the proxy Class object returned from WeakCache.get() is
> post-validated with a check like:
>
> for (Class<?> intf : interfaces) {
> if (!intf.isAssignableFrom(proxyClass)) {
> throw new IllegalArgumentException();
> }
> }
> // return post-validated proxyClass from getProxyClass0()...
>
> I feel that Class.isAssignableFrom(Class) check could be much faster
> and that the only reason the check can fail is if some interface is
> not visible from the class loader.
>
> Am I correct?
>
> Regards, Peter
>
>
>
> On 04/19/2013 04:36 PM, Peter Levart wrote:
>> Hi Mandy,
>>
>> On 04/19/2013 07:33 AM, Mandy Chung wrote:
>>>>
>>>> https://dl.dropboxusercontent.com/u/101777488/jdk8-tl/proxy-wc/webrev.02/index.html
>>>>
>>>> What about package-private in java.lang.reflect? It makes Proxy
>>>> itself much easier to read. When we decide which way to go, I can
>>>> remove the interface and only leave a single package-private class...
>>>>
>>>
>>> thanks. Moving it to a single package-private classin
>>> java.lang.reflectand remove the interface sounds good.
>>
>> Right.
>>
>>>
>>> I have merged your patch with the recent TL repo and did some clean
>>> up while reviewing it. Some comments:
>>> 1. getProxyClass0 should validate the input interfaces and throw IAE
>>> if any illegal argument (e.g. interfaces are not visible to the
>>> given loader) before calling proxyClassCache.get(loader,
>>> interfaces). I moved back the validation code from
>>> ProxyClassFactory.apply to getProxyClass0.
>>
>> Ops, you're right. There could be a request with interface(s) with
>> same name(s) but loaded by different loader(s) and such code could
>> return wrong pre-cached proxy class instead of throwing exception.
>> Unfortunately, moving validation to slow-path was the cause of major
>> performance and scalability improvement observed. With validation
>> moved back to getProxyClass0 (in spite of using two-level WeakCache),
>> we have the following performance (WeakCache#1):
>>
>>
>> Summary (4 Cores x 2 Threads i7 CPU):
>>
>> Test Threads ns/op Original WeakCache#1
>> ======================= ======= ============== ===========
>> Proxy_getProxyClass 1 2,403.27 2,174.51
>> 4 3,039.01 2,555.00
>> 8 5,193.58 4,273.42
>>
>> Proxy_isProxyClassTrue 1 95.02 43.14
>> 4 2,266.29 43.23
>> 8 4,782.29 72.06
>>
>> Proxy_isProxyClassFalse 1 95.02 1.36
>> 4 2,186.59 1.36
>> 8 4,891.15 2.72
>>
>> Annotation_equals 1 240.10 195.68
>> 4 1,864.06 201.41
>> 8 8,639.20 337.46
>>
>> It's a little better than original getProxyClass(), but not much. The
>> isProxyClass() and consequently Annotation.equals() are far better
>> though. But as you might have guessed, I kind of solved that too...
>>
>> My first attempt was to optimize the interface validation. Only the
>> "visibility" part is necessary to be performed on fast-path.
>> Uniqueness and other things can be performed on slow-path. With
>> split-validation and hacks like:
>>
>> private static final MethodHandle findLoadedClass0MH,
>> findBootstrapClassMH;
>> private static final ClassLoader dummyCL = new ClassLoader() {};
>>
>> static {
>> try {
>> Method method =
>> ClassLoader.class.getDeclaredMethod("findLoadedClass0", String.class);
>> method.setAccessible(true);
>> findLoadedClass0MH =
>> MethodHandles.lookup().unreflect(method);
>>
>> method =
>> ClassLoader.class.getDeclaredMethod("findBootstrapClass", String.class);
>> method.setAccessible(true);
>> findBootstrapClassMH =
>> MethodHandles.lookup().unreflect(method);
>> } catch (NoSuchMethodException e) {
>> throw (Error) new
>> NoSuchMethodError(e.getMessage()).initCause(e);
>> } catch (IllegalAccessException e) {
>> throw (Error) new
>> IllegalAccessError(e.getMessage()).initCause(e);
>> }
>> }
>>
>> static Class<?> findLoadedClass(ClassLoader loader, String name) {
>> try {
>> if (VM.isSystemDomainLoader(loader)) {
>> return (Class<?>)
>> findBootstrapClassMH.invokeExact(dummyCL, name);
>> } else {
>> return (Class<?>)
>> findLoadedClass0MH.invokeExact(loader, name);
>> }
>> } catch (RuntimeException | Error e) {
>> throw e;
>> } catch (Throwable t) {
>> throw new UndeclaredThrowableException(t);
>> }
>> }
>>
>>
>> ... using findLoadedClass(loader, intf.getName()) and only doing
>> Class.forName(intf.getName(), false, loader) if the former returned
>> null ... I managed to reclaim some performance (WeakCache#1+):
>>
>>
>> Test Threads ns/op Original WeakCache#1
>> WeakCache#1+
>> ======================= ======= ============== ===========
>> ============
>> Proxy_getProxyClass 1 2,403.27 2,174.51 1,589.36
>> 4 3,039.01 2,555.00 1,929.11
>> 8 5,193.58 4,273.42 3,409.77
>>
>>
>> ...but that was still not very satisfactory.
>>
>> I modified the KeyFactory to create keys that weakly-reference
>> interface Class objects and implement hashCode/equals in terms of
>> comparing those Class objects. With such keys, no false aliasing can
>> occur and the whole validation can be pushed back to slow-path. I
>> tried hard to create keys with as little space overhead as possible:
>>
>> http://dl.dropboxusercontent.com/u/101777488/jdk8-tl/proxy-wc-wi/webrev.01/index.html
>>
>>
>> ...but there can be no miracles. The good news is that the
>> performance is back (WeakCache#2):
>>
>>
>> Summary (4 Cores x 2 Threads i7 CPU):
>>
>> Test Threads ns/op Original WeakCache#1 WeakCache#2
>> ======================= ======= ============== =========== ===========
>> Proxy_getProxyClass 1 2,403.27 2,174.51 163.57
>> 4 3,039.01 2,555.00 211.70
>> 8 5,193.58 4,273.42 322.14
>>
>> Proxy_isProxyClassTrue 1 95.02 43.14 41.23
>> 4 2,266.29 43.23 42.20
>> 8 4,782.29 72.06 72.21
>>
>> Proxy_isProxyClassFalse 1 95.02 1.36 1.36
>> 4 2,186.59 1.36 1.36
>> 8 4,891.15 2.72 2.72
>>
>> Annotation_equals 1 240.10 195.68 194.61
>> 4 1,864.06 201.41 198.81
>> 8 8,639.20 337.46 342.90
>>
>>
>> ... and the most common usage (proxy class implementing exactly one
>> interface) uses even less space than with interface-names-key - 16
>> bytes saved per proxy class vs. 8 bytes saved (32 bit addressing mode):
>>
>> --------------------------------------
>> Original j.l.r.Proxy
>> 1 interfaces / proxy class
>>
>> class proxy size of delta to
>> loaders classes caches prev.ln.
>> -------- -------- -------- --------
>> 0 0 400 400
>> 1 1 768 368
>> 1 2 920 152
>> 1 3 1072 152
>> 1 4 1224 152
>> 1 5 1376 152
>> 1 6 1528 152
>> 1 7 1680 152
>> 1 8 1832 152
>> 2 9 2152 320
>> 2 10 2304 152
>> 2 11 2456 152
>> 2 12 2672 216
>> 2 13 2824 152
>> 2 14 2976 152
>> 2 15 3128 152
>> 2 16 3280 152
>>
>> --------------------------------------
>> Patched j.l.r.Proxy
>> 1 interfaces / proxy class
>>
>> class proxy size of delta to
>> loaders classes caches prev.ln.
>> -------- -------- -------- --------
>> 0 0 240 240
>> 1 1 792 552
>> 1 2 928 136
>> 1 3 1064 136
>> 1 4 1200 136
>> 1 5 1336 136
>> 1 6 1472 136
>> 1 7 1608 136
>> 1 8 1744 136
>> 2 9 2088 344
>> 2 10 2224 136
>> 2 11 2360 136
>> 2 12 2560 200
>> 2 13 2696 136
>> 2 14 2832 136
>> 2 15 2968 136
>> 2 16 3104 136
>>
>>
>> Did you know, that Proxy.getProxyClass() can generate proxy classes
>> implementing 0 interfaces? It can. There's exactly one such class
>> generated per class loader:
>>
>>
>> --------------------------------------
>> Original j.l.r.Proxy
>> 0 interfaces / proxy class
>>
>> class proxy size of delta to
>> loaders classes caches prev.ln.
>> -------- -------- -------- --------
>> 0 0 400 400
>> 1 1 760 360
>> 2 2 1072 312
>>
>> --------------------------------------
>> Patched j.l.r.Proxy
>> 0 interfaces / proxy class
>>
>> class proxy size of delta to
>> loaders classes caches prev.ln.
>> -------- -------- -------- --------
>> 0 0 240 240
>> 1 1 728 488
>> 2 2 1040 312
>>
>>
>> With 2 or more interfaces implemented by proxy class the space
>> overhead increases faster than with original Proxy:
>>
>>
>> --------------------------------------
>> Original j.l.r.Proxy
>> 2 interfaces / proxy class
>>
>> class proxy size of delta to
>> loaders classes caches prev.ln.
>> -------- -------- -------- --------
>> 0 0 400 400
>> 1 1 768 368
>> 1 2 920 152
>> 1 3 1072 152
>> 1 4 1224 152
>> 1 5 1376 152
>> 1 6 1528 152
>> 1 7 1680 152
>> 1 8 1832 152
>> 2 9 2152 320
>> 2 10 2304 152
>> 2 11 2456 152
>> 2 12 2672 216
>> 2 13 2824 152
>> 2 14 2976 152
>> 2 15 3128 152
>> 2 16 3280 152
>>
>> --------------------------------------
>> Patched j.l.r.Proxy
>> 2 interfaces / proxy class
>>
>> class proxy size of delta to
>> loaders classes caches prev.ln.
>> -------- -------- -------- --------
>> 0 0 240 240
>> 1 1 832 592
>> 1 2 1008 176
>> 1 3 1184 176
>> 1 4 1360 176
>> 1 5 1536 176
>> 1 6 1712 176
>> 1 7 1888 176
>> 1 8 2064 176
>> 2 9 2448 384
>> 2 10 2624 176
>> 2 11 2800 176
>> 2 12 3040 240
>> 2 13 3216 176
>> 2 14 3392 176
>> 2 15 3568 176
>> 2 16 3744 176
>>
>> --------------------------------------
>> Original j.l.r.Proxy
>> 3 interfaces / proxy class
>>
>> class proxy size of delta to
>> loaders classes caches prev.ln.
>> -------- -------- -------- --------
>> 0 0 400 400
>> 1 1 776 376
>> 1 2 936 160
>> 1 3 1096 160
>> 1 4 1256 160
>> 1 5 1416 160
>> 1 6 1576 160
>> 1 7 1736 160
>> 1 8 1896 160
>> 2 9 2224 328
>> 2 10 2384 160
>> 2 11 2544 160
>> 2 12 2768 224
>> 2 13 2928 160
>> 2 14 3088 160
>> 2 15 3248 160
>> 2 16 3408 160
>>
>> --------------------------------------
>> Patched j.l.r.Proxy
>> 3 interfaces / proxy class
>>
>> class proxy size of delta to
>> loaders classes caches prev.ln.
>> -------- -------- -------- --------
>> 0 0 240 240
>> 1 1 864 624
>> 1 2 1072 208
>> 1 3 1280 208
>> 1 4 1488 208
>> 1 5 1696 208
>> 1 6 1904 208
>> 1 7 2112 208
>> 1 8 2320 208
>> 2 9 2736 416
>> 2 10 2944 208
>> 2 11 3152 208
>> 2 12 3424 272
>> 2 13 3632 208
>> 2 14 3840 208
>> 2 15 4048 208
>> 2 16 4256 208
>>
>> --------------------------------------
>> Original j.l.r.Proxy
>> 4 interfaces / proxy class
>>
>> class proxy size of delta to
>> loaders classes caches prev.ln.
>> -------- -------- -------- --------
>> 0 0 400 400
>> 1 1 776 376
>> 1 2 936 160
>> 1 3 1096 160
>> 1 4 1256 160
>> 1 5 1416 160
>> 1 6 1576 160
>> 1 7 1736 160
>> 1 8 1896 160
>> 2 9 2224 328
>> 2 10 2384 160
>> 2 11 2544 160
>> 2 12 2768 224
>> 2 13 2928 160
>> 2 14 3088 160
>> 2 15 3248 160
>> 2 16 3408 160
>>
>> --------------------------------------
>> Patched j.l.r.Proxy
>> 4 interfaces / proxy class
>>
>> class proxy size of delta to
>> loaders classes caches prev.ln.
>> -------- -------- -------- --------
>> 0 0 240 240
>> 1 1 896 656
>> 1 2 1136 240
>> 1 3 1376 240
>> 1 4 1616 240
>> 1 5 1856 240
>> 1 6 2096 240
>> 1 7 2336 240
>> 1 8 2576 240
>> 2 9 3024 448
>> 2 10 3264 240
>> 2 11 3504 240
>> 2 12 3808 304
>> 2 13 4048 240
>> 2 14 4288 240
>> 2 15 4528 240
>> 2 16 4768 240
>>
>>
>> There's an increase of 8 bytes per proxy class key for each 2
>> interfaces added to proxy class in original Proxy code, but there's
>> an increase of 32 bytes per proxy class key for each single interface
>> added in patched Proxy code.
>>
>> I think the most common usage is to implement a single interface and
>> there is 16 bytes gained for each such usage compared to original
>> Proxy code.
>>
>>> 2. I did some cleanup to restore some original comments to make the
>>> diffs clearer where the change is.
>>> 3. I removed the newInstance method which is dead code after my
>>> previous code. Since we are in this code, I took the chance to
>>> clean that up and also change a couple for-loop to use for-each.
>>>
>>> I have put the merged and slightly modified Proxy.java and webrev at:
>>> http://cr.openjdk.java.net/~mchung/jdk8/webrevs/7123493/webrev.00/
>>>
>>> We will use this bug for your contribution:
>>> 7123493 : (proxy) Proxy.getProxyClass doesn't scale under high load
>>
>> I took j.l.r.Proxy file from your webrev and just changed the
>> KeyFactory implementation. WeakCache is generic and can be used
>> unchanged with either implementation of KeyFactory.
>>
>>>
>>> For the weak cache class, since it's for proxy implementation use, I
>>> suggest to take out the supportContainsValueOperation flagas it
>>> always keeps the reverse map for isProxyClass lookup.
>>>
>>> You can simply call Objects.requireNonNull(param) instead of
>>> requireNonNull(param, "param-name") since the proxy implementation
>>> should have made sure the argument is non-null.
>>>
>>> Formatting nits:
>>>
>>> 68 Object cacheKey = CacheKey.valueOf(
>>> 69 key,
>>> 70 refQueue
>>> 71 );
>>>
>>> should be: all in one line or line break on a long-line. Same for
>>> method signature.
>>>
>>> 237 void expungeFrom(
>>> 238 ConcurrentMap<?, ? extends ConcurrentMap<?, ?>> map,
>>> 239 ConcurrentMap<?, Boolean> reverseMap
>>> 240 );
>>>
>>> should be:
>>>
>>> void expungeFrom(ConcurrentMap<?, ? extends ConcurrentMap<?, ?>> map,
>>> ConcurrentMap<?, Boolean> reverseMap);
>>>
>>> so that it'll be more consistent with the existing code. I'll do a
>>> detailed review on the weak cache class as you will finalize the code
>>> per the decision to go with the two-level weak cache.
>>
>> I hope I have addressed all that in above webrev.
>>
>> Regards, Peter
>>
>>>
>>> Thanks again for the good work.
>>>
>>> Mandy
>>> [1] http://openjdk.java.net/jeps/161
>>
>
More information about the core-libs-dev
mailing list