Có hai "lực lượng" ở đây, căng thẳng: Hiệu suất so với Khả năng đọc.
Trước tiên, hãy giải quyết vấn đề thứ ba, dài dòng:
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.");
Cách tốt nhất để thực hiện điều này và giữ mức độ dễ đọc, là sử dụng nối chuỗi:
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.");
Việc nối chuỗi liên tục sẽ xảy ra tại thời điểm biên dịch và hoàn toàn không ảnh hưởng đến hiệu suất. Các dòng có thể đọc được, và bạn có thể tiếp tục.
Bây giờ, về:
System.out.println("Good morning.");
System.out.println("Please enter your name");
so với
System.out.println("Good morning.\nPlease enter your name");
Tùy chọn thứ hai nhanh hơn đáng kể. Tôi sẽ đề nghị về 2X nhanh như vậy .... tại sao?
Bởi vì 90% (với biên độ sai số rộng) của tác phẩm không liên quan đến việc bỏ các ký tự vào đầu ra, nhưng là chi phí cần thiết để bảo đảm đầu ra để ghi vào nó.
Đồng bộ hóa
System.out
là một PrintStream
. Tất cả các triển khai Java mà tôi biết, đồng bộ hóa nội bộ PrintStream: Xem mã trên GrepCode! .
Điều này có ý nghĩa gì với mã của bạn?
Điều đó có nghĩa là mỗi lần bạn gọi System.out.println(...)
bạn đang đồng bộ hóa mô hình bộ nhớ, bạn đang kiểm tra và chờ khóa. Bất kỳ luồng nào khác gọi System.out cũng sẽ bị khóa.
Trong các ứng dụng đơn luồng, tác động của System.out.println()
thường bị giới hạn bởi hiệu suất IO của hệ thống của bạn, bạn có thể ghi ra tệp nhanh như thế nào. Trong các ứng dụng đa luồng, việc khóa có thể là một vấn đề hơn so với IO.
Rửa
Mỗi println được tuôn ra . Điều này làm cho bộ đệm bị xóa và kích hoạt ghi mức Console cho bộ đệm. Lượng nỗ lực được thực hiện ở đây phụ thuộc vào việc thực hiện, nhưng, người ta thường hiểu rằng hiệu suất của việc xả chỉ là một phần nhỏ liên quan đến kích thước của bộ đệm được xả. Có một chi phí đáng kể liên quan đến việc xả, trong đó bộ đệm được đánh dấu là bẩn, máy ảo đang thực hiện IO, v.v. Phát sinh chi phí đó một lần, thay vì hai lần, là một tối ưu hóa rõ ràng.
Một số số
Tôi tập hợp các bài kiểm tra nhỏ sau đây:
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);
}
}
Mã này tương đối đơn giản, nó liên tục in một chuỗi ngắn hoặc một chuỗi dài để xuất ra. Chuỗi dài có nhiều dòng mới trong đó. Nó đo thời gian cần thiết để in 1000 lần lặp mỗi lần.
Nếu tôi chạy nó tại dấu nhắc lệnh unix (Linux) và chuyển hướng STDOUT
đến /dev/null
và in kết quả thực tế đến STDERR
, tôi có thể làm như sau:
java -cp . ConsolePerf > /dev/null 2> ../errlog
Đầu ra (in errlog) trông giống như:
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
Điều đó có nghĩa là gì? Hãy để tôi nhắc lại 'khổ thơ' cuối cùng:
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
Điều đó có nghĩa là, đối với tất cả các ý định và mục đích, mặc dù dòng 'dài' dài hơn khoảng 5 lần và chứa nhiều dòng mới, nó chỉ mất khoảng thời gian để xuất ra như dòng ngắn.
Số lượng ký tự mỗi giây trong thời gian dài gấp 5 lần và thời gian trôi qua là như nhau .....
Nói cách khác, hiệu suất của bạn có tỷ lệ tương ứng với số lượng bản in bạn có chứ không phải những gì họ in.
Cập nhật: Điều gì xảy ra nếu bạn chuyển hướng đến một tệp, thay vì đến / 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
Nó chậm hơn rất nhiều, nhưng tỷ lệ là như nhau ....