предисловие
Так совпало, что в эти дни я читаю книгу под названием "Практика оптимизации производительности системы Java", написанную Ли Цзяжи. В главе, посвященной анализу кода, я упомянул проблему с выводом журнала. Давайте посмотрим, как мы изначально выводим информацию. , следующим образом.
private static Logger logger = LoggerFactory.getLogger(FileManageApplication.class);
public static void main(String[] args) {
logger.info("日志输出{}",1);
}
Первый параметр — это шаблон формата, «{}» — заполнитель, а второй параметр — тип, который может бытьObject... arguments
, то "{}" в первом параметре поочередно заменяется данными этого массива. Если ничего другого, то будет выведена следующая информация.
2021年01月07日 19:52:09:INFO main (FileManageApplication.java:35) - 日志输出1
Однако он не рекомендует использовать этот метод. Причина в том, что процесс замены заполнителя "{}" на целевую переменную внутри среды ведения журнала займет много времени. Учитывая, что метод info может вызываться часто, он повлияет на производительность, поэтому рекомендуется выполнять сплайсинг напрямую, код выглядит следующим образом:
public static void main(String[] args) {
User user =getUser();
logger.info("用户名:"+user.getUserName());
}
Это звучит немного разумно, но сегодня утром я наткнулся на статью на официальном аккаунте, в которой также упоминалась эта проблема (это большая буква V), в которой говорилось: «Не выполняйте сращивание струн, это приведет к Строковые объекты занимают место, влияют на производительность».
what???
И привел контрпример следующим образом:
logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
И есть положительный пример, а именно:
logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol)
Кроме того, этот формат более удобочитаем и полезен для устранения неполадок.
Итак, какой метод мы используем в конце?
Давайте посмотрим на тест сами.
сравнение времени
Использовать сплайсинг
public class Main {
private static Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
long startTimer = System.currentTimeMillis();
for (int i = 0; i < 200000; i++) {
logger.info("i="+i);
}
System.out.println(System.currentTimeMillis()-startTimer);
}
}
Пробежав 10 раз, результаты следующие, средний результат 512,2.
534、510、486、518、495、505、526、507、511、530
Использовать метод шаблона
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
long startTimer = System.currentTimeMillis();
for (int i = 0; i < 200000; i++) {
logger.info("i={}",i);
}
System.out.println(System.currentTimeMillis()-startTimer);
}
}
Пробежав 10 раз, результаты следующие, средний результат 642,9.
654、648、599、624、678、660、643、656、583、684
Ведь, как говорится в книге, процесс замены "{}" занимает много времени.
здесь не используетсяSystem.out.println()
Для сравнения, потому что это слишком медленно, потому что внутренняя блокировка задействована.
сравнение использования памяти
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Main extends JFrame {
private static Logger logger = LoggerFactory.getLogger(Main.class);
public Main() {
this.setSize(300, 300);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
JButton jButton = new JButton("开始");
jButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < 1000000; i++) {
logger.info("i={}",i);
// logger.info("i="+ i);
}
}
});
this.add(jButton);
}
public static void main(String[] args) {
new Main();
}
}
Метод шаблона
После нажатия кнопки и ожидания завершения вывода память застряла на 112 764 КБ.
После выполнения GC он упал до 13 484 КБ.
Метод сращивания
После нажатия кнопки и ожидания завершения вывода память застряла на 128 014 КБ, разница составляет 15 250 КБ.
После выполнения GC он упал до 17 777 КБ.
В этом сравнении память, занимаемая методом сплайсинга, выше, что также соответствует общедоступной учетной записи.
В заключение
Очевидно, что у каждого есть свои преимущества, поэтому вы можете смотреть только на свои потребности.Кроме того, в исходном коде Tomcat также используется метод сплайсинга....
В Руководстве по разработке Java для Alibaba также сказано....