मैं बहुत धीमी DataInputStream.readByte()
विधि के साथ समस्या का परीक्षण कर रहा हूं, और दिलचस्प, लेकिन समझ में आया समस्या मिली। मैं jdk1.7.0_40
, Windows 7 64 bit
का उपयोग कर रहा हूं।अजीब विधि आमंत्रण अनुकूलन समस्या
मान लें कि हमारे पास कुछ विशाल बाइट-सरणी है और इससे डेटा पढ़ रहा है। और चलो इस सरणी से बाइट-दर-बाइट पढ़ने के लिए 4 तरीकों की तुलना करते हैं: ->DataInputStream
ByteArrayInputStream
के माध्यम से पढ़ने -
- सरल पाश
ByteArrayInputStream
के माध्यम से पढ़ने के माध्यम से पढ़ने> हमारे अपनेDataInputStream
कार्यान्वयन (MyDataInputStream
)ByteArrayInputStream
के माध्यम से पढ़ना औरDataInputStream
से विधिreadByte()
की प्रतिलिपि बनाएँ।
मैं निम्नलिखित परिणाम (परीक्षण लूप पुनरावृत्ति के बाद लंबे समय तक) पाया है:
- लूप aprox ले लिया। 312446094 एनएस
DataInputStream
अपॉक्स लिया। 2555898090 एनएसMyDataInputStream
aprox लिया। "मूल" कार्यान्वयन के माध्यम से एक ही आपरेशन वस्तु विधि मंगलाचरण के माध्यम से 10 बार लंबे समय तक काम में लेते हैं, तो: २६३०६६४२९८ एनएस- विधि के माध्यम से
readByte()
प्रतिलिपि 309,265,568 एनएस
दूसरे शब्दों में, हम अजीब अनुकूलन मुद्दा है ले लिया ।
प्रश्न: क्यों?।
जानकारी के लिए:
@Test
public void testBytes1() throws IOException {
byte[] bytes = new byte[1_000_000_000];
Random r = new Random();
for (int i = 0; i < bytes.length; i++)
bytes[i] = (byte) r.nextInt();
do {
System.out.println();
bytes[r.nextInt(1_000_000_000)] = (byte) r.nextInt();
testLoop(bytes);
testDis(bytes);
testMyDis(bytes);
testViaMethod(bytes);
} while (true);
}
private void testDis(byte[] bytes) throws IOException {
long time1 = System.nanoTime();
long c = 0;
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
DataInputStream dis = new DataInputStream(bais)) {
for (int i = 0; i < bytes.length; i++) {
c += dis.readByte();
}
}
long time2 = System.nanoTime();
System.out.println("Dis: \t\t\t\t" + (time2 - time1) + "\t\t\t\t" + c);
}
private void testMyDis(byte[] bytes) throws IOException {
long time1 = System.nanoTime();
long c = 0;
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
MyDataInputStream dis = new MyDataInputStream(bais)) {
for (int i = 0; i < bytes.length; i++) {
c += dis.readByte();
}
}
long time2 = System.nanoTime();
System.out.println("My Dis: \t\t\t" + (time2 - time1) + "\t\t\t\t" + c);
}
private void testViaMethod(byte[] bytes) throws IOException {
long time1 = System.nanoTime();
long c = 0;
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)
) {
for (int i = 0; i < bytes.length; i++) {
c += readByte(bais);
}
}
long time2 = System.nanoTime();
System.out.println("Via method: \t\t" + (time2 - time1) + "\t\t\t\t" + c);
}
private void testLoop(byte[] bytes) {
long time1 = System.nanoTime();
long c = 0;
for (int i = 0; i < bytes.length; i++) {
c += bytes[i];
}
long time2 = System.nanoTime();
System.out.println("Loop: \t\t\t\t" + (time2 - time1) + "\t\t\t\t" + c);
}
public final byte readByte(InputStream in) throws IOException {
int ch = in.read();
if (ch < 0)
throw new EOFException();
return (byte)(ch);
}
static class MyDataInputStream implements Closeable {
InputStream in;
MyDataInputStream(InputStream in) {
this.in = in;
}
public final byte readByte() throws IOException {
int ch = in.read();
if (ch < 0)
throw new EOFException();
return (byte)(ch);
}
@Override
public void close() throws IOException {
in.close();
}
}
पी.एस. thoose, जो मेरे परिणामों के बारे में संदेह में है के लिए अद्यतन, इस प्रिंटआउट है, -XX:+PrintCompilation -verbose:gc -XX:CICompilerCount=1
37 1 java.lang.String::hashCode (55 bytes)
41 2 java.lang.String::charAt (29 bytes)
43 3 java.lang.String::indexOf (70 bytes)
49 4 java.lang.AbstractStringBuilder::ensureCapacityInternal (16 bytes)
52 5 java.lang.AbstractStringBuilder::append (29 bytes)
237 6 java.util.Random::nextInt (7 bytes)
237 9 n sun.misc.Unsafe::compareAndSwapLong (native)
238 7 java.util.concurrent.atomic.AtomicLong::get (5 bytes)
238 8 java.util.concurrent.atomic.AtomicLong::compareAndSet (13 bytes)
239 10 java.util.Random::next (47 bytes)
239 11 % fias.TestArrays::testBytes1 @ 15 (77 bytes)
9645 11 % fias.TestArrays::testBytes1 @ -2 (77 bytes) made not entrant
9646 12 % fias.TestArrays::testLoop @ 10 (77 bytes)
9964 12 % fias.TestArrays::testLoop @ -2 (77 bytes) made not entrant
Loop: 318726397 -500090432
9965 13 java.io.DataInputStream::readByte (23 bytes)
9966 14 s java.io.ByteArrayInputStream::read (36 bytes)
9967 15 % ! fias.TestArrays::testDis @ 37 (279 bytes)
Dis: 2684374258 -500090432
12651 16 fias.TestArrays$MyDataInputStream::readByte (23 bytes)
12652 17 % ! fias.TestArrays::testMyDis @ 37 (279 bytes)
My Dis: 2675570541 -500090432
15327 18 fias.TestArrays::readByte (20 bytes)
15328 19 % ! fias.TestArrays::testViaMethod @ 23 (179 bytes)
Via method: 2367507141 -500090432
17694 20 fias.TestArrays::testLoop (77 bytes)
17699 21 % fias.TestArrays::testLoop @ 10 (77 bytes)
Loop: 374525891 -500090567
18069 22 ! fias.TestArrays::testDis (279 bytes)
Dis: 2674626125 -500090567
20745 23 ! fias.TestArrays::testMyDis (279 bytes)
My Dis: 2671418683 -500090567
23417 24 ! fias.TestArrays::testViaMethod (179 bytes)
Via method: 2359181776 -500090567
Loop: 315081855 -500090663
Dis: 2558738649 -500090663
My Dis: 2627056034 -500090663
Via method: 311692727 -500090663
Loop: 317813286 -500090778
Dis: 2565161726 -500090778
My Dis: 2630665760 -500090778
Via method: 314594434 -500090778
Loop: 313695660 -500090797
Dis: 2568251556 -500090797
My Dis: 2635236578 -500090797
Via method: 311882312 -500090797
Loop: 316781686 -500090929
Dis: 2563535623 -500090929
My Dis: 2638487613 -500090929
Via method: 313170789 -500090929
युपीडी -2 का उपयोग कर: यहाँ benchmark और results कृपया @maaartinus द्वारा दिए गए है।
आप कहते हैं: "लूप aprox ले लिया। 312446094 एनएस "। यह असली परिणाम इस के रूप में सटीक नहीं हो सकता है, सिर्फ इसलिए कि आप वास्तव में इस अवधि के दौरान इस थ्रेड पर 50% ?, 100%?) के दौरान कितना समय चल रहे हैं और यह एक बदल सकता है बहुत सी चीज। मैं आपको इस प्रोग्राम को कई बार चलाने, स्टोर करने के समय, और एक विशिष्ट निष्पादन समय के बजाय औसत मूल्य का उपयोग करने की सलाह देता हूं। – Gwenc37
आपका बेंचमार्क उचित गर्म करने की अनुमति नहीं देता है + आपके पास परीक्षण ढांचे का ओवरहेड है जो पूर्वाग्रह हो सकता है परिणाम। आपको [उचित बेंचमार्किंग टूल] (http://stackoverflow.com/a/15787478/829571) का उपयोग करना चाहिए। – assylias
थीस के परिणाम कई टेन्स परीक्षण लूप पुनरावृत्तियों के बाद लिया जाता है। यदि आप अधिक सटीक परीक्षण की सलाह दे सकते हैं - कृपया , सुझाव दें। – Andremoniy