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

Peter Levart peter.levart at gmail.com
Thu Oct 2 20:47:45 UTC 2014


On 10/02/2014 09:28 PM, Vitaly Davidovich wrote:
> Yes, this is the version I wanted to see (i.e. where the only diff is 
> varargs, and not any anything else like array iteration, etc).
> Why did fillCopyLoop() get some much worse than in your prior email 
> though?

82050640.406  (+-4055652.247) vs. 82395900.795  (+-2794747.540)

I don't see a noticeable difference (there's a lot of jitter - didn't 
turn off tiered compilation).

Regards, Peter

>
>
>
> On Thu, Oct 2, 2014 at 3:12 PM, Peter Levart <peter.levart at gmail.com 
> <mailto:peter.levart at gmail.com>> wrote:
>
>     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/da829a8b/attachment-0001.html>


More information about the mlvm-dev mailing list