Вопрос по stringbuilder, ram, .net – Каково потребление памяти в StringBuilder?

6

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

Итак, прежде чем приступить к пересмотру нашего кода, я хотел бы спросить: каковы характеристики потребления ОЗУ StringBuilder для больших строк?

Тем более, что они сравниваются со стандартным типом строки. Размер строк превышает 10 МБ, и мы, похоже, сталкиваемся с проблемами около 20 МБ.

НОТАРечь идет не о скорости, а о оперативной памяти.

Ваш Ответ

5   ответов
1

Strigbuilder - это отличное решение проблем с памятью, вызванных объединением строк.

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

По сравнению со строкой, это замечательно.

string output = "Test";
output += ", printed on " + datePrinted.ToString();
output += ", verified by " + verificationName;
output += ", number lines: " + numberLines.ToString();

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

Для человека, который проголосовал против, пожалуйста, объясните. torial
6

Вот хорошее исследование оКонкатенация строк и распределение памяти.

Если вы можете избежать объединения, сделайте это!

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

Дон»t использовать + = объединение когда-либо. Слишком много изменений происходит за сценой, которые неВо-первых, это очевидно из моего кода. Я советую использовать String.Concat () явно с любой перегрузкой (2 строки, 3 строки, строковый массив). Это наглядно покажет, что делает ваш код без каких-либо сюрпризов, и в то же время позволит вам контролировать эффективность.

Попробуйте оценить целевой размер StringBuilder.

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

Не используйте методы Format (), если производительность является проблемой.

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

3

Вас может заинтересовать структура данных веревок. Эта статья:Веревки: теория и практика объясняет их преимущества. Может быть, есть реализация для .NET.

[Обновить, чтобы ответить на комментарий] Использует ли он меньше памяти? Поискобъем памяти в статье вы найдете несколько подсказок.

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

У меня нетЯ нашел реализацию для .NET, но есть, по крайней мере, реализация C ++ (в SGI 'с STL:http://www.sgi.com/tech/stl/Rope.html). Может быть, вы можете использовать эту реализацию. Обратите внимание, что на странице, на которую я ссылаюсь, есть работа с производительностью памяти.

Обратите внимание, что веревки неРешение всех проблем: их полезность сильно зависит от того, как вы строите свои большие строки и как вы их используете. В статьях отмечены преимущества и недостатки.

Я отвечаю, обновляя мой ответ. Я надеюсь, что вы будете уведомлены об ответах на комментарии. PhiLho
Любые данные о том, как он работает в оперативной памяти, а не по скорости? torial
10

Каждый раз, когда StringBuilder исчерпывает пространство, он перераспределяет новый буфер в два раза больше исходного буфера, копирует старые символы и позволяет старому буферу получить GC 'д. Это'возможно, что тыпросто использовать достаточно (назовите это х), так что в 2 раза больше, чем память, которую выРазрешено выделять. Возможно, вы захотите определить максимальную длину для ваших строк и передать ее конструктору StringBuilder, чтобы вы предварительно распределили, и вы 'не во власти удвоения перераспределения.

-2

Я неЯ не знаю точно шаблон памяти строителя строк, но обычная строка не подходит.

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

string a = "a";

//creates object with a

a += "b"

/creates object with b, creates object with ab, assings object with ab to "a" pointer
Я рекомендую вам изучить реализацию строкового класса, прежде чем полагаться на это. По крайней мере, в Java этоумнее, чем сейчас. У меня нетt осмотрен .net 'реализация, но я могуне понимаю, почему они не будутсделать те же оптимизации. Bill K

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