Java - влияние System.out на производительность

Я видел этот вопрос, и он несколько похож. Я хотел бы знать, действительно ли это большой фактор, который повлияет на производительность моего приложения. Вот мой сценарий.

У меня есть это веб-приложение на Java, которое может загружать тысячи данных из электронной таблицы, которая читается в каждой строке сверху вниз. Я использую System.out.println(), чтобы показать на стороне сервера, какую строку приложение в данный момент читает.

- Мне известно о создании файла журнала. Фактически, я создаю файл журнала и в то же время показываю журналы в командной строке сервера.
Есть ли другой способ распечатать текущие данные в командной строке?


person Michael 'Maik' Ardan    schedule 03.09.2013    source источник
comment
System.out работает медленно, но повлияет ли он на общую производительность вашего приложения, полностью зависит от того, что он делает. На этот вопрос нельзя ответить как есть.   -  person ewernli    schedule 03.09.2013
comment
Вы можете запустить печать в другом потоке. Конечно, тогда вы не будете в курсе, где именно находится ваш код, по крайней мере, это не замедлит вас. Однако помните, какой у вас большой буфер.   -  person jontejj    schedule 03.09.2013
comment
@ Майкл Ардан: если сервер обработает тысячи записей и распечатает их на консоли, вы действительно их видите? Это это для отладки?   -  person Jayan    schedule 03.09.2013
comment
@Jayan: Да, это видно из консоли.   -  person Michael 'Maik' Ardan    schedule 03.09.2013
comment
Это также зависит от соотношения вызовов println к другим функциям, выполняемым вашим кодом. Объективно это не так, но если вашей программе требуется 60 секунд для запуска, а лишние printlns составляют 2 секунды, это кажется менее актуальным.   -  person Cole Henrich    schedule 22.05.2021


Ответы (6)


Это может повлиять на производительность вашего приложения. Величина будет варьироваться в зависимости от типа оборудования, на котором вы работаете, и нагрузки на хост.

Некоторые моменты, по которым это может повлиять на производительность:

-> Как заявил Rocket Boy, println синхронизирован, что означает, что вы будете нести накладные расходы на блокировку заголовка объекта и можете вызвать узкие места потока в зависимости от вашего дизайна.

-> Для печати на консоли требуется время ядра, время ядра означает, что процессор не будет работать в пользовательском режиме, что в основном означает, что ваш процессор будет занят выполнением кода ядра, а не кода вашего приложения.

-> Если вы уже регистрируете это, это означает дополнительное время ядра для ввода-вывода, а если ваша платформа не поддерживает асинхронный ввод-вывод, это означает, что ваш процессор может зависнуть в ожидании занятости.

Вы действительно можете попробовать и проверить это самостоятельно.

Есть способы избежать этого, например, иметь действительно быстрый ввод-вывод, возможно, огромную машину для специального использования и предвзятую блокировку ваших параметров JVM, если дизайн вашего приложения не будет многопоточным при печати этой консоли.

Как и все, что касается производительности, все зависит от вашего оборудования и приоритетов.

person bubooal    schedule 03.09.2013
comment
Если я тестирую интеграцию с помощью такого инструмента, как Selenium WebDriver, насколько сильно снизится производительность при использовании System.out.println при интеграционном тестировании небольших тестовых приложений? - person ; 04.08.2015

Недавно я тестировал (читал и) писал большие (1-1,5 ГБ) текстовые файлы и обнаружил, что:

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);

Моя тестовая программа сначала прочитала около 1 ГБ данных, немного обработала их и выдала в несколько другом формате.

Результаты тестирования (на Macbook Pro, при чтении и записи SSD с использованием одного и того же диска):

  • данные-выход-в-систему-выход> output.txt => 1мин32сек
  • данные-записанные-в-файл-в-java => 37сек
  • данные-записанные-в-буферизованный-писатель-stdout> output.txt => 36сек

Я пытался использовать несколько буферов размером от 256 до 10 КБ, но это не имело значения.

Так что имейте в виду, что если вы создаете инструменты командной строки unix с помощью Java, где вывод должен быть направлен или перенаправлен куда-то еще, не используйте System.out напрямую!

person Render    schedule 29.06.2015
comment
Спасибо за статистику производительности! Как использование BufferedWriter сравнивается по производительности с использованием объекта Logger? - person ; 04.08.2015
comment
Теперь это буферизованный писатель, как сравнить производительность при заполнении буфера? - person tuskiomi; 26.06.2017
comment
Привет из будущего! Для сравнения, буфер stdout для GNU / Linux glibc 2018 составляет 4096 байт, а буфер копирования файла - 131072 байта. Инструмент копирования dd застрял с 512-байтовым буфером по умолчанию (как в этом ответе) из-за спецификации, что делает его привязанным к процессору на современных дисках. - person that other guy; 09.06.2018

System.out.println()

синхронизируется.

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

Если в него пишут несколько потоков, его производительность пострадает.

person rocketboy    schedule 03.09.2013

Да, это ОГРОМНО повлияет на производительность. Если вам нужно количественное число, то есть много программного обеспечения и / или способов измерения производительности вашего собственного кода.

person redFIVE    schedule 03.09.2013

System.out.println работает очень медленно по сравнению с большинством медленных операций. Это связано с тем, что он требует больше работы на машине, чем другие операции ввода-вывода (и является однопоточным).

Я предлагаю вам записать вывод в файл и tail вывод этого файла. Таким образом, вывод по-прежнему будет медленным, но не так сильно замедлит работу вашего веб-сервиса.

person Peter Lawrey    schedule 03.09.2013

Вот очень простая программа для проверки производительности 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 
person Harshil    schedule 22.01.2021