[PATCH] Enhancement proposal for usage of Method::getParameterTypes
Сергей Цыпанов
sergei.tsypanov at yandex.ru
Wed Nov 13 23:24:25 UTC 2019
Hello,
thanks for quick review!
Tagir Valeev from JetBrains comes with suggestion to improve compiler optimizations here https://youtrack.jetbrains.com/issue/IDEA-226474.
Rationale: in fact the cloned array could be a subject of allocation erasure as any property dereferenced from it can be dereferenced from original array:
Consider this test:
@Test
void join() {
final Object[] objects = new Object[3];
objects[0] = "azaza";
objects[1] = 365;
objects[2] = 9876L;
final Object[] clone = objects.clone();
assertEquals(objects.length, clone.length);
assertSame(objects[0], clone[0]);
assertSame(objects[1], clone[1]);
assertSame(objects[2], clone[2]);
}
Optimizing compiler could drop allocation of clone and substitute its usage with original array, but as previous benchmark demonstrates it doesn't do that at least on JDK 11.
Is there a way I can develop a patch for compiler and is this mailing list is appropriate place to discuss compiler issues?
Regards,
Sergey Tsypanov
09.11.2019, 01:15, "Claes Redestad" <claes.redestad at oracle.com>:
> Hi,
>
> some or all of these were pointed out as part of
> https://bugs.openjdk.java.net/browse/JDK-8029019
>
> There was a patch out for review early 2017. I'm not sure what happened
> to that?
>
> Either way I think it might make sense to get this small and trivial
> enhancement separated out and fixed.
>
> Thanks!
>
> /Claes
>
> On 2019-11-08 23:04, Сергей Цыпанов wrote:
>> Hello,
>>
>> it seems like Method.getParameterTypes() is often misused in JDK (and beyond): array returned from the method is used only to acquire number of method params by retrieving array.length.
>> The problem here is that Method.getPatameterTypes() clones underlying array and returns the copy.
>> Instead we can use Method.getParameterCount() which doesn't allocate any additional memory but returns directly the length of underlying array.
>>
>> To measure probable performance difference I've created a benchmark for the most simple case when tested method has no parameters:
>>
>> @State(Scope.Thread)
>> @BenchmarkMode(Mode.AverageTime)
>> @OutputTimeUnit(TimeUnit.NANOSECONDS)
>> public class MethodToStringBenchmark {
>> private Method method;
>>
>> @Setup
>> public void setup() throws Exception { method = getClass().getMethod("toString"); }
>>
>> @Benchmark
>> public int getParameterCount() { return method.getParameterCount(); }
>>
>> @Benchmark
>> public int getParameterTypes() { return method.getParameterTypes().length; }
>> }
>>
>> on my i7-7700 with JDK 11 it produces these results:
>>
>> Benchmark Mode Cnt Score Error Units
>>
>> MethodToStringBenchmark.getParameterCount avgt 25 2,528 ± 0,085 ns/op
>> MethodToStringBenchmark.getParameterCount:·gc.alloc.rate avgt 25 ≈ 10⁻⁴ MB/sec
>> MethodToStringBenchmark.getParameterCount:·gc.alloc.rate.norm avgt 25 ≈ 10⁻⁷ B/op
>> MethodToStringBenchmark.getParameterCount:·gc.count avgt 25 ≈ 0 counts
>>
>> MethodToStringBenchmark.getParameterTypes avgt 25 7,299 ± 0,410 ns/op
>> MethodToStringBenchmark.getParameterTypes:·gc.alloc.rate avgt 25 1999,454 ± 89,929 MB/sec
>> MethodToStringBenchmark.getParameterTypes:·gc.alloc.rate.norm avgt 25 16,000 ± 0,001 B/op
>> MethodToStringBenchmark.getParameterTypes:·gc.churn.G1_Eden_Space avgt 25 2003,360 ± 91,537 MB/sec
>> MethodToStringBenchmark.getParameterTypes:·gc.churn.G1_Eden_Space.norm avgt 25 16,030 ± 0,045 B/op
>> MethodToStringBenchmark.getParameterTypes:·gc.churn.G1_Old_Gen avgt 25 0,004 ± 0,001 MB/sec
>> MethodToStringBenchmark.getParameterTypes:·gc.churn.G1_Old_Gen.norm avgt 25 ≈ 10⁻⁵ B/op
>> MethodToStringBenchmark.getParameterTypes:·gc.count avgt 25 2380,000 counts
>> MethodToStringBenchmark.getParameterTypes:·gc.time avgt 25 1325,000 ms
>>
>> I've prepared a small patch to replace usage of getParameterTypes() with getParameterCount() where appropriate in java.base module.
>>
>> The patch is attached.
>>
>> Regards,
>> Sergey Tsypanov
More information about the core-libs-dev
mailing list