Автор оригинала: Ram Lakshmanan.
Использование расширенного расширения – плюсы и минусы Позвольте мне начать эту статью с интересной статистики (основанной на исследовании, проведенном командой разработчиков JDK).:
- 25% памяти Java-приложений заполнено строками.
- 13,5% – это повторяющиеся строки в приложениях Java.
- Средняя длина строки составляет 45 символов.
Да, вы правы, 13,5% памяти тратится впустую из-за повторяющихся строк. 13,5% – это среднее количество повторяющихся строк, присутствующих в java-приложении. Чтобы выяснить, сколько памяти тратит ваше приложение из-за повторяющихся строк, вы можете использовать такие инструменты, как Heather, которые могут сообщать, сколько памяти тратится впустую из-за повторяющихся строк и других неэффективных методов программирования.
Что такое повторяющиеся строки? Во-первых, давайте разберемся, что означает повторяющаяся строка. Посмотрите на приведенный ниже фрагмент кода:
String string1 = new String("Hello World"); String string2 = new String("Hello World");
В приведенном выше коде есть два строковых объекта string1 и string2, они имеют одинаковое содержимое, т. е. “Привет, мир”, но они хранятся в двух разных объектах. Когда вы сделаете string1.equals(string2), он вернет “true”, но “string1” вернет “false”. Это то, что мы называем дублирующими строками.
Почему так много повторяющихся строк? Существует несколько причин, по которым приложение в конечном итоге имеет много повторяющихся строк. В этом разделе давайте рассмотрим два наиболее распространенных шаблона:
- Разработчики создают новые строковые объекты для каждого запроса вместо ссылки/повторного использования “общедоступного статического конечного строкового литерала”. Приведенный выше пример может быть оптимально написан с использованием шаблона строкового литерала:
public static final String HELLO_WORLD = "Hello World"; String string1 = HELLO_WORLD; String string2 = HELLO_WORLD;
2.Предположим, вы создаете банковское приложение/приложение для электронной коммерции. Вы сохраняете валюту (т. е. “USD”, “EUR”, “INR”, ….) для каждой записи транзакции в базе данных. Скажем, теперь клиент входит в ваше приложение, и он просматривает страницу истории транзакций. Теперь ваше приложение в конечном итоге будет считывать все транзакции, относящиеся к этому клиенту, из базы данных. Предположим, что этот клиент живет в США (тогда большинство, если не все его транзакции будут совершаться в долларах США). Поскольку каждая запись транзакции имеет валюту, ваше приложение в конечном итоге создаст строковый объект ” USD ” для каждой записи транзакции, считанной из базы данных. Если у этого клиента тысячи транзакций, вы в конечном итоге создадите тысячи дубликатов “ИСПОЛЬЗОВАННЫХ” строковых объектов в памяти, которые тоже предназначены только для этого одного клиента.
Аналогично, ваше приложение может считывать несколько столбцов (имя клиента, адрес, штат, страна, номер учетной записи, идентификаторы и т. д.) из баз данных несколько раз. Среди них могут быть дубликаты. Ваше приложение считывает и записывает XML/JSON с помощью внешних приложений, оно манипулирует множеством строк. Все эти операции могут/будут создавать повторяющиеся строки.
Эта проблема была давно признана командой JDK с момента ее возникновения (середина 1990-х годов), поэтому до сих пор было найдено несколько решений. Последним дополнением к этому списку решений является “- XX:+UseStringDeduplication”.
-XX:+Повторное использование Попытка с наименьшими усилиями устранить повторяющиеся строки заключается в передаче аргумента JVM ‘-XX:+UseStringDeduplication’. Когда вы передадите этот аргумент JVM во время запуска приложения, JVM попытается удалить повторяющиеся строки как часть процесса сборки мусора. Во время процесса сборки мусора JVM проверяет все объекты в памяти, таким образом, в рамках этого процесса он пытается идентифицировать повторяющиеся строки среди них и пытается устранить их.
Означает ли это, что если вы просто передадите аргумент JVM ‘-XX:+UseStringDeduplication’, сможете ли вы сразу сохранить 13,5% памяти? Звучит очень просто, не так ли? Мы хотели бы, чтобы это было так просто. Но в этом решении “- XX:+Usestringduplication ” есть некоторые недостатки. Давайте обсудим их.
(1). Работает только с алгоритмом G1 GC Существует несколько алгоритмов сбора мусора (последовательный, параллельный, CMS, G1,…). ‘ -XX:+UseStringDeduplication’ работает только в том случае, если вы используете алгоритм G1 GC. Итак, если вы используете какой-либо другой алгоритм GC, вам нужно переключиться на алгоритм G1 GC, чтобы использовать “- XX:+UseStringDeduplication”.
(2). Работает только с долгоживущими объектами ‘-XX:+UseStringDeduplication’ устраняет дубликаты строк, которые живут в течение более длительного периода времени. Они не устраняют повторяющиеся строки среди недолговечных строковых объектов. Если объекты недолговечны, они скоро исчезнут, тогда какой смысл тратить ресурсы на устранение повторяющихся строк среди них. Вот пример из реальной жизни , проведенный в крупном веб-приложении Java, которое не показало никакого облегчения памяти при использовании “- XX:+UseStringDeduplication”. Однако “- XX:+UseStringDeduplication ” может иметь значение, если в вашем приложении много кэшей (поскольку объекты кэша обычно имеют тенденцию быть долгоживущими объектами).
(3). -XX:stringduplicationagethreshold По умолчанию строки становятся пригодными для дедупликации, если они выдержали 3 запуска GC. Его можно изменить, передав это “- XX:StringDeduplicationAgeThreshold”.
Example: -XX:StringDeduplicationAgeThreshold=6
(4). Влияние на время паузы GC Поскольку дедупликация строк выполняется во время сборки мусора, это может повлиять на время паузы GC. Однако предполагается, что достаточно высокий показатель успешности дедупликации уравновесит большую часть или все эти последствия, поскольку дедупликация может уменьшить объем работы, необходимый на других этапах паузы GC (например, уменьшить количество объектов для эвакуации), а также снизить частоту GC (из-за снижения давления на кучу). Чтобы проанализировать влияние времени паузы GC, вы можете рассмотреть возможность использования таких инструментов, как GC easy
(5). Заменяется только базовый символ [] Язык java.lang. Класс String имеет два поля:
private final char[] value private int hash
‘-XX:+UseStringDeduplication’ не устраняет дубликат самого строкового объекта. Он заменяет только базовый символ[ ]. Дедупликация строкового объекта концептуально является просто переназначением поля значения, т. е..value.
Каждый строковый объект занимает не менее 24 байт (точный размер строкового объекта зависит от конфигурации JVM, но 24 байта-это минимум). Таким образом, эта функция экономит меньше памяти, если имеется много коротких повторяющихся строк.
(6). Java 8 обновление 20 Функция ‘-XX:+UseStringDeduplication’ поддерживается только с Java 8 обновление 20. Таким образом, если вы работаете на любых более старых версиях Java, вы не сможете использовать эту функцию.
(7). –XX:+Статистика дедупликации строк Печати Если вы хотите просмотреть статистику дедупликации строк, например, сколько времени потребовалось для запуска, сколько повторяющихся строк было удалено, сколько вы сэкономили, вы можете передать аргумент JVM ‘-XX:+PrintStringDeduplicationStatistics’. В консоли ошибок будет выведена статистика.
Вывод: Если ваше приложение использует G1GC и работает на версии выше Java 8 обновление 20, вы можете рассмотреть возможность включения “- XX:+UseStringDeduplication”. Вы можете получить плодотворные результаты, особенно если среди долгоживущих объектов много повторяющихся строк. Однако, прежде чем включать этот аргумент в рабочей среде, проведите тщательное тестирование.
Оригинал: “https://www.codementor.io/@suryab/usestringdeduplication-t4v3a72qv”