[9] RFR (S): 8058892: FILL_ARRAYS and ARRAYS are eagely initialized in MethodHandleImpl

Peter Levart peter.levart at gmail.com
Thu Oct 2 19:12:28 UTC 2014


Well, if I add the following variant to the mix:

     private static void fillWith8Arguments(Object[] a, int pos, 
Object... args) {
         a[pos] = args[0];
         a[pos + 1] = args[1];
         a[pos + 2] = args[2];
         a[pos + 3] = args[3];
         a[pos + 4] = args[4];
         a[pos + 5] = args[5];
         a[pos + 6] = args[6];
         a[pos + 7] = args[7];
     }

     private static Object[] fillArrayByHand(
         Integer pos, Object[] a,
         Object a0, Object a1, Object a2, Object a3,
         Object a4, Object a5, Object a6, Object a7
     ) {
         fillWith8Arguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7);
         return a;
     }

     @Benchmark
     public Object[] fillByHand() {
         return fillArrayByHand(0, target, a0, a1, a2, a3, a4, a5, a6, a7);
     }

The results:

Benchmark                          Mode   Samples        Score Score 
error    Units
j.t.FillArrayTest.fillArray       thrpt         8 75994667.408 
4169836.951    ops/s
j.t.FillArrayTest.fillArrayAlt    thrpt         8 142761145.565 
7127589.095    ops/s
j.t.FillArrayTest.fillByHand      thrpt         8 141206898.861 
6435932.932    ops/s
j.t.FillArrayTest.fillCopyLoop    thrpt         8 82395900.795 
2794747.540    ops/s


...show that with fillByHand, varargs array is indeed eliminated. But 
then the "helper" method is not of any help, since it's not reusable for 
different array lengths...


Regards, Peter

