มีแรงสองแรงที่นี่ในความตึงเครียด: ประสิทธิภาพเทียบกับความสามารถในการอ่าน
ลองแก้ไขปัญหาข้อที่สามก่อนเถอะเส้นยาว:
System.out.println("Good morning everyone. I am here today to present you with a very, very lengthy sentence in order to prove a point about how it looks strange amongst other code.");
วิธีที่ดีที่สุดในการใช้สิ่งนี้และให้อ่านง่ายคือการใช้การต่อสตริง:
System.out.println("Good morning everyone. I am here today to present you "
+ "with a very, very lengthy sentence in order to prove a "
+ "point about how it looks strange amongst other code.");
การต่อข้อมูลแบบสตริงคงที่จะเกิดขึ้นในเวลารวบรวมและจะไม่มีผลต่อประสิทธิภาพเลย บรรทัดสามารถอ่านได้และคุณสามารถไปต่อได้
ตอนนี้เกี่ยวกับ:
System.out.println("Good morning.");
System.out.println("Please enter your name");
เมื่อเทียบกับ
System.out.println("Good morning.\nPlease enter your name");
ตัวเลือกที่สองนั้นเร็วกว่ามาก ฉันจะแนะนำเกี่ยวกับ 2X เร็ว .... ทำไม?
เนื่องจาก 90% (ที่มีข้อผิดพลาดกว้าง) ของงานไม่เกี่ยวข้องกับการดัมพ์อักขระไปยังเอาต์พุต แต่จำเป็นต้องมีค่าใช้จ่ายในการรักษาความปลอดภัยของเอาต์พุตที่จะเขียนลงไป
การประสานข้อมูล
System.out
PrintStream
เป็น การนำ Java ไปใช้ทั้งหมดที่ฉันรู้จัก PrintStream ภายใน: ดูรหัสบน GrepCode!.
สิ่งนี้หมายความว่าอะไรสำหรับรหัสของคุณ?
มันหมายความว่าทุกครั้งที่คุณโทร System.out.println(...)
คุณกำลังซิงโครไนซ์โมเดลหน่วยความจำของคุณคุณกำลังตรวจสอบและรอการล็อก เธรดอื่น ๆ ที่เรียก System.out จะถูกล็อกเช่นกัน
ในการใช้งานแบบเธรดเดียวผลกระทบของ System.out.println()
มักถูก จำกัด โดยประสิทธิภาพการทำงานของระบบ IO ของคุณคุณสามารถเขียนลงไฟล์ได้อย่างรวดเร็วเพียงใด ในแอพพลิเคชั่นแบบมัลติเธรดการล็อคอาจมีปัญหามากกว่า IO
ที่กรอกด้วยน้ำ
แต่ละ println เป็นแดง สิ่งนี้ทำให้บัฟเฟอร์ถูกลบทิ้งและทริกเกอร์การเขียนระดับคอนโซลไปยังบัฟเฟอร์ จำนวนของความพยายามที่นี่ขึ้นอยู่กับการใช้งาน แต่โดยทั่วไปจะเข้าใจว่าประสิทธิภาพของฟลัชนั้นมีเฉพาะในส่วนเล็ก ๆ ที่เกี่ยวข้องกับขนาดของบัฟเฟอร์ที่ถูกฟลัช มีค่าใช้จ่ายที่สำคัญที่เกี่ยวข้องกับการล้างข้อมูลที่บัฟเฟอร์หน่วยความจำถูกทำเครื่องหมายว่าสกปรกเครื่องเสมือนกำลังทำงาน IO และอื่น ๆ เกิดขึ้นที่ค่าใช้จ่ายครั้งเดียวแทนที่จะเป็นสองครั้งคือการเพิ่มประสิทธิภาพที่ชัดเจน
ตัวเลขบางตัว
ฉันรวบรวมการทดสอบเล็กน้อยต่อไปนี้:
public class ConsolePerf {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
benchmark("Warm " + i);
}
benchmark("real");
}
private static void benchmark(String string) {
benchString(string + "short", "This is a short String");
benchString(string + "long", "This is a long String with a number of newlines\n"
+ "in it, that should simulate\n"
+ "printing some long sentences and log\n"
+ "messages.");
}
private static final int REPS = 1000;
private static void benchString(String name, String value) {
long time = System.nanoTime();
for (int i = 0; i < REPS; i++) {
System.out.println(value);
}
double ms = (System.nanoTime() - time) / 1000000.0;
System.err.printf("%s run in%n %12.3fms%n %12.3f lines per ms%n %12.3f chars per ms%n",
name, ms, REPS/ms, REPS * (value.length() + 1) / ms);
}
}
รหัสค่อนข้างง่ายมันพิมพ์ซ้ำ ๆ สั้น ๆ หรือสตริงยาวออก สตริงที่ยาวมีการขึ้นบรรทัดใหม่หลายบรรทัด มันวัดระยะเวลาที่ใช้ในการพิมพ์ 1,000 รอบในแต่ละรอบ
ถ้าฉันเรียกใช้ที่พรอมต์คำสั่ง unix (Linux) และเปลี่ยนเส้นทางSTDOUT
ไปยัง/dev/null
และพิมพ์ผลลัพธ์จริงไปยังSTDERR
ฉันสามารถทำสิ่งต่อไปนี้:
java -cp . ConsolePerf > /dev/null 2> ../errlog
เอาต์พุต (เป็น errlog) ดูเหมือนว่า:
Warm 0short run in
7.264ms
137.667 lines per ms
3166.345 chars per ms
Warm 0long run in
1.661ms
602.051 lines per ms
74654.317 chars per ms
Warm 1short run in
1.615ms
619.327 lines per ms
14244.511 chars per ms
Warm 1long run in
2.524ms
396.238 lines per ms
49133.487 chars per ms
.......
Warm 99short run in
1.159ms
862.569 lines per ms
19839.079 chars per ms
Warm 99long run in
1.213ms
824.393 lines per ms
102224.706 chars per ms
realshort run in
1.204ms
830.520 lines per ms
19101.959 chars per ms
reallong run in
1.215ms
823.160 lines per ms
102071.811 chars per ms
สิ่งนี้หมายความว่า? ให้ฉันทำซ้ำ 'บทสุดท้าย':
realshort run in
1.204ms
830.520 lines per ms
19101.959 chars per ms
reallong run in
1.215ms
823.160 lines per ms
102071.811 chars per ms
นั่นหมายความว่าสำหรับทุกเจตนาและวัตถุประสงค์แม้ว่าบรรทัด 'long' จะยาวกว่าประมาณ 5 เท่าและมีการขึ้นบรรทัดใหม่หลายครั้ง แต่ก็ใช้เวลาในการส่งออกสั้นเป็นบรรทัดสั้น ๆ
จำนวนตัวอักษรต่อวินาทีสำหรับระยะยาวนั้นมากถึง 5 เท่าและเวลาที่ผ่านไปนั้นใกล้เคียงกัน .....
ในคำอื่น ๆ ผลงานของคุณที่สมดุลเมื่อเทียบกับจำนวนของ printlns คุณมีไม่สิ่งที่งานพิมพ์ที่คุณพิมพ์พิมพ์
อัปเดต:จะเกิดอะไรขึ้นหากคุณเปลี่ยนเส้นทางไปยังไฟล์แทนที่จะเป็น / dev / null
realshort run in
2.592ms
385.815 lines per ms
8873.755 chars per ms
reallong run in
2.686ms
372.306 lines per ms
46165.955 chars per ms
มันช้ากว่ามาก แต่สัดส่วนก็ใกล้เคียงกัน ....