Мой первый вопрос по StackOverflow (после многих лет чтения различных тем).
Мне особенно трудно решить эту проблему, поэтому приветствуется любая помощь.
Я бегу много (50+) экземпляров вычислительно дорогостоящих. Net Ядро на Linux.
На машине достаточно ядер (64 ядра) и примерно 500 ГБ ОЗУ.
I есть один простой метод:
public static void Compute(Message m) {
// Does a lot of computation, memory allocation here
// All root objects are set to null at end (just to really make it clear!)
}
Этот метод вызывается несколько раз для каждого из 50+ экземпляров.
Я обнаружил, что объем памяти каждого процесса (в частности, VIRT с использованием top) продолжает увеличиваться после каждой итерации. В конце концов, каждый процесс пытается освободить память, но в целом доступная память для всей машины чрезвычайно мала (<1-2%). Наконец, запускаются сборщики мусора, но чрезвычайно низкий (иногда 0%) доступный объем памяти вызывает множество проблем в моих вычислениях, и некоторые из экземпляров «застревают» - в основном останавливаются и больше не выполняют никаких вычислений или прослушивания внешних событий. </p>
Я повторил тот же эксперимент, используя поддельный код, который просто обрабатывает числа и выделяет большие объемы памяти, и вижу тот же образец.
Я пробовал эти вещи (по отдельности и вместе ):
- Создание отдельного потока «жнеца», который вызывает G C .Collect (3, CollectionMode.Forced, true, true), et c.
- Обнуление каждого временного объекта в вычислении и немедленный вызов G C .Collect ()
- Резкое уменьшение количества экземпляров
Ни один из них не работал, и я довольно застрял.
Похоже, что. Net «держится» за память, если в ней нет крайней необходимости, но к тому времени уже слишком поздно, так как все другие экземпляры также делают то же самое . В конце концов, это вызывает большой G C всеми процессами, а затем я получаю проблему с мертвой / остановкой (некоторые экземпляры могут быть в процессе запуска потока или в сложной композиции LINQ) и просто молча d ie.
Технически, все созданные объекты и временные объекты не имеют корней и должны быть помечены как G C -able, но это не происходит плавно и периодически, как мне бы хотелось. Более того, вычисления существуют в совершенно другом методе, для которого нет никакой информации о состоянии, которая вообще сохраняется в других объектах.
Тем не менее, память просто продолжает падать и сбрасываться, пока доступная память не станет чрезвычайно низкой.
Если бы я написал это на C, я бы сделал malloc / free, и память сбрасывалась бы после каждой итерации метода Compute (). Наконец, я не понимаю, что проблема заключается в endemi c to Linux, я наблюдаю такое же поведение (для одного экземпляра) и на Windows.
Заранее благодарим вас за ваши предложения.
В ответ на некоторые комментарии: 1. Я пробовал все виды режима G C .Collect () - принудительный, блокирующий, большой объект и т. Д. c., Gens 0-2 - некоторые незначительные различия, но ничего, что могло бы обеспечить комфорт для стабильного вычислительного процесса - 2) Я пробовал как рабочую станцию (сначала меньше - затем достигло того же состояния), так и сервер