ทำไมการพิมพ์“ B” ช้ากว่าการพิมพ์“ #” มาก


2746

ฉันสร้างเมทริกซ์สองตัวของ1000x 1000:

แรกเมทริกซ์: และO ประการที่สองเมทริกซ์: และ#
OB

ใช้รหัสต่อไปนี้เมทริกซ์แรกใช้เวลา 8.52 วินาทีในการทำให้เสร็จสมบูรณ์:

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("#");
        }
    }

   System.out.println("");
 }

ด้วยรหัสนี้เมทริกซ์ที่สองใช้เวลา 259.152 วินาทีในการทำให้เสร็จสมบูรณ์:

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("B"); //only line changed
        }
    }

    System.out.println("");
}

อะไรคือเหตุผลที่อยู่เบื้องหลังช่วงเวลาที่แตกต่างกันอย่างมาก?


เป็นข้อเสนอแนะในความคิดเห็นที่พิมพ์เพียงSystem.out.print("#");ใช้เวลา7.8871ไม่กี่วินาทีในขณะที่ช่วยให้System.out.print("B");still printing...

ขณะที่คนอื่นที่ชี้ให้เห็นว่ามันใช้งานได้ตามปกติฉันลองใช้Ideone.comและโค้ดทั้งสองชิ้นทำงานด้วยความเร็วเดียวกัน

เงื่อนไขการทดสอบ:

  • ฉันรันการทดสอบนี้จากNetbeans 7.2โดยมีเอาต์พุตไปยังคอนโซล
  • ฉันใช้System.nanoTime()สำหรับการวัด

62
ลองเปลี่ยน rand.nextInt (4) == 0 ถึง i <250 เพื่อกำจัดเอฟเฟกต์ของเครื่องกำเนิดไฟฟ้าแบบสุ่ม คุณอาจหมดเอนโทรปีที่ชะลอการสร้างแบบสุ่ม
fejese

3
ทั้งคู่ดูเหมือนจะทำงานในเวลาเดียวกันบนเครื่องของฉัน ~ 4 วินาที
Sotirios Delimanolis

155
หากคุณแนะนำว่าการพิมพ์ B ต้องใช้เวลามากกว่าการพิมพ์ # .... ทำไมคุณไม่ลองพิมพ์ B & ทั้งหมด # แทนที่จะใช้ตัวแปรสุ่ม r
Kakarot

18
จากคำตอบที่ยอมรับแล้วดูเหมือนว่าคุณไม่ได้ลองรันด้วยเอาต์พุตที่เปลี่ยนเส้นทางไปยังไฟล์หรือ / dev / null
Barmar

24
@fejese, Random () ไม่ใช่ rng การเข้ารหัสลับดังนั้นไม่ต้องใช้พูลเอนโทรปี
แบ่ง

คำตอบ:


4070

การเก็งกำไรที่แท้จริงคือคุณกำลังใช้เทอร์มินัลที่พยายามทำการตัดคำแทนที่จะใช้การห่ออักขระและใช้Bเป็นอักขระคำ แต่#เป็นอักขระที่ไม่ใช่คำ ดังนั้นเมื่อถึงจุดสิ้นสุดของเส้นและค้นหาสถานที่เพื่อทำลายเส้นมันจะเห็นจุดพักที่#เกือบจะทันทีและมีความสุข ในขณะที่ด้วยBมันจะต้องค้นหาอีกต่อไปและอาจมีข้อความที่จะห่อ (ซึ่งอาจมีราคาแพงในบางขั้วเช่นเอาท์พุท backspaces จากนั้นส่งออกช่องว่างเพื่อเขียนทับตัวอักษรถูกห่อ)

แต่นั่นเป็นการเก็งกำไรที่บริสุทธิ์


559
นี่เป็นคำตอบที่ถูกต้องจริง ๆ ! การเพิ่มช่องว่างหลังจากBแก้มัน
Kuba Spatny

