उत्पन्न कोड पर फिर से विचार, अभी भी कुछ नहीं है कि हमारे आंखों को दिखाई है। अच्छा, यह दिलचस्प लगता है। आइए इसे ठीक से प्राप्त करें। क्या हम वर्कलोड को चिह्नित कर सकते हैं? बेशक हम -prof perfnorm
की मदद से कर सकते हैं, जो प्रति बेंचमार्क ऑप हार्डवेयर हार्डवेयर काउंटर को सामान्य करता है। चलो देखते हैं:
Benchmark Mode Cnt Score Error Units
LoopInc.directInc thrpt 15 161.875 ± 3.038 ops/ms
LoopInc.directInc:·CPI thrpt 3 0.967 ± 0.196 #/op
LoopInc.directInc:·L1-dcache-load-misses thrpt 3 0.394 ± 3.663 #/op
LoopInc.directInc:·L1-dcache-loads thrpt 3 2149.594 ± 228.166 #/op
LoopInc.directInc:·L1-dcache-store-misses thrpt 3 0.114 ± 1.001 #/op
LoopInc.directInc:·L1-dcache-stores thrpt 3 1073.666 ± 96.066 #/op
LoopInc.directInc:·L1-icache-load-misses thrpt 3 0.965 ± 22.984 #/op
LoopInc.directInc:·LLC-loads thrpt 3 0.204 ± 2.763 #/op
LoopInc.directInc:·LLC-stores thrpt 3 0.060 ± 0.633 #/op
LoopInc.directInc:·branch-misses thrpt 3 536.068 ± 43.293 #/op
LoopInc.directInc:·branches thrpt 3 3728.890 ± 220.539 #/op
LoopInc.directInc:·cycles thrpt 3 26219.146 ± 6287.590 #/op
LoopInc.directInc:·dTLB-load-misses thrpt 3 0.063 ± 0.124 #/op
LoopInc.directInc:·dTLB-loads thrpt 3 2136.942 ± 165.990 #/op
LoopInc.directInc:·dTLB-store-misses thrpt 3 0.022 ± 0.029 #/op
LoopInc.directInc:·dTLB-stores thrpt 3 1084.787 ± 417.281 #/op
LoopInc.directInc:·iTLB-load-misses thrpt 3 0.081 ± 0.333 #/op
LoopInc.directInc:·iTLB-loads thrpt 3 3.623 ± 19.955 #/op
LoopInc.directInc:·instructions thrpt 3 27114.052 ± 1843.720 #/op
LoopInc.indirectInc thrpt 15 489.164 ± 2.692 ops/ms
LoopInc.indirectInc:·CPI thrpt 3 0.281 ± 0.015 #/op
LoopInc.indirectInc:·L1-dcache-load-misses thrpt 3 0.503 ± 9.071 #/op
LoopInc.indirectInc:·L1-dcache-loads thrpt 3 2149.806 ± 369.040 #/op
LoopInc.indirectInc:·L1-dcache-store-misses thrpt 3 0.167 ± 1.370 #/op
LoopInc.indirectInc:·L1-dcache-stores thrpt 3 1073.895 ± 186.741 #/op
LoopInc.indirectInc:·L1-icache-load-misses thrpt 3 0.313 ± 1.275 #/op
LoopInc.indirectInc:·branch-misses thrpt 3 1.102 ± 0.375 #/op
LoopInc.indirectInc:·branches thrpt 3 2143.670 ± 228.475 #/op
LoopInc.indirectInc:·cycles thrpt 3 8701.665 ± 706.183 #/op
LoopInc.indirectInc:·dTLB-load-misses thrpt 3 0.020 ± 0.301 #/op
LoopInc.indirectInc:·dTLB-loads thrpt 3 2141.965 ± 135.852 #/op
LoopInc.indirectInc:·dTLB-store-misses thrpt 3 0.002 ± 0.029 #/op
LoopInc.indirectInc:·dTLB-stores thrpt 3 1070.376 ± 81.445 #/op
LoopInc.indirectInc:·iTLB-load-misses thrpt 3 0.007 ± 0.135 #/op
LoopInc.indirectInc:·iTLB-loads thrpt 3 0.310 ± 5.768 #/op
LoopInc.indirectInc:·instructions thrpt 3 30968.207 ± 3627.540 #/op
ओह, दोनों मानकों में निर्देशों की तुलनात्मक संख्या है। धीमी गति से अधिक चक्र लेते हैं (यही कारण है कि सीपीआई directInc
में भी आदर्श नहीं है; indirectInc
, हालांकि, एक करीबी आदर्श सीपीआई उत्पन्न करता है)। यदि आप संभावित कारणों पर बारीकी से देखते हैं: कई कैश याद नहीं हैं, कई टीएलबी याद नहीं करते हैं, लेकिन धीमी बेंचमार्क में बहुत सी शाखाएं याद आती हैं। अहा! अब हम जानते हैं कि जेनरेट कोड में क्या देखना है।
चलिए जेनरेट कोड फिर से देखें। -prof perfasm
आसानी से कूदता पर प्रकाश डाला गया। और फिर आप यह देखेंगे ...
directInc:
╭│ 0x00007fa0a82a50ff: jmp 0x00007fa0a82a5116
11.39% 16.90% ││ ↗ 0x00007fa0a82a5101: inc %edx ;*iinc
││ │ ; - org.openjdk.LoopInc::[email protected] (line 18)
12.52% 23.11% ││ │↗↗ 0x00007fa0a82a5103: mov %r10,0xe8(%r11) ;*invokevirtual putLong
││ │││ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 241)
12.00% 8.14% ││ │││ 0x00007fa0a82a510a: inc %r8d ;*iinc
││ │││ ; - org.openjdk.LoopInc::[email protected] (line 18)
0.03% 0.03% ││ │││ 0x00007fa0a82a510d: cmp $0x3e8,%r8d
│╰ │││ 0x00007fa0a82a5114: jge 0x00007fa0a82a50c7 ;*aload_0
│ │││ ; - org.openjdk.LoopInc::[email protected] (line 19)
0.80% 0.91% ↘ │││ 0x00007fa0a82a5116: mov 0xf0(%r11),%r10d ;*invokevirtual getInt
│││ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 222)
4.28% 1.23% │││ 0x00007fa0a82a511d: test %r10d,%r10d
╭│││ 0x00007fa0a82a5120: je 0x00007fa0a82a517b ;*ifne
││││ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 222)
2.11% 0.01% ││││ 0x00007fa0a82a5122: movabs $0x9e3779b97f4a7c15,%r10
0.01% 0.07% ││││ 0x00007fa0a82a512c: add 0xe8(%r11),%r10 ;*ladd
││││ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 242)
7.73% 1.89% ││││ 0x00007fa0a82a5133: mov %r10,%r9
1.21% 1.84% ││││ 0x00007fa0a82a5136: shr $0x21,%r9
1.90% 0.03% ││││ 0x00007fa0a82a513a: xor %r10,%r9
2.02% 0.03% ││││ 0x00007fa0a82a513d: movabs $0xff51afd7ed558ccd,%rcx
0.94% 1.82% ││││ 0x00007fa0a82a5147: imul %rcx,%r9 ;*lmul
││││ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 182)
7.01% 2.40% ││││ 0x00007fa0a82a514b: mov %r9,%rcx
││││ 0x00007fa0a82a514e: shr $0x21,%rcx
1.89% 0.70% ││││ 0x00007fa0a82a5152: xor %r9,%rcx
3.11% 2.55% ││││ 0x00007fa0a82a5155: movabs $0xc4ceb9fe1a85ec53,%r9
0.99% 1.50% ││││ 0x00007fa0a82a515f: imul %r9,%rcx
7.66% 2.89% ││││ 0x00007fa0a82a5163: shr $0x20,%rcx
3.70% 1.97% ││││ 0x00007fa0a82a5167: mov %ecx,%r9d
0.11% ││││ 0x00007fa0a82a516a: and $0x1,%r9d ;*iand
││││ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 356)
3.76% 11.13% ││││ 0x00007fa0a82a516e: cmp $0x1,%r9d
│╰││ 0x00007fa0a82a5172: je 0x00007fa0a82a5101
10.48% 16.62% │ ││ 0x00007fa0a82a5174: test %r9d,%r9d
│ ╰│ 0x00007fa0a82a5177: je 0x00007fa0a82a5103 ;*lookupswitch
│ │ ; - org.openjdk.LoopInc::[email protected] (line 19)
│ ╰ 0x00007fa0a82a5179: jmp 0x00007fa0a82a5103 ;*aload_0
│ ; - org.openjdk.LoopInc::[email protected] (line 19)
↘ 0x00007fa0a82a517b: mov $0xffffff5d,%esi
indirectInc:
0.01% 0.01% ↗ 0x00007f65588d8260: mov %edx,%r9d
0.01% │ 0x00007f65588d8263: nopw 0x0(%rax,%rax,1)
11.99% 11.38% │ 0x00007f65588d826c: data16 data16 xchg %ax,%ax ;*iconst_0
│ ; - org.openjdk.LoopInc::[email protected] (line 34)
│ 0x00007f65588d8270: mov 0xf0(%r8),%r10d ;*invokevirtual getInt
│ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 222)
│ 0x00007f65588d8277: test %r10d,%r10d
│ 0x00007f65588d827a: je 0x00007f65588d8331 ;*ifne
│ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 222)
0.01% │ 0x00007f65588d8280: movabs $0x9e3779b97f4a7c15,%r10
11.80% 11.49% │ 0x00007f65588d828a: add 0xe8(%r8),%r10 ;*ladd
│ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 242)
0.01% 0.01% │ 0x00007f65588d8291: mov %r10,0xe8(%r8) ;*invokevirtual putLong
│ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 241)
│ 0x00007f65588d8298: mov %r9d,%edx
0.01% 0.01% │ 0x00007f65588d829b: inc %edx
11.12% 12.40% │ 0x00007f65588d829d: mov %r10,%rcx
0.01% │ 0x00007f65588d82a0: shr $0x21,%rcx
0.03% │ 0x00007f65588d82a4: xor %r10,%rcx
0.06% 0.03% │ 0x00007f65588d82a7: movabs $0xff51afd7ed558ccd,%r10
12.38% 13.94% │ 0x00007f65588d82b1: imul %r10,%rcx ;*lmul
│ ; - java.util.concurrent.ThreadLocalRandom::[email protected] (line 182)
0.03% 0.01% │ 0x00007f65588d82b5: mov %rcx,%r10
│ 0x00007f65588d82b8: shr $0x21,%r10
0.03% │ 0x00007f65588d82bc: xor %rcx,%r10
11.43% 12.62% │ 0x00007f65588d82bf: movabs $0xc4ceb9fe1a85ec53,%rcx
0.01% │ 0x00007f65588d82c9: imul %rcx,%r10
0.34% 0.30% │ 0x00007f65588d82cd: shr $0x20,%r10
0.85% 0.76% │ 0x00007f65588d82d1: mov %r10d,%r10d
11.81% 11.51% │ 0x00007f65588d82d4: and $0x1,%r10d
2.16% 1.78% │ 0x00007f65588d82d8: cmp $0x1,%r10d
3.45% 3.00% │ 0x00007f65588d82dc: cmovne %r9d,%edx <----- HERE IT IS
17.55% 15.86% │ 0x00007f65588d82e0: inc %r11d ;*iinc
│ ; - org.openjdk.LoopInc::[email protected] (line 33)
│ 0x00007f65588d82e3: cmp $0x3e8,%r11d
╰ 0x00007f65588d82ea: jl 0x00007f65588d8260 ;*if_icmpge
; - org.openjdk.LoopInc::[email protected] (line 33)
सूचना jmp
के बजाय cmovne
- यही कारण है कि हम और अधिक है " अनुमानित "शाखाएं। हॉटस्पॉट शाखाओं को प्रोफाइल करता है, और शाखा प्रोफाइल शाखा बहुत सपाट होने पर सशर्त चाल को छोड़ देता है।दूसरे शब्दों में, सशर्त चाल की अतिरिक्त विलंबता के लिए थोड़ा भुगतान करके एक बहुत ही संभावित शाखा गलतफहमी चकमा दें। हालांकि, इस मामले में, स्विच विशेष है: इसमें दो विकल्प (0, 1, और "कुछ नहीं") से अधिक है। यही कारण है कि, मैं अनुमान लगाता हूं, result
वृद्धि को cmov में नहीं जोड़ा जा रहा है। (सामान्यतया, हॉटस्पॉट शून्य result
लिए "डिफ़ॉल्ट" में संग्रहीत कर सकता है, लेकिन यह यह विस्फोट से उड़ा दिया, ओह अच्छी तरह से)
कि परिकल्पना की पुष्टि के लिए, आइए directCompleteInc
मामले में, जहां हम अभी भी switch
का उपयोग करते हैं, लेकिन अब सभी को कवर किया मामलों:
@Benchmark
public int directCompleteInc() {
int result = 0;
for (int i = 0; i < 1000; i++) {
switch (getValue()) {
case 1:
result++;
break;
default:
break;
}
}
return result;
}
... और यह मापने, और इस समय किसी भी विकल्प के बिना, ओ पी पसंद आया:
Benchmark Mode Cnt Score Error Units
LoopInc.directCompleteInc thrpt 5 644.414 ± 0.371 ops/ms
LoopInc.directInc thrpt 5 174.974 ± 0.103 ops/ms
LoopInc.indirectInc thrpt 5 644.015 ± 0.533 ops/ms
वहां।
आप इसे कैसे बेंचमार्क कर रहे हैं? –
निश्चित रूप से, अपने बेंचमार्क दृष्टिकोण के साथ कुछ गड़बड़ है। प्रश्न है: क्या? – Kon
एक गर्मजोशी मुद्दा हो सकता है। अपने परीक्षणों के क्रम को वापस करने का प्रयास करें – ControlAltDel