Я пишу программу в Java, которая имитирует гравитацию, и в ней у меня есть множество операторов журнала (для System.out). Моя программа работает очень медленно, и я думаю, что регистрация может быть частью причины. Есть ли способ отключить System.out, чтобы моя программа не замедлялась при печати, или мне приходится вручную проходить и комментировать/раскомментировать каждый, чтобы включить/отключить отладочные заявления? Любая помощь будет оценена по достоинству.Отключить System.out для скорости в Java
ответ
Я согласен с другими, что собственно регистратор должен использоваться. Однако это невозможно в каждом случае. Следующий код отключает вне и быстро как просили OP:
System.setOut(new java.io.PrintStream(new java.io.OutputStream() {
@Override public void write(int b) {}
}) {
@Override public void flush() {}
@Override public void close() {}
@Override public void write(int b) {}
@Override public void write(byte[] b) {}
@Override public void write(byte[] buf, int off, int len) {}
@Override public void print(boolean b) {}
@Override public void print(char c) {}
@Override public void print(int i) {}
@Override public void print(long l) {}
@Override public void print(float f) {}
@Override public void print(double d) {}
@Override public void print(char[] s) {}
@Override public void print(String s) {}
@Override public void print(Object obj) {}
@Override public void println() {}
@Override public void println(boolean x) {}
@Override public void println(char x) {}
@Override public void println(int x) {}
@Override public void println(long x) {}
@Override public void println(float x) {}
@Override public void println(double x) {}
@Override public void println(char[] x) {}
@Override public void println(String x) {}
@Override public void println(Object x) {}
@Override public java.io.PrintStream printf(String format, Object... args) { return this; }
@Override public java.io.PrintStream printf(java.util.Locale l, String format, Object... args) { return this; }
@Override public java.io.PrintStream format(String format, Object... args) { return this; }
@Override public java.io.PrintStream format(java.util.Locale l, String format, Object... args) { return this; }
@Override public java.io.PrintStream append(CharSequence csq) { return this; }
@Override public java.io.PrintStream append(CharSequence csq, int start, int end) { return this; }
@Override public java.io.PrintStream append(char c) { return this; }
});
Мои измерения образца были:
- 82MS полномасштабная выход
- 57ms когда только переопределение
write(int)
вOutputStream
- 31 мс при переопределении
PrintStream
методов - 5мс, когда комментировал все
println
иprintf
использований
Так это быстрее, чем другие ответы здесь, но не может бить несуществующий код (закомментировать System.out
с или обертку в if (DEBUG)
) в качестве списков параметров выделяет массивы и коробок или StringBuilder
(+
) все еще выполняется.
Любая причина, по которой это не работает внутри статического блока? – 53by97
Спасибо за решение. Теперь как мы снова включим system.out в более поздний момент? – rahul
@rahul 'stdout = System.out', а затем вызывать' System.setOut (stdout) ' – TWiStErRob
Если вы не возражаете, чтобы пройти через все их только один раз, вы могли бы создать константу, которая «включает» или «отключает», и добавлять флаг только для печати, если эта константа включена. Тогда вы можете просто просто перевернуть константу.
public static boolean PRINTLN_ENABLED = true;
if(Constant.PRINTLN_ENABLED)
System.out.println();
Это работы. Но возникает проблема, заключающаяся в том, что для включения и отключения входа в систему необходимо изменить константу в исходном коде и перекомпилировать класс, а также * каждый другой класс *, который использует эту константу. Если вы замените константу на то, что неизвестно во время компиляции, тогда тест должен выполняться каждый раз, и это представляет собой небольшую часть времени выполнения. –
вы должны использовать реальные рамки протоколирования как log4j или slf4j. в любом случае вы можете установить уровень ведения журнала, чтобы ограничить уровень информации, сбрасываемой в журналы.
, если вы настаиваете на использовании System.out, вы можете обернуть ваши заявления протоколирования в состоянии, как,
if (DEBUG) {
System.out.println(...);
}
да, тяжелая каротаж или печать на System.out будет влиять на производительность.
Почему вы говорите, что нет возможности отключить System.out, когда он действительно может быть перенаправлен? –
@HovercraftFullOfEels вы можете перенаправить его только на PrintStream, который будет почти таким же образом привязывать его. –
согласился. исходный вопрос - «отключить system.out». вы не можете его технически отключить. перенаправление может привести к меньшей нагрузке, но все еще есть работа по записи в поток и оценка строкового объекта (ов), который должен быть записан. –
Я бы предположил, что вы заглянете в log4j (или подобные библиотеки) в будущем. Он работает так же, как и system.out, но на самом деле имеют переключатели, чтобы отключить их, когда вам нужно.
Определенно начать использовать API протоколирования вместо System.out
. Я очень рекомендую Logback. Вы можете легко настроить что-то, что просто входит в консоль, но может быть отключено в любое время. Резервное копирование мертво просто для настройки, но если вам не нравятся конфигурационные файлы, вы можете даже установить это программно.
Log4j также хорошо, это ранняя структура того же автора, что и Logback, и считается многими стандартными. SLF4J, еще раз тем же автором, не является истинной основой регистрации, а скорее стандартной оболочкой для абстрактной реализации фактического ведения журнала. Log4j можно обернуть в SLF4J, а Logback имеет собственный интерфейс SLF4J. Если бы я был вами, я бы избежал регистрации Apache Commons, для various reasons. Я никогда не был большим поклонником встроенного журналирования Java (java.util.logging
).
Я подозреваю, что вы можете использовать System.setOut(PrintStream)
для делегирования PrintStream
, который ничего не делает, но это, вероятно, не устранит все ваши накладные расходы - я подозреваю, например, что форматирование сообщений об ошибках будет по-прежнему стоить вам.
вы можете использовать System.setOut только для PrintStream –
Право, мое плохое. Исправлена. –
Опять выходной поток индюк может работать, что-то, возможно, как ...
System.setOut(new PrintStream(new OutputStream() {
@Override
public void write(int arg0) throws IOException {
}
}));
Но лучшим решением будет использовать формальную программу ведения журнала, как уже упоминалось.
Я думал об этом, но я думаю, что это все равно будет использовать некоторое время, когда PrintStream будет форматировать вход для OutputStream –
Logback и другие интерфейсы в стиле SLF4J обеспечивают достойное решение этой проблемы - так называемый «{}» стиль призыва. См. Эту ссылку: http://www.slf4j.org/faq.html#logging_performance. –
Если ваше приложение запущено в командной строке, вы можете отключить поток stdout для всей программы на уровне ОС. Это фактически отключит все ваши System.out.prinln() s, не требуя от вас изменения какого-либо кода.
На Linux/Unix вы можете закрыть стандартный вывод, перенаправив его в/Dev/нуль: java MyJavaProgram > /dev/null
Началось с затмения. Есть ли способ сделать это в eclipse? –
@ + 1. Исходный вопрос не похож на специфический для eclipse. этот ответ должен быть указан выше других ответов. (я пропустил это, следовательно, мой комментарий к nul) – Jayan
В eclipse откройте окно «Run Configurations», выберите вкладку «Common». В нижней части окна есть раздел для обработки стандартных ввода и вывода. Снимите флажок «Выделить консоль», и он больше ничего не должен выводить на консоль. Обратите внимание, что это также отключит вашу способность использовать stdin. – shj
Поскольку вы упомянули Eclipse, в одном из своих комментариев вы можете найти соответствующий ответ здесь: https://stackoverflow.com/a/799277/1017130
(I изначально хотел опубликовать это как комментарий к ответу shj, но мне кажется, что мне больше нужно повторить)
Лучшим долгосрочным решением будет использование рамки ведения журнала. Обычно я использую встроенное ведение журнала, так как я стараюсь избегать дополнительных зависимостей. Вы можете прочитать об этом здесь: http://docs.oracle.com/javase/1.4.2/docs/guide/util/logging/overview.html
я поставил этот код один раз в перекодировки слушателя в моем веб-проекта и решить проблему
/*
* In this case, if you are not in debug mode or any other
*the default system out is replaced internally with this
*implementation, else it works as expected. This way you do not
*have to find and replace anything in your code.
*/
//or as i did servletContext.getInitParameter("mode")
//from web.xml for global parameter
if(!DEBUG) {
System.setOut(
new PrintStream(new OutputStream() {
public void close() {}
public void flush() {}
public void write(byte[] b) {}
public void write(byte[] b, int off, int len) {}
public void write(int b) {}
});
}
}
Я предполагаю, что вы могли бы создать поток gobbler, перенаправить стандартный поток вывода к вашему gobbler и пойти от там. –
Без рефакторинга вашего кода я сомневаюсь. – Alexander
@ Вы пытались написать/dev/null (если вы находитесь в UNIX) или NUL в окнах. Это должно быть быстрее - не уверен, сколько. Я ожидаю, что это будет значительно быстрее. – Jayan