Вопрос по memory, stringbuilder, java – Самый эффективный начальный размер емкости для StringBuilder?

5

я пишу много вещей для входа в пакеты и оптимизирую путь данных. Я строю текст журнала сStringBuilder, Какова была бы наиболее эффективная начальная емкость с точки зрения управления памятью, чтобы она работала хорошо независимо от JVM? Цель состоит в том, чтобы почти всегда избегать перераспределения, которое должно покрываться первоначальной емкостью около 80-100. Но я также хочу тратить как можно меньше байтов, так как экземпляр StringBuilder может зависать в буфере, и расточительные байты возникают.

Я понимаю, что это зависит от JVM, но должна быть какая-то ценность, которая будет тратить наименьшее количество байтов, неважно, JVM, вроде "наименьший общий знаменатель, Я сейчас пользуюсь128-16где 128 - это хорошее круглое число, а вычитание предназначено для накладных расходов. Кроме того, это может рассматриваться как случай "преждевременная оптимизация », но так как ответ, который я после "Верховенство а-эмпирическое» номер, зная, что это будет полезно и в будущем.

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

Ответ на этот вопрос зависит от многих вещей, например, от того, как долго текст хранится вStringBuilder и т. д. Единственный способ выяснить это - измерение с использованием профилировщика памяти и / или процессора. Там'нет причин беспокоиться о нескольких байтах, если вы не создаете сотни тысячStringBuilder объекты. Jesper
Безусловно, самые большие накладные расходы - это стоимость IO. Если вы нея не собирался записывать эти данные в IOне беспокойся об этом. Peter Lawrey

Ваш Ответ

2   ответа
3

я закончил тестировать это сам, а затем протестировал еще несколько комментариев, чтобы получить отредактированный ответ.

Использование JDK 1.7.0_07 и тестовое приложение, сообщающее имя VM "Java HotSpot (TM) 64-битная серверная виртуальная машина "гранулярностьStringBuilder использование памяти составляет 4символы, увеличиваясь даже на 4 символа.

Ответ:любой кратный 4 одинаково хорошая емкость для StringBuilder с точки зрения выделения памяти, по крайней мере, на этой 64-битной JVM.

Протестировано путем создания 1000000 объектов StringBuilder с различной начальной емкостью, в разных выполнениях тестовой программы (чтобы иметь одинаковое начальное состояние кучи) и распечаткойManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() до и после.

Распечатка размеров кучи также подтвердила, что сумма фактически выделяется из кучи для каждогоStringBuilderКак и ожидалось, буфер s равен кратному 8 байтам, поскольку длина символа Java составляет 2 байта. Другими словами, выделение 1000000 экземпляров с начальной емкостью 1..4 занимает примерно на 8 мегабайт меньше памяти (8 байт на единицу), чем выделение того же количества экземпляров с начальной емкостью 5 ... 8.

Я заметил, что 1000000 хnew StringBuilder(112) занял столько же кучи, сколько 1000000 хnew StringBuilder(115), Увеличение емкости до 116 заметно увеличило использование кучи, 120 снова увеличило ее и т. Д. Я был довольно удивлен, полагая, что это 4 байта, но 4 символа = 8 байтов имеет гораздо больше смысла (на 64-битной JVM). hyde
Вы не против поделиться своими процедурами тестирования? - Как вам удается определить использование кучи с такой детализацией? JimmyB
Я неКод был удобен, но использование кучи увеличивалось с каждым увеличением на 4 единицы в начальной емкости StringBuilder, а затем было примерно таким же для 3 следующих размеров, прежде чем снова подскочить до следующего кратного 4.Но тот's 4 символа, то есть 8 байтов, верно? Спасибо за вопрос, яЗавтра обязательно еще раз проверим, чтобы убедиться в этом. hyde
Итак, вы наблюдали увеличение использования кучи с шагом 1000000 x 4 байта? - Я нене стоит думать о том, сколько байтов пространства кучи Java займет [структура данных], а неchar и не для любого другого значения / типа в любой программе Java. - Кроме того, независимо отраспределение гранулярность кучи, гранулярность, при которой GC решаетрелиз память обратно в кучу неизвестна и будет влиять на любые измерения. - Если вы проводите тестирование из любопытства и / или для измерения некоторых характеристик данной JVM, продолжайте. - В противном случае, см. Мой ответ выше :) JimmyB
4

В настоящее время я использую 128-16, где 128 - хорошее круглое число, а вычитание - для накладных расходов.

В Java это основано на совершенно произвольных предположениях о внутренней работе JVM. Java не C. Байт-выравнивание и тому подобное абсолютноне проблема, которую программист может или должен попытаться использовать.

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

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

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