【问题标题】:Java - System.out effect on performanceJava - System.out 对性能的影响
【发布时间】:2013-09-06 05:55:34
【问题描述】:

我见过this question,它有点相似。我想知道这是否真的是影响我的应用程序性能的一个重要因素。这是我的场景。

我有这个 Java webapp,它可以从电子表格上传数千个数据,每行从上到下读取。我正在使用System.out.println() 在服务器端显示应用程序当前正在读取的行。

- 我知道创建一个日志文件。事实上,我正在创建一个日志文件,同时在服务器的提示符上显示日志。
有没有其他方法可以在提示符上打印当前数据?

【问题讨论】:

  • System.out 很慢,但它是否会影响应用程序的整体性能完全取决于它的作用。此问题无法按原样回答。
  • 您可以在另一个线程中启动打印。当然,这样您就不会及时了解代码的确切位置,至少它不会减慢您的速度。但请注意您有多大的缓冲区。
  • @Michael Ardan:如果服务器处理数千条记录并在控制台上打印,你真的看到了吗?它是用来调试的吗?
  • @Jayan :是的,可以从控制台看到。
  • 它还取决于 println 调用与您的代码正在执行的其他函数的比率。客观地说,它没有,但如果你的程序需要 60 秒来运行并且多余的 printlns 占 2 秒,它似乎不太相关。

标签: java performance performance-testing outputstream


【解决方案1】:

我最近正在测试(读取和)写入大型(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读写同盘):

  • data-output-to-system-out > output.txt => 1min32sec
  • data-written-to-file-in-java => 37sec
  • data-written-to-buffered-writer-stdout > output.txt => 36sec

我确实尝试过使用大小在 256-10k 之间的多个缓冲区,但这似乎并不重要。

所以请记住,如果您使用 Java 创建 unix 命令行工具,其中的输出旨在被定向或通过管道传输到其他地方,请不要直接使用 System.out!

【讨论】:

  • 感谢您提供的性能统计数据!使用 BufferedWriter 与使用 Logger 对象的性能相比如何?
  • 现在这是一个缓冲写入器,当缓冲区已满时性能如何比较?
  • 来自未来的问候!相比之下,2018 GNU/Linux glibc 标准输出缓冲区为 4096 字节,而文件复制缓冲区为 131072 字节。由于规范,复制工具 dd 被默认的 512 字节缓冲区(如this answer)卡住,这使得它在现代驱动器上受 CPU 限制。
【解决方案2】:

它可能会影响您的应用程序性能。大小会根据您运行的硬件类型和主机上的负载而有所不同。

这可以转化为性能方面的一些要点:

-> 正如 Rocket boy 所说,println 是同步的,这意味着您将在对象头上产生锁定开销,并且可能会根据您的设计导致线程瓶颈。

-> 在控制台上打印需要内核时间,内核时间意味着 cpu 不会在用户模式下运行,这基本上意味着您的 cpu 将忙于执行内核代码而不是您的应用程序代码。

-> 如果你已经记录了这个,这意味着额外的内核时间用于 I/O,如果你的平台不支持异步 I/O,这意味着你的 cpu 可能会因为忙等待而停滞。

您实际上可以尝试对此进行基准测试并自行验证。

有一些方法可以解决这个问题,例如拥有非常快的 I/O、一台供专用使用的大型机器,如果您的应用程序设计不会在该控制台打印上实现多线程,则可能会偏向锁定您的 JVM 选项。

就像所有关于性能的事情一样,这完全取决于您的硬件和优先级。

【讨论】:

  • 如果我使用 Selenium 的 WebDriver 等工具进行集成测试,那么使用 System.out.println 对小型测试应用程序的集成测试会有多大的性能影响?
【解决方案3】:
System.out.println()

是同步的。

 public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }

如果多个线程写入它,它的性能会受到影响。

【讨论】:

    【解决方案4】:

    是的,它会对性能产生巨大影响。如果您想要一个可量化的数字,那么有很多软件和/或方法可以衡量您自己的代码的性能。

    【讨论】:

      【解决方案5】:

      与大多数慢速操作相比,System.out.println 非常慢。这是因为它比其他 IO 操作在机器上放置了更多的工作(并且它是单线程的)

      我建议你将输出写入一个文件,tail 这个文件的输出。这样,输出仍然会很慢,但不会使您的 Web 服务变慢。

      【讨论】:

        【解决方案6】:

        这是一个非常简单的程序,用于检查 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 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-08-30
          • 2021-03-09
          • 2011-06-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-11
          相关资源
          最近更新 更多