मेरा अंतिम लक्ष्य मानक जावा संग्रहों का उपयोग आधार रेखा के रूप में करते हुए कई जावा आदिम संग्रह पुस्तकालयों के लिए बेंचमार्क का एक व्यापक सेट बनाना है। अतीत में मैंने इन प्रकार के माइक्रो-बेंचमार्क लिखने की लूपिंग विधि का उपयोग किया है। मैंने फ़ंक्शन लगाया है, मैं एक लूप में बेंचमार्किंग कर रहा हूं और 1 मिलियन + बार फिर से चलाता हूं ताकि जिट को गर्म करने का मौका मिले। मैं लूप का कुल समय लेता हूं और फिर पुनरावृत्ति की संख्या से विभाजित करता हूं ताकि अनुमान लगाया जा सके कि फ़ंक्शन में एक ही कॉल के लिए मैं बेंचमार्किंग कर रहा हूं। हाल ही में JMH परियोजना और विशेष रूप से इस उदाहरण के बारे में पढ़ने के बाद: JMHSample_11_Loops मुझे इस दृष्टिकोण के साथ समस्या दिखाई देती है।बेंचमार्किंग जावा हैश मैप गेट (जेएमएच बनाम लूपिंग)
मेरे मशीन:
:public static void main(String[] args) {
HashMap<Long, Long> hmap = new HashMap<Long, Long>();
long val = 0;
//populating the hashmap
for (long idx = 0; idx < 10000000; idx++) {
hmap.put(idx, idx);
}
Stopwatch s = Stopwatch.createStarted();
long x = 0;
for (long idx = 0; idx < 10000000; idx++) {
x = hmap.get(idx);
}
s.stop();
System.out.println(s); //5.522 s
System.out.println(x); //9999999
//5.522 seconds/10000000 = 552.2 nanoseconds
}
यहाँ इस बेंचमार्क को फिर से लिखने में मेरी प्रयास JMH उपयोग कर रहा है:
Windows 7 64-bit
Core i7-2760QM @ 2.40 GHz
8.00 GB Ram
jdk1.7.0_45 64-bit
यहाँ ऊपर वर्णित पाशन विधि कोड के नीचे छीन सरल उदाहरण है
package com.test.benchmarks;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
@State(Scope.Thread)
public class MyBenchmark {
private HashMap<Long, Long> hmap = new HashMap<Long, Long>();
private long key;
@Setup(Level.Iteration)
public void setup(){
key = 0;
for(long i = 0; i < 10000000; i++) {
hmap.put(i, i);
}
}
@Benchmark
@BenchmarkMode(Mode.SampleTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public long testGetExistingKey() throws InterruptedException{
if(key >= 10000000) key=0;
return hmap.get(key++);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(".*" + MyBenchmark.class.getSimpleName() + ".*")
.warmupIterations(5)
.measurementIterations(25)
.forks(1)
.build();
new Runner(opt).run();
}
}
यहां परिणाम हैं:
Result: 31.163 ±(99.9%) 11.732 ns/op [Average]
Statistics: (min, avg, max) = (0.000, 31.163, 939008.000), stdev = 1831.428
Confidence interval (99.9%): [19.431, 42.895]
Samples, N = 263849
mean = 31.163 ±(99.9%) 11.732 ns/op
min = 0.000 ns/op
p(0.0000) = 0.000 ns/op
p(50.0000) = 0.000 ns/op
p(90.0000) = 0.000 ns/op
p(95.0000) = 427.000 ns/op
p(99.0000) = 428.000 ns/op
p(99.9000) = 428.000 ns/op
p(99.9900) = 856.000 ns/op
p(99.9990) = 9198.716 ns/op
p(99.9999) = 939008.000 ns/op
max = 939008.000 ns/op
# Run complete. Total time: 00:02:07
Benchmark Mode Samples Score Score error Units
c.t.b.MyBenchmark.testGetExistingKey sample 263849 31.163 11.732 ns/op
जहां तक मेरा बता सकते हैं, JMH में एक ही बेंचमार्क hashmap नैनोसेकंड बनाम पाशन परीक्षण के लिए नैनोसेकंड में हो जाता है है। 31 नैनोसेकंड मेरे लिए थोड़ा तेज़ लगता है। Latency Numbers Every Programmer Should Know पर एक मुख्य मेमोरी संदर्भ लगभग 100 नैनोसेकंड है। एल 2 कैश संदर्भ लगभग 7 नैनोसेकंड है, लेकिन हैश मैप 10 मिलियन लंबी चाबियाँ और मानों के साथ अच्छी तरह से एल 2 से अधिक है। इसके अलावा जेएमएच परिणाम मेरे लिए अजीब लगते हैं। 9 0% कॉल कॉल 0.0 नैनोसेकंड लेते हैं?
मुझे लगता है कि यह उपयोगकर्ता त्रुटि है। किसी भी मदद/पॉइंटर्स की सराहना की जाएगी। धन्यवाद।
अद्यतन
यहाँ AverageTime
रन करने से परिणाम हैं। यह मेरी अपेक्षाओं के साथ बहुत अधिक है। धन्यवाद @ ओलेग-एस्टेखिन! नीचे दी गई टिप्पणियों में मैंने उल्लेख किया है कि मैंने पहले AverageTime
परीक्षण किया था और SampleTime
के समान परिणाम थे। मुझे विश्वास है कि उस दौड़ में मैंने बहुत कम प्रविष्टियों के साथ हैश मैप का इस्तेमाल किया था और तेज लुकअप को समझ में आया था।
Result: 266.306 ±(99.9%) 139.359 ns/op [Average]
Statistics: (min, avg, max) = (27.266, 266.306, 1917.271), stdev = 410.904
Confidence interval (99.9%): [126.947, 405.665]
# Run complete. Total time: 00:07:17
Benchmark Mode Samples Score Score error Units
c.t.b.MyBenchmark.testGetExistingKey avgt 100 266.306 139.359 ns/op
प्रतिक्रिया के लिए धन्यवाद! मैंने आपके द्वारा वर्णित लेख पढ़ा है। वास्तव में अच्छी तरह से लिखा है। मुझे रूसी सीखने की ज़रूरत नहीं है इसलिए मैं अपने अधिक (Aleksey Shipilёv) काम पढ़ सकता हूं। लेख से, विंडोज मशीनों के बारे में बात करते हुए: "ऐसा लगता है कि हमारे पास केवल 370 एनएस परिशुद्धता है"। क्या यह एक संभावित स्पष्टीकरण हो सकता है कि ऐसा क्यों लगता है कि यह समय केवल मेरी मशीन पर दिखाया गया है जो 400ns से अधिक है? मैंने वास्तव में 'औसत समय' मोड में परीक्षण चलाने शुरू कर दिए और इसी तरह के परिणाम थे। 'नमूना समय' मोड क्या हो रहा था में अधिक अंतर्दृष्टि प्रदान करने के लिए प्रतीत होता है। मैं परीक्षण और जवाब दोबारा शुरू करूंगा। – Jon
मेरे काम कंप्यूटर पर नैनोटाइम सटीक 450 एनएस पर भी अधिक है। और निश्चित रूप से यह आपको प्राप्त होने वाले संभावित समय मूल्यों को सीधे प्रभावित करता है। –
क्या मुझे ग्रैन्युलरिटी को शोर में बदलने के लिए बैचमार्क बैच आकार सुविधा का उपयोग करना चाहिए? क्या वह उस सुविधा के लिए वैध उपयोग केस है? जेएमएच नमूने में इसका उपयोग इस प्रकार किया जाता है: "कभी-कभी आपको ऑपरेशन का मूल्यांकन करने की आवश्यकता होती है जिसमें स्थिर स्थिति नहीं होती है। बेंचमार्क किए गए ऑपरेशन की लागत में आमंत्रण से आमंत्रण में काफी भिन्नता हो सकती है।" – Jon