मुझे पता है कि जावा माइक्रोबेंचमार्क के निर्णय करना बेहद भरा है, लेकिन मुझे ऐसा कुछ दिखाई दे रहा है जो अजीब लगता है, और मैं इसके लिए कुछ स्पष्टीकरण प्राप्त करना चाहता हूं।मेरा जावा लैम्ब्डा एक डमी असाइनमेंट के बिना इसके बिना बहुत तेज़ क्यों है?
ध्यान दें कि मैं इसके लिए JMH ढांचे का उपयोग नहीं कर रहा हूं। मुझे इसके बारे में पता है, लेकिन मैं इसके लिए उस लंबाई में नहीं जाना चाहता था।
मैं पूरी कोड नमूना प्रदान करेंगे, लेकिन संक्षेप में, मैं जब मैं बहुत ही आश्चर्य परिणामों को खोजने इन दोनों तरीकों
private FooPrime[] testStreamToArray(ArrayList<Foo> fooList) {
return (FooPrime[]) fooList.stream().
map(it -> {
return new FooPrime().gamma(it.getAlpha() + it.getBeta());
}).
toArray(FooPrime[]::new);
}
private FooPrime[] testStreamToArray2(ArrayList<Foo> fooList) {
return (FooPrime[]) fooList.stream().
map(it -> {
int stuff = it.getAlpha().length();
return new FooPrime().gamma(it.getAlpha() + it.getBeta());
}).
toArray(FooPrime[]::new);
}
के प्रदर्शन का परीक्षण करें। बड़े कोड नमूने में, मैं इसे करने के चार अलग-अलग तरीकों को माप रहा हूं, और पहले तीन प्रदर्शन में बहुत करीब हैं। वे सभी प्रति पुनरावृत्ति के बारे में 50k एनएस चलाते हैं। हालांकि, दूसरा कोड नमूना लगातार उस कुल के आधे से नीचे चलाता है। ये सही है। यह धीमा नहीं है, यह काफी तेज है।
पिछले रन इस तरह संख्या पता चलता है:
manualcopy:54575 ns
toarray:53617 ns
streamtoarray:52990 ns
streamtoarray2:24217 ns
प्रत्येक रन इन के समान संख्या है।
अब मैं पूरी कक्षा और बेस क्लास प्रदान करूंगा। ध्यान दें कि मेरे पास "गर्मजोशी" पास है, जहां मैं समय शुरू करने से पहले कुछ हजार बार परीक्षण के तहत विधियों को निष्पादित करता हूं। यह भी ध्यान रखें कि यद्यपि यह "testStreamToArray2" चलाता है, फिर भी मैंने उस ब्लॉक को पहले परीक्षण में ले जाने की कोशिश की, और संख्याएं इसके बारे में बताती हैं। टिप्पणी की गई लाइनें मुझे यह समझाने के लिए हैं कि विधियां वास्तव में कुछ कर रही हैं (समय अभी भी उन पंक्तियों के समान हैं जिन पर टिप्पणी नहीं की गई है)।
package timings;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ListToArrayOfPrimesTiming {
public static void main(String[] args) {
ListToArrayOfPrimesTiming tests = new ListToArrayOfPrimesTiming(args);
tests.go();
}
public ListToArrayOfPrimesTiming(String[] args) { }
private void go() {
final ArrayList<Foo> fooList = new ArrayList<>();
for (int ctr = 0; ctr < 1000; ++ ctr) {
fooList.add(new Foo().alpha("a" + ctr).beta("b" + ctr));
}
for (int ctr = 0; ctr < 20000; ++ ctr) {
testManualCopy(fooList);
testToArray(fooList);
testStreamToArray(fooList);
testStreamToArray2(fooList);
}
int iters = 100000;
// Set<Integer> lengths = new HashSet<>();
// Set<FooPrime> distinctFooPrimes = new HashSet<>();
// lengths.clear();
// distinctFooPrimes.clear();
new TimingContainer(iters, "manualcopy", new TimingTest() {
@Override
public void run() {
FooPrime[] fooPrimeArray = testManualCopy(fooList);
// lengths.add(fooPrimeArray.length);
// distinctFooPrimes.add(fooPrimeArray[0]);
}
}).run();
// System.out.println("lengths[" + lengths + "]");
// lengths.clear();
// System.out.println("distinctFooPrimes[" + distinctFooPrimes + "]");
// distinctFooPrimes.clear();
new TimingContainer(iters, "toarray", new TimingTest() {
@Override
public void run() {
FooPrime[] fooPrimeArray = testManualCopy(fooList);
// lengths.add(fooPrimeArray.length);
// distinctFooPrimes.add(fooPrimeArray[0]);
}
}).run();
// System.out.println("lengths[" + lengths + "]");
// lengths.clear();
// System.out.println("distinctFooPrimes[" + distinctFooPrimes + "]");
// distinctFooPrimes.clear();
new TimingContainer(iters, "streamtoarray", new TimingTest() {
@Override
public void run() {
FooPrime[] fooPrimeArray = testStreamToArray(fooList);
// lengths.add(fooPrimeArray.length);
// distinctFooPrimes.add(fooPrimeArray[0]);
}
}).run();
// System.out.println("lengths[" + lengths + "]");
// lengths.clear();
// System.out.println("distinctFooPrimes[" + distinctFooPrimes + "]");
// distinctFooPrimes.clear();
new TimingContainer(iters, "streamtoarray2", new TimingTest() {
@Override
public void run() {
FooPrime[] fooPrimeArray = testStreamToArray2(fooList);
// lengths.add(fooPrimeArray.length);
// distinctFooPrimes.add(fooPrimeArray[0]);
}
}).run();
// System.out.println("lengths[" + lengths + "]");
// lengths.clear();
// System.out.println("distinctFooPrimes[" + distinctFooPrimes + "]");
// distinctFooPrimes.clear();
}
private FooPrime[] testManualCopy(ArrayList<Foo> fooList) {
FooPrime[] fooPrimeArray = new FooPrime[fooList.size()];
int index = -1;
for (Foo foo: fooList) {
++ index;
fooPrimeArray[index] = new FooPrime().gamma(foo.getAlpha() + foo.getBeta());
}
return fooPrimeArray;
}
private FooPrime[] testToArray(ArrayList<Foo> fooList) {
List<FooPrime> fooPrimeList = new ArrayList<>();
for (Foo foo: fooList) {
fooPrimeList.add(new FooPrime().gamma(foo.getAlpha() + foo.getBeta()));
}
return fooPrimeList.toArray(new FooPrime[fooList.size()]);
}
private FooPrime[] testStreamToArray(ArrayList<Foo> fooList) {
return (FooPrime[]) fooList.stream().
map(it -> {
return new FooPrime().gamma(it.getAlpha() + it.getBeta());
}).
toArray(FooPrime[]::new);
}
private FooPrime[] testStreamToArray2(ArrayList<Foo> fooList) {
return (FooPrime[]) fooList.stream().
map(it -> {
int stuff = it.getAlpha().length();
return new FooPrime().gamma(it.getAlpha() + it.getBeta());
}).
toArray(FooPrime[]::new);
}
public static FooPrime fooToFooPrime(Foo foo) {
return new FooPrime().gamma(foo.getAlpha() + foo.getBeta());
}
public static class Foo {
private String alpha;
private String beta;
public String getAlpha() { return alpha; }
public String getBeta() { return beta; }
public void setAlpha(String alpha) { this.alpha = alpha; }
public void setBeta(String beta) { this.beta = beta; }
public Foo alpha(String alpha) { this.alpha = alpha; return this; }
public Foo beta(String beta) { this.beta = beta; return this; }
}
public static class FooPrime {
private String gamma;
public String getGamma() { return gamma; }
public void setGamma(String gamma) { this.gamma = gamma; }
public FooPrime gamma(String gamma) { this.gamma = gamma; return this; }
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((gamma == null) ? 0 : gamma.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
FooPrime other = (FooPrime) obj;
if (gamma == null) {
if (other.gamma != null)
return false;
} else if (!gamma.equals(other.gamma))
return false;
return true;
}
@Override
public String toString() {
return "FooPrime [gamma=" + gamma + "]";
}
}
}
और आधार वर्ग:
package timings;
public class TimingContainer {
private int iterations;
private String label;
private TimingTest timingTest;
public TimingContainer(int iterations, String label, TimingTest timingTest) {
this.iterations = iterations;
this.label = label;
this.timingTest = timingTest;
}
public void run() {
long startTime = System.nanoTime();
for (int ctr = 0; ctr < iterations; ++ ctr) {
timingTest.randomize();
timingTest.run();
}
long endTime = System.nanoTime();
long totalns = (endTime - startTime);
System.out.println(label + ":" + (totalns/iterations) + " ns");
}
}
यदि आप 'testStreamToArray (fooList) स्विच करते हैं तो क्या होता है; ' ' testStreamToArray2 (fooList); 'आपके' 20000 पुनरावृत्ति 'में? –
या बस यह सुनिश्चित करने के लिए, अलग परीक्षण दोनों के लिए चलता है? आश्चर्य है कि अतिरिक्त लाइन कुछ अनुकूलन का कारण बन सकती है, शायद बाइटकोड में दिखाई दे सकती है? – NickL
मैंने उन्हें गर्मजोशी में बदलने की कोशिश की, कोई फर्क नहीं पड़ता। मैंने केवल streamarray2 के साथ एक रन की कोशिश की, एक ही परिणाम मिला। –