Использовать пространство PermGen или метод интерна roll-my-own?

Я пишу Кодек для обработки сообщений, отправленных по TCP с помощью сделанного на заказ проводного протокола. Во время процесса декодирования я создаю много Strings, BigDecimals и даты. Схемы доступа клиент-сервер означают, что клиенту свойственно выпустить запрос и затем декодировать тысячи ответных сообщений, который приводит к большому количеству дубликата Strings, BigDecimals, и т.д.

Поэтому я создал InternPool<T> класс, разрешающий мне интернировать каждый класс объекта. Внутренне, пул использует a WeakHashMap<T, WeakReference<T>>. Например:

InternPool<BigDecimal> pool = new InternPool<BigDecimal>();

...

// Read BigDecimal from in buffer and then intern.
BigDecimal quantity = pool.intern(readBigDecimal(in));

Мой вопрос: Я использую InternPool для BigDecimal но если я рассматриваю также использование его для String вместо String intern() метод, которому я верю, использует пространство PermGen? Каково преимущество использования пространства PermGen?

8
задан Adamski 9 January 2012 в 16:18
поделиться

2 ответа

Вероятно, пул JVM String.intern () будет работать быстрее. AFAIK, он реализован в собственном коде, поэтому он должен быть быстрее и использовать меньше места, чем пул, реализованный с использованием WeakHashMap и WeakReference . Чтобы подтвердить это, вам нужно будет провести тщательный сравнительный анализ.

Однако, если у вас нет огромного количества долгоживущих повторяющихся объектов, я сомневаюсь, что интернирование (либо в permGen, либо с вашими собственными пулами) будет иметь большое значение. А если соотношение уникальных и повторяющихся объектов слишком низкое, интернирование просто увеличит количество живых объектов (что заставит сборщик мусора занять больше времени) и снизит производительность из-за накладных расходов на интернирование и т. Д. Так что я бы также поддержал сравнение подходов «стажер» и «не стажер».

3
ответ дан 5 December 2019 в 20:14
поделиться

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

Кроме того, я бы использовал Коллекции Google MapMaker , чтобы создать InternPool , чтобы избежать повторного создания колеса:

Map<BigDecimal,BigDecimal> bigDecimalPool = new MapMaker()
    .weakKeys()
    .weakValues()
    .expiration(1, TimeUnits.MINUTES)
    .makeComputingMap(
      new Function<BigDecimal, BigDecimal>() {
        public BigDecimal apply(BigDecimal value) {
          return value;
        }
      });

Это даст вам (правильно реализовано ) слабые ключи и значения, безопасность потоков, автоматическая очистка старых записей и очень простой интерфейс (простая, хорошо известная карта ). Конечно, вы также можете обернуть его, используя Collections.immutableMap () , чтобы избежать неправильного кода.

5
ответ дан 5 December 2019 в 20:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: