интересный OutOfMemoryException с StringBuilder

Я думал, что буду суммировать некоторые большие ответы, которые я имел к этому вопросу, вместе с моими собственными мыслями теперь я считал их всех:)

здесь существует две отличных проблемы:

  1. я должен предварительно заполнить базу данных со своим специальным 'администраторским' пользователем? Или приложение должно позволить настраивать, когда оно сначала используется?
  2. , Как каждый предварительно заполняет базу данных с данными? Обратите внимание, что это - допустимый вопрос независимо от ответа на часть 1: существуют другие сценарии использования для предварительного населения, чем администраторский пользователь.

Для (1), кажется, что установка первого пользователя из самого приложения является довольно мало дополнительной работы для функциональности, которая, по определению, почти никогда не используется. Это может быть немного более безопасно, однако, поскольку это вынуждает пользователя установить пароль их выбора. Лучшее решение является промежуточным эти два экстремальных значения: имейте сценарий (или обстреляйте задачу, или безотносительно) настраивать исходного пользователя. Сценарий может тогда быть настроен, чтобы автозаполнить с паролем по умолчанию во время разработки и потребовать, чтобы пароль был введен во время производственной установки / развертывание (если Вы хотите препятствовать паролю по умолчанию для администратора).

Для (2), кажется, что существует много хороших, допустимых решений. Задача граблей кажется хорошим путем, и существуют некоторые плагины для создания этого еще легче. Просто просмотрите некоторые из других ответов для наблюдения деталей тех:)

11
задан bitbonk 20 November 2009 в 09:58
поделиться

3 ответа

Память есть, но нет непрерывного сегмента, который мог бы обработать размер вашего построителя строк. Вы должны знать, что каждый раз, когда буфер построителя строк становится слишком коротким, его размер удваивается. Если вы можете определить (в ctor) размер вашего конструктора, это лучше. Вы МОЖЕТЕ вызвать GC.Collect () , когда закончите работу с большой коллекцией объектов.

На самом деле, когда у вас есть OutOfMemory, он обычно показывает плохой дизайн, вы можете использовать жесткий диск ( временные файлы) вместо памяти, вам не следует выделять память снова и снова (попробуйте повторно использовать объекты / буферы / ...).

Я НАСТОЯТЕЛЬНО советую вам прочитать этот пост «Недостаточно памяти» не См. Физическую память от Эрика Липперта.

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

Попробуйте повторно использовать объект StringBuilder при создании данных.

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

Чтобы проиллюстрировать мою точку зрения:

void MainProgram()
{
    StringBuilder builder = new StringBuilder(2 * 1024); //2 Kb

    PerformOperation(builder);
    PerformOperation(builder);
    PerformOperation(builder);
    PerformOperation(builder);
}

void PerformOperation(StringBuilder builder)
{
    builder.Length = 0;

    //
    // do the work here builder.Append(...);
    //
}
3
ответ дан 3 December 2019 в 05:58
поделиться

With the sizes you mention you are probably running into Large Object Heap (LOH) fragmentation.

Reusing StringBuilder objects is not a direct solution, you need to get a grip on the underlying buffers.
If possible, calculate or estimate the size beforehand and pre-allocate.

And it could help if you round up allocations, let's say to multiples of 20k or so. That could improve reuse.

3
ответ дан 3 December 2019 в 05:58
поделиться
Другие вопросы по тегам:

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