On 10/02/2014 08:54 PM, Peter Levart wrote:
>
> On 10/02/2014 08:42 PM, Vitaly Davidovich wrote:
>>
>> AFIK, varargs (up to something like 64 args) should be eliminated by 
>> EA.  Peter, can you add another jmh test that uses varargs but 
>> doesn't call into System.arraycopy but uses the hand rolled version 
>> like your at method? I'm wondering if that makes EA not kick in.
>>
>
> Hm, here is a modified benchmark (I also eliminated repeatable 
> allocation of target array):
>
>
> @State(Scope.Benchmark)
> public class FillArrayTest {
>
>     private Object
>         a0 = new Object(),
>         a1 = new Object(),
>         a2 = new Object(),
>         a3 = new Object(),
>         a4 = new Object(),
>         a5 = new Object(),
>         a6 = new Object(),
>         a7 = new Object();
>
>
>     private Object[] target = new Object[8];
>
>     private static void fillWithArguments(Object[] a, int pos, 
> Object... args) {
>         System.arraycopy(args, 0, a, pos, args.length);
>     }
>
>     private static Object[] fillArray(
>         Integer pos, Object[] a,
>         Object a0, Object a1, Object a2, Object a3,
>         Object a4, Object a5, Object a6, Object a7
>     ) {
>         fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7);
>         return a;
>     }
>
>     private static void fillWithArgumentsCopyLoop(Object[] a, int pos, 
> Object... args) {
>         for (int i = 0; i < args.length; i++) {
>             a[i + pos] = args[i];
>         }
>     }
>
>     private static Object[] fillArrayCopyLoop(
>         Integer pos, Object[] a,
>         Object a0, Object a1, Object a2, Object a3,
>         Object a4, Object a5, Object a6, Object a7
>     ) {
>         fillWithArgumentsCopyLoop(a, pos, a0, a1, a2, a3, a4, a5, a6, a7);
>         return a;
>     }
>
>     private static Object[] fillArrayAlt(
>         Integer pos, Object[] a,
>         Object a0, Object a1, Object a2, Object a3,
>         Object a4, Object a5, Object a6, Object a7
>     ) {
>         int i = pos;
>         a[i++] = a0;
>         a[i++] = a1;
>         a[i++] = a2;
>         a[i++] = a3;
>         a[i++] = a4;
>         a[i++] = a5;
>         a[i++] = a6;
>         a[i++] = a7;
>         return a;
>     }
>
>     @Benchmark
>     public Object[] fillArray() {
>         return fillArray(0, target, a0, a1, a2, a3, a4, a5, a6, a7);
>     }
>
>     @Benchmark
>     public Object[] fillCopyLoop() {
>         return fillArrayCopyLoop(0, target, a0, a1, a2, a3, a4, a5, 
> a6, a7);
>     }
>
>     @Benchmark
>     public Object[] fillArrayAlt() {
>         return fillArrayAlt(0, target, a0, a1, a2, a3, a4, a5, a6, a7);
>     }
> }
>
>
>
> The results:
>
>
> Benchmark                          Mode   Samples        Score Score 
> error    Units
> j.t.FillArrayTest.fillArray       thrpt         8 76534019.978 
> 3063590.310    ops/s
> j.t.FillArrayTest.fillArrayAlt    thrpt         8 141640280.270 
> 7815152.038    ops/s
> j.t.FillArrayTest.fillCopyLoop    thrpt         8 82050640.406 
> 4055652.247    ops/s
>
>
> The fillCopyLoop seems a little faster. I don't know if this is 
> because of possible elimination of allocation. The fillArrayAlt is 
> still almost 2x as fast.
>
> Peter
>
>> Sent from my phone
>>
>> On Oct 2, 2014 2:34 PM, "Peter Levart" <peter.levart at gmail.com 
>> <mailto:peter.levart at gmail.com>> wrote:
>>
>>
>>     On 10/02/2014 06:55 PM, Vladimir Ivanov wrote:
>>
>>         Small update:
>>         http://cr.openjdk.java.net/~vlivanov/8058892/webrev.01/
>>         <http://cr.openjdk.java.net/%7Evlivanov/8058892/webrev.01/>
>>
>>         Need to reorder initialization sequence in MHI.Lazy.
>>         Initialized FILL_ARRAYS and ARRAYS are required for later MH
>>         lookups.
>>
>>         Additional testing:
>>           * jck (api/java_lang/invoke)
>>           * jdk/java/lang/invoke, jdk/java/util/streams w/ "-ea -esa"
>>         and COMPILE_THRESHOLD={0,30}
>>
>>         Best regards,
>>         Vladimir Ivanov
>>
>>
>>     Hi Vladimir,
>>
>>     I have a comment that does not directly pertain to the code
>>     changes (the initialization of arrays) but to the sub-optimal
>>     implementation of "fillArray" methods I noticed by the way. While
>>     it is nice to use varargs "makeArray" helper method with "array"
>>     methods to construct the array, the same strategy used with
>>     "fillWithArguments" in "fillArray" methods makes a redundant
>>     array that is then copied to target array and discarded. The
>>     redundant copying has a price. Here's a benchmark (Aleksey,
>>     please bear with me):
>>
>>     @State(Scope.Benchmark)
>>     public class FillArrayTest {
>>
>>         private Object
>>             a0 = new Object(),
>>             a1 = new Object(),
>>             a2 = new Object(),
>>             a3 = new Object(),
>>             a4 = new Object(),
>>             a5 = new Object(),
>>             a6 = new Object(),
>>             a7 = new Object();
>>
>>
>>         private static void fillWithArguments(Object[] a, int pos,
>>     Object... args) {
>>             System.arraycopy(args, 0, a, pos, args.length);
>>         }
>>
>>         private static Object[] fillArray(
>>             Integer pos, Object[] a,
>>             Object a0, Object a1, Object a2, Object a3,
>>             Object a4, Object a5, Object a6, Object a7
>>         ) {
>>             fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7);
>>             return a;
>>         }
>>
>>         private static Object[] fillArrayAlt(
>>             Integer pos, Object[] a,
>>             Object a0, Object a1, Object a2, Object a3,
>>             Object a4, Object a5, Object a6, Object a7
>>         ) {
>>             int i = pos;
>>             a[i++] = a0;
>>             a[i++] = a1;
>>             a[i++] = a2;
>>             a[i++] = a3;
>>             a[i++] = a4;
>>             a[i++] = a5;
>>             a[i++] = a6;
>>             a[i++] = a7;
>>             return a;
>>         }
>>
>>         @Benchmark
>>         public Object[] fillArray() {
>>             return fillArray(0, new Object[8], a0, a1, a2, a3, a4,
>>     a5, a6, a7);
>>         }
>>
>>         @Benchmark
>>         public Object[] fillArrayAlt() {
>>             return fillArrayAlt(0, new Object[8], a0, a1, a2, a3, a4,
>>     a5, a6, a7);
>>         }
>>     }
>>
>>
>>     The results on my i7 with JMH arguments "-i 8 -wi 5 -f 1 -gc true":
>>
>>     Benchmark                          Mode   Samples Score Score
>>     error    Units
>>     j.t.FillArrayTest.fillArray       thrpt         8 48601447.674
>>     5414853.634 <tel:5414853.634>    ops/s
>>     j.t.FillArrayTest.fillArrayAlt    thrpt         8 90044973.732
>>     8713725 <tel:732%208713725>.735   ops/s
>>
>>
>>     So fillArrayAlt is nearly twice as fast...
>>
>>     Regards, Peter
>>
>>
>>
>>         On 10/2/14, 7:52 PM, Vladimir Ivanov wrote:
>>
>>             http://cr.openjdk.java.net/~vlivanov/8058892/webrev.00/
>>             <http://cr.openjdk.java.net/%7Evlivanov/8058892/webrev.00/>
>>             https://bugs.openjdk.java.net/browse/JDK-8058892
>>
>>             Core j.l.i classes are preloaded during VM startup in
>>             order to avoid
>>             possible deadlock when accessing JSR292-related
>>             functionality from
>>             multiple threads. After LF sharing-related changes,
>>             FILL_ARRAYS and
>>             ARRAYS are initialized too early. It affects startup time
>>             & footprint of
>>             applications that don't use JSR292.
>>
>>             The fix is to move these fields into MHI.Lazy class, thus
>>             delaying their
>>             initialization to the first usage of JSR292 API.
>>
>>             Testing: failing test, manual (measured HelloWorld app
>>             startup time;
>>             compared -XX:+PrintCompilation logs)
>>
>>             Best regards,
>>             Vladimir Ivanov
>>
>>         _______________________________________________
>>         mlvm-dev mailing list
>>         mlvm-dev at openjdk.java.net <mailto:mlvm-dev at openjdk.java.net>
>>         http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>>
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20141002/b7279e2d/attachment.html>


More information about the mlvm-dev mailing list