我看过这个问题,它有些相似。我想知道它是否真的是一个会影响我的应用程序性能的重要因素。以下是我的情况。
我有一个Java Web应用程序,可以从电子表格中上传成千上万条数据,每行从顶部到底部读取。我使用System.out.println()
在服务器侧显示当前应用程序正在读取的行数。
- 我知道创建日志文件的方法。实际上,我正在创建一个日志文件,并同时在服务器提示窗口中显示日志。
还有其他打印当前数据到提示窗口的方法吗?
我看过这个问题,它有些相似。我想知道它是否真的是一个会影响我的应用程序性能的重要因素。以下是我的情况。
我有一个Java Web应用程序,可以从电子表格中上传成千上万条数据,每行从顶部到底部读取。我使用System.out.println()
在服务器侧显示当前应用程序正在读取的行数。
- 我知道创建日志文件的方法。实际上,我正在创建一个日志文件,并同时在服务器提示窗口中显示日志。
还有其他打印当前数据到提示窗口的方法吗?
最近我在测试读写大型文本文件(1-1.5GB),并发现:
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(java.io.FileDescriptor.out), "UTF-8"), 512));
out.println(yourString);
//...
out.flush();
实际上比原来快250%
System.out.println(yourString);
我的测试程序首先读取了大约1GB的数据,稍微处理一下,然后以稍微不同的格式输出。
在MacBook Pro上进行的测试结果(使用SSD进行读写操作,同一块磁盘):
我尝试了多个不同的缓冲区大小(在256-10k之间),但似乎并没有影响。
因此,请记住,如果您正在使用Java创建Unix命令行工具,并且输出需要被定向或者管道到其他地方,请不要直接使用System.out!
它可能会影响应用程序的性能。其影响的程度取决于您运行的硬件类型和主机负载。
下面是一些性能方面的要点:
-> 如Rocket boy所述,println是同步的,这意味着您将在对象标头上产生锁定开销,并且根据设计可能会导致线程瓶颈。
-> 在控制台上打印需要内核时间,内核时间意味着CPU不会在用户模式下运行,这基本上意味着您的CPU将忙于执行内核代码而不是应用程序代码。
-> 如果您已经记录了此内容,则意味着需要额外的内核时间进行I/O操作,如果您的平台不支持异步I/O,则这意味着您的CPU可能会在忙等待时停顿。
您可以尝试对此进行基准测试并自行验证。
有一些方法可以解决这个问题,例如具有非常快的I/O、专用使用的大型计算机以及JVM选项上的偏向锁定,如果您的应用程序设计不会在控制台上打印多线程。
像所有性能相关的事情一样,这取决于您的硬件和优先级。
System.out.println()
已同步。
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
如果有多个线程同时写入,它的性能将会受到影响。是的,这将对性能产生巨大影响。如果你想要一个量化的数字,那么有很多软件和/或测量自己代码性能的方法。
与大多数缓慢的操作相比,System.out.println非常缓慢。这是因为它比其他IO操作更加繁重(并且是单线程的)。
我建议您将输出写入文件,并使用tail
命令查看该文件的输出。这样,输出仍然很慢,但不会使您的Web服务变得太慢。
这是一个非常简单的程序,用于检查System.out.println的性能,并将其与乘法操作进行比较(您可以使用其他操作或特定于您要求的函数)。
public class Main{
public static void main(String []args) throws InterruptedException{
long tTime = System.nanoTime();
long a = 123L;
long b = 234L;
long c = a*b;
long uTime = System.nanoTime();
System.out.println("a * b = "+ c +". Time taken for multiplication = "+ (uTime - tTime) + " nano Seconds");
long vTime = System.nanoTime();
System.out.println("Time taken to execute Print statement : "+ (vTime - uTime) + " nano Seconds");
}
}
输出结果取决于您的计算机及其当前状态。
以下是我在https://www.onlinegdb.com/online_java_compiler上得到的结果。
a * b = 28782. Time taken for multiplication = 330 nano Seconds
Time taken to execute Print statement : 338650 nano Seconds
编辑:
我在本地机器上设置了日志记录器,想要让你了解系统输出和日志记录器(即控制台打印与日志记录)之间的性能差异。
public static void main(String []args) throws InterruptedException{
long tTime = System.nanoTime();
long a = 123L;
long b = 234L;
long c = a*b;
long uTime = System.nanoTime();
System.out.println("a * b = "+ c +". Time taken for multiplication = "+ (uTime - tTime) + " nano Seconds");
long vTime = System.nanoTime();
System.out.println("Time taken to execute Print statement : "+ (vTime - uTime) + " nano Seconds");
long wTime = System.nanoTime();
logger.info("a * b = "+ c +". Time taken for multiplication = "+ (uTime - tTime) + " nano Seconds");
long xTime = System.nanoTime();
System.out.println("Time taken to execute log statement : "+ (xTime - wTime) + " nano Seconds");
}
a * b = 28782. Time taken for multiplication = 1667 nano Seconds
Time taken to execute Print statement : 34080917 nano Seconds
2022-11-15 11:36:32.734 [] INFO CreditAcSvcImpl uuid: - a * b = 28782. Time taken for multiplication = 1667 nano Seconds
Time taken to execute log statement : 9645083 nano Seconds