Неэффективное использование конкатенации строк - PullRequest
9 голосов
/ 20 марта 2012

Я создавал регистратор в своем java-приложении (с NetBeans в качестве IDE), когда внезапно увидел предупреждение: «Неэффективное использование конкатенации строк в регистраторе».

Мой международный код

srcLogger.getLogger().log(Level.INFO,"UploadBean.doUpload completado [" + file.getName() + "]\n");

но NetBeans предложила преобразовать его в шаблон (что здесь означает «шаблон») с указанием этого кода:

srcLogger.getLogger().log(Level.INFO, "UploadBean.doUpload completado [{0}]\n", file.getName());

Чем отличаются эти два способа объединения, я никогдаиспользовал последний, хотя.

Приветствия.

Ответы [ 6 ]

17 голосов
/ 30 декабря 2013

Сообщение не относится к стоимости конкатенации строк само по себе. Другие ответы абсолютно верны, когда говорят, что будет использоваться StringBuilder.

Основная причина использования шаблона сообщения заключается в том, что обработка выполняется только при отображении уровня ведения журнала!

Давайте используем эти два примера:

srcLogger.getLogger().log(Level.INFO,"UploadBean.doUpload completado [" + file.getName() + "]\n");
srcLogger.getLogger().log(Level.INFO, "UploadBean.doUpload completado [{0}]\n", file.getName());

При включенном уровне отладки INFO: Оба должны получить имя файла из файла, оба должны обновить строку, сгенерировать новую, отобразить ее.

При отключенном уровне отладки INFO: Второй ответ проходит через имя объекта File (это простой запрос), метод log () проверяет уровень INFO и немедленно возвращает результат. Нет String обработка не выполняется вообще!

Теперь представьте, что вместо простого file.getName() мы регистрировали более сложный объект, который сам требовал много конкатенации строк в методе toString(). При непосредственном ведении этих объектов ни одна из этих обработок не выполняется вообще. toString() никогда даже не вызывается, если не отображается уровень отладки.

Таким образом, шаблон сообщения не более эффективен в случае отображения журнала, но он значительно более эффективен (особенно в случаях нетривиального ведения журнала), когда ведение журнала не отображается. Одна из целей ведения журнала должна заключаться в том, что, если ведение журнала отключено, оно оказывает минимально возможное влияние на производительность системы.

12 голосов
/ 20 марта 2012

Я бы проигнорировал предупреждение (и, если возможно, выключил бы его).Конкатенация не настолько неэффективна, потому что современные компиляторы заменяют ее эффективной реализацией, основанной на StringBuilder (вы увидите это, если посмотрите на байт-код файла класса).

Предлагаемая замена не объединяет строкино он требует дополнительной обработки для анализа шаблона и объединения его с параметрами.

Netbeans, это плохой совет.

Это верно для Java 1.5+.Более старые версии Java (возможно) создают много неиспользованных String экземпляров во время конкатенации.

11 голосов
/ 20 марта 2012

Реальный выигрыш в том, что вам вообще не нужно выполнять какую-либо обработку строк (либо конкатенацию, либо расширение шаблона), если регистратор настроен так, чтобы не вести журнал на уровне INFO.

То естьРегистратор может вообще ничего не делать, не прибегая к каким-либо манипуляциям со строками.

4 голосов
/ 20 марта 2012

Поскольку строки являются неизменяемыми в Java, при объединении String объектов вы фактически создаете совершенно новый объект.Использование чего-то вроде шаблона, предложенного Netbeans, или StringBuilder не позволяет создавать все эти промежуточные объекты, которые требуют времени и ресурсов.

1 голос
/ 20 марта 2012

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

  1. Сообщения журнала, которые не собираются отправляться в журнал, не создаются при использовании стиля шаблона. Вы даже можете оптимизировать стиль немного больше, избегая вызовов методов в списке аргументов.

Но есть и другие причины выбрать стиль шаблона для сообщения журнала.

а. Предотвращает возможные накладные расходы. Как уже отмечали другие, это не большая проблема с недавним Javac's.

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

1 голос
/ 20 марта 2012

Шаблон означает именно это, он должен быть шаблоном для строки, а не самой строкой.Идея состоит в том, что бит {0} будет заменен первым аргументом, который появляется после него в списке (file.getName()).Это соответствует шаблону String format.

Я не видел тестов производительности, чтобы проверить, быстрее это или нет.Как уже указывалось в других ответах, оставить его как есть не будет особенно медленно, поскольку компилятор будет использовать StringBuilder вместо обычной строки.Однако, как указывает @dty, я думаю, что это должно быть быстрее в случае, если уровень ведения журнала установлен так, чтобы оператор фактически не регистрировался, так как не требуется никакой работы для создания строки для вывода.Кроме того, поскольку вся строка шаблона представляет собой один литерал, он будет добавлен компилятором в пул строк.Это означает, что все экземпляры этого конкретного String будут указывать на один и тот же фактический экземпляр - поэтому, если оператор фактически не зарегистрирован, ему даже не нужно выделять память для хранения этой строки, он просто ищет ее, чтодолжно быть более эффективным.

...