c # многопоточность использования памяти - приложение замедляется и загрузка процессора падает - PullRequest
3 голосов
/ 11 сентября 2010

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

Затем этот многопоточный процесс запускается, он запускается очень быстро и загрузка ЦП составляет 60% для 5 ядер, физическая память составляет 50% от объема ОЗУ. (Информация из диспетчера задач). После того, как он проходит около 1/3 пути, он начинает замедляться и загрузка ЦП падает чуть ниже 20%. К тому времени, когда он достигает 2 / 3с пути, он настолько медленный, что для завершения последней трети требуется 1 день, а для первой 1/3 - полчаса.

В процессе создается много сортированных списков и списков, поэтому я начинаю подозревать, что сборщик мусора не справляется, хотя использование памяти диспетчера задач не так уж и плохо ... Я хочу попытаться заставить GC освободить неиспользованные коллекции сразу, это разумно или даже выполнимо? И почему загрузка ЦП снижается?

Ответы [ 5 ]

1 голос
/ 11 сентября 2010

Я полагаю, что добавление большого количества элементов в сильно загруженную коллекцию не так эффективно, как могло бы быть. Я заметил нечто похожее со старым запросом SQL - 100 записей в наборе записей были быстрыми, но полмиллиона записей замедлили экспоненциально.

Чтобы проверить GC, запустите perfmon и просмотрите (или зарегистрируйте) счетчики производительности для сборщика мусора и выделения памяти.

1 голос
/ 11 сентября 2010

Похоже на проблему блокировки структуры данных.Трудно сказать, не зная точно, что вы делаете.

Попробуйте использовать одну из несмежных несмежных коллекций, таких как ConcurrentDictionary или ConcurrentBag, и / или подходящую очередь типа BlockingCollection.

1 голос
/ 11 сентября 2010

Принудительно запускать сборщик мусора - это всегда плохая идея.(В некоторых случаях принудительное выполнение этого может привести к увеличению продолжительности жизни объектов)

Загрузите инструмент, такой как Memprofiler , Ants или dotTrace (все они имеют пробные версии), чтобы определить, нет ли у вас утечки памяти.Вы выделяете объекты размером более 85 КБ?

Кроме того, какую версию ОС и .NET Framework вы используете?(были различия в том, как работали версии GC для сервера и ПК)

Кроме того, помните, что вставка в SortedList - это O (N) (тогда как вставка SortedDictionary - это O (logN):

Универсальный класс SortedList представляет собой двоичное дерево поиска с поиском O (log n), где n - количество элементов в словаре, в этом он похож на универсальный класс SortedDictionary. Оба класса имеютаналогичные объектные модели, и обе имеют поиск O (log n). Эти два класса различаются в использовании памяти и скорости вставки и удаления:

  • SortedList использует меньше памяти, чем SortedDictionary.

  • SortedDictionary имеет более быстрые операции вставки и удаления для несортированных данных, O (log n), а не O (n) для SortedList.

  • Еслисписок заполняется сразу из отсортированных данных, SortedList работает быстрее, чем SortedDictionary.

Ref .

Как вы управляетемногомногопоточный доступ к этим спискам?Можете выложить какой-нибудь урезанный код?

0 голосов
/ 11 сентября 2010

60% CPU на 5 ядрах из 5 потоков.Я предполагаю, что это 60% на каждое ядро.Это на самом деле очень плохо.Вы не можете довести процессор до 100%, выполняя только операции с памятью (без базы данных, без сети, без ввода-вывода файлов), это означает, что ваша конкуренция за блокировку огромна.По мере выполнения программы ваши структуры, вероятно, увеличиваются в размере (больше элементов в некоторых списках / словарях), вы дольше удерживаете блокировки, и в результате уменьшается загрузка ЦП и даже снижается производительность.

Трудно сказать без каких-либо реальных данных о производительности, но это не похоже на GC.Это больше похоже на высокую конкуренцию в структурах данных.Вы должны проследить свое приложение под профилировщиком и посмотреть, где процессор / время ожидания тратится больше всего.См. Определение проблем с производительностью с помощью hotpath в Visual Studio 2008 для быстрого ознакомления с профилировщиком выборки.

0 голосов
/ 11 сентября 2010

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

...