为什么System.out.println这么慢?

2022-09-02 23:32:56

这是所有编程语言的共同点吗?进行多次打印,然后进行println似乎更快,但将所有内容移动到字符串中,并且只是打印速度似乎最快。为什么?

编辑:例如,Java可以在不到一秒钟的时间内找到所有最多100万的素数 - 但是将所有素数打印出来然后在自己的println上打印出来可能需要几分钟!高达100亿罐的打印时间!

前任:

package sieveoferatosthenes;
public class Main {
    public static void main(String[] args) {
        int upTo = 10000000;
        boolean primes[] = new boolean[upTo];
        for( int b = 0; b < upTo; b++ ){
            primes[b] = true;
        }
        primes[0] = false;
        primes[1] = false;

        int testing = 1;

        while( testing <= Math.sqrt(upTo)){
            testing ++;
            int testingWith = testing;
            if( primes[testing] ){
                while( testingWith < upTo ){
                    testingWith = testingWith + testing;
                    if ( testingWith >= upTo){
                    }
                    else{
                        primes[testingWith] = false;
                    }

                }
            }
        }
        for( int b = 2; b < upTo; b++){
            if( primes[b] ){
                System.out.println( b );
            }
        }
    }
}

答案 1

println不是慢,而是与主机连接的底层,由托管操作系统提供。PrintStream

您可以自己检查:将大型文本文件转储到控制台,并将相同的文本文件管道化到另一个文件中进行比较:

cat largeTextFile.txt
cat largeTextFile.txt > temp.txt

读取和写入是相似的,并且与文件的大小成正比(O(n)),唯一的区别是,目标不同(控制台与文件相比)。这与 基本相同。System.out


基础操作系统操作(在控制台窗口中显示字符)很慢,因为

  1. 字节必须发送到控制台应用程序(应该非常快)
  2. 每个字符必须使用(通常)真实类型的字体进行渲染(这非常慢,关闭抗锯齿可以提高性能,顺便说一句)
  3. 显示的区域可能必须滚动才能将新行附加到可见区域(最佳情况:位块传输操作,最坏情况:重新呈现整个文本区域)

答案 2

System.out是一个静态类。 除其他事项外,还有那些您可能非常熟悉的方法,例如等等。PrintStreamPrintStreamprint()println()

输入和输出操作需要很长时间并不是Java独有的。“长”。打印或写入 a 需要几分之一秒的时间,但是超过 100 亿个此打印的实例可以加起来相当多!PrintStream

这就是为什么你的“将所有内容移动到字符串”是最快的。你巨大的String已经建成,但你只打印一。当然,这是一个巨大的打印,但是您花时间在实际打印上,而不是在与 或 相关的开销上。print()println()

正如Dvd Prd所提到的,字符串是不可变的。这意味着,每当您将新字符串分配给旧字符串但重用引用时,您实际上都会销毁对旧字符串的引用并创建对新字符串的引用。因此,您可以使用 StringBuilder 类(可变类)使整个操作运行得更快。这将减少与生成最终要打印的字符串相关的开销。


推荐