JavaSystem.out.print效率
Java System.out.print efficiency
最近几天,在做一些竞争性编程练习时,我找到了一些问题的解决方案,而不是在 for
循环中在控制台中打印文本,他们构建了一个 StringBuilder
通过在彼此之后附加文本。一开始我很困惑,但我试了一下并做了一些基准测试。
第一次测试:这是在屏幕上打印内容的经典方式:
class TestClass {
public static void main(String args[]) throws Exception {
double startTime = System.currentTimeMillis();
//code
for (int i = 0; i < 1000000; i++) {
System.out.print("test");
}
//code
double endTime = System.currentTimeMillis();
String result = String.format("for loop: %.5f", (endTime-startTime) / 1000);
System.out.print("\n"+result);
}
}
第二次测试:这是StringBuilder
的增强版:
class TestClass {
public static void main(String args[]) throws Exception {
double startTime = System.currentTimeMillis();
//code
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000000; i++) {
sb.append("test");
}
System.out.print(sb);
//code
double endTime = System.currentTimeMillis();
String result = String.format("for loop: %.5f", (endTime - startTime) / 1000);
System.out.print("\n" + result);
}
}
经过运行多次测试(运行 Intel i5 6500 四核 3.2 GHZ CPU,Win 10),结果如下:
first test(for loop): 4,25s
second test(StringBuilder): 0.23s
结果并不出乎意料,因为out.print
是同步的所以每次调用都会增加一些开销。但是慢了将近 20 倍有点奇怪。
我的问题是:有没有办法进一步改进它?
synchronized
在这种情况下不应归咎于关键字。
第一个测试用例比较慢,因为System.out.print
会带来频繁极小I/O。
你可以使用BufferedWriter
(它的write方法也是同步的)来减少不必要的I/O:
BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out));
//code
for (int i = 0; i < 1000000; i++) {
log.write("test");
}
for loop: 0.21200
并且,StringBuilder
使用 byte[]
进行内部字符存储。当您通过将旧值复制到新值 byte[]
来不断追加内容时,此字节数组将会增长。
给它足够大的容量可能会带来一些效率:
StringBuilder sb = new StringBuilder(1000000 * 10);
最近几天,在做一些竞争性编程练习时,我找到了一些问题的解决方案,而不是在 for
循环中在控制台中打印文本,他们构建了一个 StringBuilder
通过在彼此之后附加文本。一开始我很困惑,但我试了一下并做了一些基准测试。
第一次测试:这是在屏幕上打印内容的经典方式:
class TestClass {
public static void main(String args[]) throws Exception {
double startTime = System.currentTimeMillis();
//code
for (int i = 0; i < 1000000; i++) {
System.out.print("test");
}
//code
double endTime = System.currentTimeMillis();
String result = String.format("for loop: %.5f", (endTime-startTime) / 1000);
System.out.print("\n"+result);
}
}
第二次测试:这是StringBuilder
的增强版:
class TestClass {
public static void main(String args[]) throws Exception {
double startTime = System.currentTimeMillis();
//code
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000000; i++) {
sb.append("test");
}
System.out.print(sb);
//code
double endTime = System.currentTimeMillis();
String result = String.format("for loop: %.5f", (endTime - startTime) / 1000);
System.out.print("\n" + result);
}
}
经过运行多次测试(运行 Intel i5 6500 四核 3.2 GHZ CPU,Win 10),结果如下:
first test(for loop): 4,25s
second test(StringBuilder): 0.23s
结果并不出乎意料,因为out.print
是同步的所以每次调用都会增加一些开销。但是慢了将近 20 倍有点奇怪。
我的问题是:有没有办法进一步改进它?
synchronized
在这种情况下不应归咎于关键字。
第一个测试用例比较慢,因为System.out.print
会带来频繁极小I/O。
你可以使用BufferedWriter
(它的write方法也是同步的)来减少不必要的I/O:
BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out));
//code
for (int i = 0; i < 1000000; i++) {
log.write("test");
}
for loop: 0.21200
并且,StringBuilder
使用 byte[]
进行内部字符存储。当您通过将旧值复制到新值 byte[]
来不断追加内容时,此字节数组将会增长。
给它足够大的容量可能会带来一些效率:
StringBuilder sb = new StringBuilder(1000000 * 10);