या तो प्रस्तुति बिल्कुल सटीक नहीं थी, या आपको यह सही नहीं मिला।
वास्तव में, जेवीएम इनलाइन गैर-स्थैतिक तरीकों, varargs के साथ भी कर सकते हैं। इसके अलावा, यह कुछ मामलों में संबंधित Object[]
सरणी के आवंटन को समाप्त कर सकता है। दुर्भाग्यवश, यह ऐसा नहीं करता है जब एक vararg विधि for
लूप का उपयोग कर सरणी पर पुनरावृत्ति करता है।
मैंने सिद्धांत को सत्यापित करने के लिए निम्नलिखित JMH बेंचमार्क बनाया और इसे GC profiler (-prof gc
) के साथ चलाया।
package bench;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.infra.Blackhole;
public class VarArgs {
@Benchmark
public void inlineNonStatic(Blackhole bh) {
inlineNonStaticVA(bh, "foo", 4, new Object());
}
@Benchmark
public void inlineStatic(Blackhole bh) {
inlineStaticVA(bh, "foo", 4, new Object());
}
@Benchmark
public void loopNonStatic(Blackhole bh) {
loopNonStaticVA(bh, "foo", 4, new Object());
}
@Benchmark
public void loopStatic(Blackhole bh) {
loopStaticVA(bh, "foo", 4, new Object());
}
public void inlineNonStaticVA(Blackhole bh, Object... args) {
if (args.length > 0) bh.consume(args[0]);
if (args.length > 1) bh.consume(args[1]);
if (args.length > 2) bh.consume(args[2]);
if (args.length > 3) bh.consume(args[3]);
}
public static void inlineStaticVA(Blackhole bh, Object... args) {
if (args.length > 0) bh.consume(args[0]);
if (args.length > 1) bh.consume(args[1]);
if (args.length > 2) bh.consume(args[2]);
if (args.length > 3) bh.consume(args[3]);
}
public void loopNonStaticVA(Blackhole bh, Object... args) {
for (Object arg : args) {
bh.consume(arg);
}
}
public static void loopStaticVA(Blackhole bh, Object... args) {
for (Object arg : args) {
bh.consume(arg);
}
}
}
-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining
पता चलता है कि सभी 4 वेरिएंट सफलतापूर्वक फोन करने वाले में inlined रहे हैं:
@ 28 bench.VarArgs::inlineNonStaticVA (52 bytes) inline (hot)
@ 27 bench.VarArgs::inlineStaticVA (52 bytes) inline (hot)
@ 28 bench.VarArgs::loopNonStaticVA (35 bytes) inline (hot)
@ 27 bench.VarArgs::loopStaticVA (33 bytes) inline (hot)
परिणामों की पुष्टि बनाम गैर स्थिर तरीकों स्थिर बुला के बीच कोई प्रदर्शन अंतर नहीं है।
Benchmark Mode Cnt Score Error Units
VarArgs.inlineNonStatic avgt 20 9,606 ± 0,076 ns/op
VarArgs.inlineStatic avgt 20 9,604 ± 0,040 ns/op
VarArgs.loopNonStatic avgt 20 14,188 ± 0,154 ns/op
VarArgs.loopStatic avgt 20 14,147 ± 0,059 ns/op
हालांकि, जीसी प्रोफाइलर इंगित करता है कि vararg Object[]
सरणी inline*
तरीकों के लिए loop*
तरीकों के लिए आवंटित किया जाता है, लेकिन नहीं।
Benchmark Mode Cnt Score Error Units
VarArgs.inlineNonStatic:·gc.alloc.rate.norm avgt 20 16,000 ± 0,001 B/op
VarArgs.inlineStatic:·gc.alloc.rate.norm avgt 20 16,000 ± 0,001 B/op
VarArgs.loopNonStatic:·gc.alloc.rate.norm avgt 20 48,000 ± 0,001 B/op
VarArgs.loopStatic:·gc.alloc.rate.norm avgt 20 48,000 ± 0,001 B/op
मुझे लगता है कि मूल बिंदु यह था कि स्थैतिक विधियां हमेशा मोनोमोर्फिक होती हैं। हालांकि, यदि विशेष कॉल साइट में बहुत से वास्तविक रिसीवर नहीं हैं तो JVM पॉलिमॉर्फिक तरीकों को भी रेखांकित कर सकता है।
आप कैसे सुनिश्चित करना चाहते हैं कि यह विधि 'स्थैतिक' नहीं है तो यह विधि अतिरंजित नहीं हुई है? (और यह 'निजी' या 'अंतिम' नहीं है) – Tom
@ टॉम: जेवीएम * जानता है * क्या एक विधि ओवरराइड हो गई है। अगर हर भारित वर्ग जानता है। – Holger