Обработка больших строк, это фрагментация кучи больших объектов? - PullRequest
7 голосов
/ 11 сентября 2011

У меня есть приложение .NET 3.5

  • Функция выполняется миллион раз
  • Он выполняет операции поиска, замены и регулярного выражения в строках размером 1 МБ + (строки разного размера)

Когда я профилирую приложение, я могу подтвердить, что эти строки хранятся в LOH, но позже они также возвращаются GC, поэтому в данный момент времени только максимум 10 из них находятся в LOH (работает 10 потоков).

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

Это не вызывает проблем в ~ 100K раз, однако, когда оно достигает 1M +, оно выдает исключения из памяти.

Я использую ANTS Memory Profiler, и это результат, который я получил в ранних казнях:

.NET Using 70MB of 210MB total private bytes allocated in to the application
Number of Fragments: 59
Number of Large Fragments : 48 (99.6% of free memory)
Largest Fragment: 9MB
Free Space: 52% of total memory  (37MB)
Unmanaged Memory: 66% of total private memory (160MB)
  1. Считаете ли вы, что мой диагноз правильный на основании имеющихся данных?
  2. Если так, как я могу решить эту проблему фрагментации LOH? Я должен обработать эти строки, и они большие строки. Должен ли я найти способ разделить их и обработать так? В этом случае запуск регулярных выражений и т. Д. В разделенных строках будет очень сложным.

1 Ответ

2 голосов
/ 11 сентября 2011
  1. Да. Это звучит правильно. LOH становится фрагментированным, что приводит к тому, что среда выполнения не может выделить достаточно непрерывного пространства для больших строк.

  2. У вас есть несколько вариантов, я полагаю, вам следует выбрать наиболее простой и эффективный способ. Это все полностью зависит от того, как это написано.

    1. Разбейте свои струны на достаточно маленькие куски, чтобы их не было в LOH. (менее 85K - Примечание: логика для того, когда объект помещен в LOH , не так уж и резка .) Это позволит ГХ иметь возможность освободить пространство. Это ни в коем случае не гарантирует исправление фрагментации - в противном случае это может произойти. Если вы сделаете струны меньше, но все равно окажетесь на LOH - вы устраните проблему. Это зависит от того, сколько нужно обработать более 1 миллиона строк. Другой недостаток - вы все равно должны загрузить строку в память, чтобы разделить ее, так что в любом случае она заканчивается на LOH. Вам нужно сжать строки до того, как ваше приложение даже загрузит их. Вид улова-22. РЕДАКТИРОВАТЬ : Гейб в комментариях подчеркивает, что, если вы можете сначала загрузить свою строку в StringBuilder, под прикрытиями она приложит немало усилий, чтобы не пускать вещи в LOH (пока вы не вызовете ToString на нем).

    2. Разбейте обработку строки на отдельный процесс. Используйте процесс вместо потока. Используйте каждый процесс для обработки, скажем, 10K строк, затем завершите процесс и запустите другой. Таким образом, каждый процесс начинается с чистого листа. Преимущество этого в том, что он не меняет логику обработки строк (в случае, если вы не можете сделать ваши строки меньше для обработки) и избегает catch-22 в # 1. Недостатком является то, что это, вероятно, требует больших изменений в вашем приложении и координации работы между основным процессом и процессом подчиненного процесса. Хитрость в том, что мастер может только сказать ему, где находится большая строка, он не может передать ее напрямую, иначе вы вернетесь к ловушке-22.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...