261
มีคำตอบบางส่วนที่มาจากประสบการณ์ที่เรียนรู้อย่างหนัก TJ และฉัน (ตั้งแต่เราเป็นเพื่อนกัน) เติบโตขึ้นในสมัยของ Apple] [และ zx80 / ​​81 ไม่มีการสร้างคำทับคำในตอนนั้น ดังนั้นเราทั้งคู่จึงลงมือเขียนของเราเอง - มากกว่าหนึ่งครั้ง และบทเรียนเหล่านั้นยังคงอยู่กับคุณพวกมันจะถูกเผาในสมองของคุณ แต่ถ้าคุณเอนโค้ดไปหลังจากนั้นเมื่อคำว่า environment ล้อมทุกอย่างหรือคุณทำมันด้วยตัวเองก่อนรันไทม์ก็ยากที่จะพบปัญหาในการตัดคำ
JockM

315
การหักที่ยอดเยี่ยม แต่เราควรพูดคุยกันจากบทเรียนนี้และวัดประสิทธิภาพด้วยการกำจัดผลลัพธ์ชี้ไปที่ / dev / null (NUL บน Windows) หรืออย่างน้อยที่สุดไปยังไฟล์ การแสดงผลบนคอนโซลประเภทใดโดยทั่วไปจะมีราคาแพงมากและมักจะบิดเบือนการกำหนดเวลา - แม้ว่าจะไม่สับสนอย่างเช่นนี้
Bob Kerns

37
@MrLister: System.out.printlnไม่ทำ wordwrapping; สิ่งที่กำลังส่งออกไปกำลังทำการตัดคำ (และการบล็อกดังนั้นSystem.out.printlnต้องรอ)
TJ Crowder

35
@ Chris - จริงฉันจะยืนยันว่าไม่ได้พิมพ์พวกเขาเป็นวิธีแก้ไขปัญหาของการกำหนดเวลาที่ถูกต้องของอัลกอริทึม ทุกครั้งที่คุณพิมพ์ไปยัง Console (ทุกประเภท) คุณจะต้องทำการประมวลผลภายนอกทุกรูปแบบโดยไม่เกี่ยวข้องกับสิ่งที่คุณกำลังทดสอบประสิทธิภาพ นั่นเป็นข้อบกพร่องในขั้นตอนการวัดของคุณบริสุทธิ์และเรียบง่าย ในทางตรงกันข้ามถ้าคุณดูปัญหาไม่ใช่การวัด แต่เข้าใจความแตกต่างใช่แล้วไม่ใช่การพิมพ์เป็นเคล็ดลับการดีบัก มันลงมาที่ปัญหาอะไรที่คุณพยายามจะแก้?
Bob Kerns

209

ฉันทำการทดสอบกับ Eclipse vs Netbeans 8.0.2 ทั้งคู่กับ Java เวอร์ชัน 1.8; ฉันใช้System.nanoTime()สำหรับการวัด

คราส:

ผมได้ในเวลาเดียวกันในทั้งสองกรณี - รอบ1.564 วินาที

NetBeans:

  • ใช้ "#": 1.536 วินาที
  • ใช้ "B": 44.164 วินาที

ดังนั้นดูเหมือนว่า Netbeans จะมีประสิทธิภาพต่ำในการพิมพ์ไปยังคอนโซล

หลังจากการวิจัยเพิ่มเติมฉันรู้ว่าปัญหาคือการตัดบรรทัดของบัฟเฟอร์สูงสุดของ Netbeans (มันไม่ได้ จำกัด อยู่แค่System.out.printlnคำสั่ง), แสดงด้วยรหัสนี้:

for (int i = 0; i < 1000; i++) {
    long t1 = System.nanoTime();
    System.out.print("BBB......BBB"); \\<-contain 1000 "B"
    long t2 = System.nanoTime();
    System.out.println(t2-t1);
    System.out.println("");
}

ผลลัพธ์เวลาน้อยกว่า 1 มิลลิวินาทีทุกการทำซ้ำยกเว้นทุก ๆ การทำซ้ำครั้งที่ห้าเมื่อผลลัพธ์เวลาประมาณ 225 มิลลิวินาที สิ่งที่ต้องการ (เป็นนาโนวินาที):

BBB...31744
BBB...31744
BBB...31744
BBB...31744
BBB...226365807
BBB...31744
BBB...31744
BBB...31744
BBB...31744
BBB...226365807
.
.
.

และอื่น ๆ ..

สรุป:

  1. Eclipse ทำงานได้อย่างสมบูรณ์กับ "B"
  2. Netbeans มีปัญหาการตัดบรรทัดที่สามารถแก้ไขได้ (เนื่องจากปัญหาไม่เกิดขึ้นใน eclipse) (โดยไม่ต้องเพิ่มช่องว่างหลัง B ("B"))

32
คุณสามารถอธิบายอย่างละเอียดเกี่ยวกับกลยุทธ์การวิจัยของคุณแล้วในที่สุดสิ่งที่นำคุณไปสู่การค้นพบว่าการตัดบรรทัดเป็นผู้ร้าย (ฉันอยากรู้เกี่ยวกับทักษะนักสืบของคุณนั่นคือ!)
silph

12

ใช่ผู้กระทำผิดเป็นคำห่อแน่นอน เมื่อฉันทดสอบสองโปรแกรมของคุณ NetBeans IDE 8.2 ให้ผลลัพธ์ต่อไปนี้แก่ฉัน

  1. เมทริกซ์แรก: O และ # = 6.03 วินาที
  2. เมทริกซ์ที่สอง: O และ B = 50.97 วินาที

ดูรหัสของคุณอย่างใกล้ชิดคุณได้ใช้ตัวแบ่งบรรทัดเมื่อสิ้นสุดการวนรอบแรก แต่คุณไม่ได้ใช้ตัวแบ่งบรรทัดในวงที่สอง ดังนั้นคุณจะพิมพ์คำที่มี 1,000 อักขระในลูปที่สอง ที่ทำให้เกิดปัญหาการตัดคำ ถ้าเราใช้ตัวอักษรที่ไม่ใช่คำ "" หลังจาก B มันใช้เวลาเพียง5.35 วินาทีในการรวบรวมโปรแกรม และถ้าเราใช้ตัวแบ่งบรรทัดในลูปที่สองหลังจากผ่าน 100 ค่าหรือ 50 ค่าจะใช้เวลาเพียง8.56 วินาทีและ7.05 วินาทีตามลำดับ

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("B");
        }
        if(j%100==0){               //Adding a line break in second loop      
            System.out.println();
        }                    
    }
    System.out.println("");                
}

คำแนะนำอีกอย่างคือการเปลี่ยนการตั้งค่าของ NetBeans IDE ครั้งแรกของทั้งหมดไป NetBeans เครื่องมือและคลิกตัวเลือก หลังจากนั้นคลิกตัวแก้ไขและไปที่แท็บการจัดรูปแบบ จากนั้นเลือกทุกที่ในตัวเลือกการตัดบรรทัด ใช้เวลาในการรวบรวมโปรแกรมน้อยลงเกือบ 6.24%

การตั้งค่าตัวแก้ไข NetBeans

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.