Я использую Perl-сервер с 10 потоками. Они никогда не будут уничтожены, пока программа не выйдет, но это то, что я намереваюсь иметь как можно больше времени безотказной работы, поэтому для меня это проблема. Потоки выполняют простую задачу много раз. Когда я запускаю сервер и запускаются все потоки, я вижу, что у меня свободно 288,30 МБ. После нескольких итераций в каждом потоке он освобождает 285,96 МБ. Это не так уж и плохо ... может быть, это просто выделение некоторого стекового пространства или что-то подобное во время этих итераций. Но через 15 минут объем свободной памяти уменьшается до 248,24 МБ! Что случилось с моей памятью? Теперь, что интересно, это плато. Он продолжает медленно потреблять, но не так быстро, как поначалу. Я подумал, что, возможно, это была моя ошибка, поэтому я попытался дважды проверить область действия всех моих переменных и даже отменить их определение в конце цикла потока.
Я распечатываю свободное пространство после КАЖДОЙ итерации потоков, чтобы я мог наблюдать, как оно медленно уменьшается. Что еще интересно, это то, что оно не уменьшается каждый раз. Иногда свободная память остается неизменной после итерации.
Я использую Perl 5.8.8, собранный из исходного кода в Linux 2.6
Кто-нибудь имеет какие-либо идеи или даже предложения относительно того, что может быть причиной этого? Я рассматриваю возможность обновления моего Perl до более поздней версии, чтобы исключить утечку памяти в ядре Perl.
ОБНОВЛЕНИЕ: Может ли это быть проблемой размера стека потока? Могу ли я выделить больше памяти для стека, чем мне нужно. Когда я создаю свои темы, я не изменяю настройку по умолчанию. Нужно ли мне? Документ по потокам говорит, что по умолчанию обычно 16 МБ, в зависимости от системы. 16x10 потоков = 160MB -> что может быть виновником. Мысли?
ОБНОВЛЕНИЕ: Я собрал и установил Perl 5.12.1, перестроил модули и все остальное. Уже около часа запускаю скрипт, и вот что я заметил. Использование памяти теперь управляемо, но не идеально.
- В начале, сразу после нереста, мои темы казались немного ниже. По сравнению с ~ 60-66 МБ, выделенными для моих 10 потоков, до ~ 45-50 МБ.
- После некоторых итераций их использование увеличилось на 3 МБ (примерно так же, как и раньше).
- До этого момента я ожидал. Вся эта память заранее для порождения, а затем немного для переменных, которые я использую в своих потоках. Эта часть мне не нравится. После 10 минут работы я теряю дополнительные 65 МБ! Почему он это делает? Если он уже повторялся несколько раз, всего лишь 3 МБ, зачем продолжать выделять?
- На данный момент он работает полтора часа, и они больше не используют дополнительные 65 МБ, это дополнительные 84 МБ!
- Медленно требуется больше памяти, НО странно то, что объем свободной памяти не уменьшается с каждой итерацией. Я распечатываю свободную память до и после каждой итерации, и она некоторое время остается неизменной или некоторое время колеблется + - вокруг определенного числа, а затем внезапно изменяется на 5-10 МБ. Я не могу оставить эту работу более чем на два дня, потому что она начинает приближаться к 80/90% моей доступной памяти.
Есть еще идеи? Кто-нибудь вообще мог попробовать? Я уже отменяю все свои переменные.
ОБНОВЛЕНИЕ: Я действительно хочу продолжить перекомпиляцию Perl с помощью glibc в качестве крайней меры, так как я нашел несколько сообщений о том, что в некоторых версиях Linux он будет зависать. Так что с тех пор, как я в последний раз писал, я продолжил исследовать возможность циклов в моих хэшах. Ничего не нашел. Поэтому я провел последние несколько дней, анализируя свою подпрограмму и кэшируя все, что используется в другой итерации. Многие новые вещи воссоздаются каждый раз, и Perl не очищает все это, даже если я явно отменяю все это. Так что, если он не будет сотрудничать, я просто не уничтожу его. Посмотрим, поможет ли кэширование моих объектов вообще. Опубликуем статистику использования памяти позже.
ОБНОВЛЕНИЕ: Хм, очень странно.Даже после кэширования моих данных для последующего использования память увеличивается примерно с той же скоростью.Сейчас он начинается выше, потому что я кеширую, но затем продолжает расти, хотя в основном использует мои кэшированные объекты.Это озадачивает.Полагаю, пришло время попробовать glibc ... или же это всего лишь недостаток выбора Perl, и придется перезагружать сервер каждые пару дней.
ОБНОВЛЕНИЕ: Пробовал безкеширование, без glibc, сноваПрекрасно работает какое-то время, несколько часов, потом начинает расти.Просто хотел, чтобы вы увидели график.
http://tinypic.com/r/311nc08/3
http://i32.tinypic.com/311nc08.jpg
ОБНОВЛЕНИЕ: Вот выдержка из журнала, документирующего свободную память до и после каждого потока послеоколо минутыМожет быть, это поможет кому-то лучше понять проблему.Кажется, что он немного стабилен, а потом время от времени съедает больше памяти.Здесь я теряю почти 40 МБ!
[9:8:30, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 253.812736MB (obj cache: 136)
[9:8:30, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 253.812736MB (obj cache: 136)
[9:8:34, Fri Jul 23, 2010] [204] Sending data to thread
[9:8:34, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:8:34, Fri Jul 23, 2010] [206] Sending data to thread
[9:8:34, Fri Jul 23, 2010] [0] 4 - Creating a new obj
[9:8:35, Fri Jul 23, 2010] [0] Memory usage at end thread 3: 253.812736MB (obj cache: 136)
[9:8:35, Fri Jul 23, 2010] [0] Memory usage at idle thread 3: 253.812736MB (obj cache: 136)
[9:8:35, Fri Jul 23, 2010] [0] Memory usage at end thread 4: 253.812736MB (obj cache: 136)
[9:8:35, Fri Jul 23, 2010] [0] Memory usage at idle thread 4: 253.812736MB (obj cache: 136)
[9:8:41, Fri Jul 23, 2010] [225] Sending data to thread
[9:8:41, Fri Jul 23, 2010] [0] 2 - Creating a new obj
[9:8:42, Fri Jul 23, 2010] [0] Memory usage at end thread 2: 253.681664MB (obj cache: 136)
[9:8:42, Fri Jul 23, 2010] [0] Memory usage at idle thread 2: 253.681664MB (obj cache: 136)
[9:8:47, Fri Jul 23, 2010] [243] Sending data to thread
[9:8:47, Fri Jul 23, 2010] [0] 1 - Creating a new obj
[9:8:48, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 253.935616MB (obj cache: 136)
[9:8:48, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 253.935616MB (obj cache: 136)
[9:9:1, Fri Jul 23, 2010] [277] Sending data to thread
[9:9:1, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:2, Fri Jul 23, 2010] [280] Sending data to thread
[9:9:2, Fri Jul 23, 2010] [0] 4 - Creating a new obj
[9:9:2, Fri Jul 23, 2010] [0] Memory usage at end thread 3: 253.935616MB (obj cache: 136)
[9:9:2, Fri Jul 23, 2010] [0] Memory usage at idle thread 3: 253.935616MB (obj cache: 136)
[9:9:3, Fri Jul 23, 2010] [283] Sending data to thread
[9:9:3, Fri Jul 23, 2010] [0] 2 - Creating a new obj
[9:9:4, Fri Jul 23, 2010] [284] Sending data to thread
[9:9:4, Fri Jul 23, 2010] [0] 1 - Creating a new obj
[9:9:4, Fri Jul 23, 2010] [0] Memory usage at end thread 2: 253.935616MB (obj cache: 136)
[9:9:4, Fri Jul 23, 2010] [0] Memory usage at idle thread 2: 253.935616MB (obj cache: 136)
[9:9:5, Fri Jul 23, 2010] [287] Sending data to thread
[9:9:5, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:5, Fri Jul 23, 2010] [0] Memory usage at end thread 4: 253.93152MB (obj cache: 136)
[9:9:5, Fri Jul 23, 2010] [0] Memory usage at idle thread 4: 253.93152MB (obj cache: 136)
[9:9:6, Fri Jul 23, 2010] [290] Sending data to thread
[9:9:6, Fri Jul 23, 2010] [0] 2 - Creating a new obj
[9:9:7, Fri Jul 23, 2010] [0] Memory usage at end thread 3: 253.804544MB (obj cache: 136)
[9:9:7, Fri Jul 23, 2010] [0] Memory usage at idle thread 3: 253.804544MB (obj cache: 136)
[9:9:7, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 253.804544MB (obj cache: 136)
[9:9:7, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 253.804544MB (obj cache: 136)
[9:9:9, Fri Jul 23, 2010] [0] 4 - Creating a new obj
[9:9:9, Fri Jul 23, 2010] [301] Sending data to thread
[9:9:9, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:9, Fri Jul 23, 2010] [302] Sending data to thread
[9:9:9, Fri Jul 23, 2010] [0] 1 - Creating a new obj
[9:9:10, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:11, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:11, Fri Jul 23, 2010] [0] Memory usage at end thread 4: 253.93152MB (obj cache: 136)
[9:9:11, Fri Jul 23, 2010] [0] Memory usage at idle thread 4: 253.93152MB (obj cache: 136)
[9:9:12, Fri Jul 23, 2010] [308] Sending data to thread
[9:9:12, Fri Jul 23, 2010] [0] 4 - Creating a new obj
[9:9:13, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 253.804544MB (obj cache: 136)
[9:9:13, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 253.804544MB (obj cache: 136)
[9:9:14, Fri Jul 23, 2010] [0] Memory usage at end thread 4: 253.804544MB (obj cache: 136)
[9:9:14, Fri Jul 23, 2010] [0] Memory usage at idle thread 4: 253.804544MB (obj cache: 136)
[9:9:14, Fri Jul 23, 2010] [0] Memory usage at end thread 3: 253.93152MB (obj cache: 136)
[9:9:14, Fri Jul 23, 2010] [0] Memory usage at idle thread 3: 253.93152MB (obj cache: 136)
[9:9:15, Fri Jul 23, 2010] [313] Sending data to thread
[9:9:15, Fri Jul 23, 2010] [0] 1 - Creating a new obj
[9:9:16, Fri Jul 23, 2010] [0] Memory usage at end thread 2: 214.482944MB (obj cache: 136)
[9:9:16, Fri Jul 23, 2010] [0] Memory usage at idle thread 2: 214.482944MB (obj cache: 136)
[9:9:16, Fri Jul 23, 2010] [315] Sending data to thread
[9:9:16, Fri Jul 23, 2010] [0] 4 - Creating a new obj
[9:9:17, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 214.355968MB (obj cache: 136)
[9:9:17, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 214.355968MB (obj cache: 136)
[9:9:18, Fri Jul 23, 2010] [316] Sending data to thread
[9:9:18, Fri Jul 23, 2010] [0] 3 - Creating a new obj
[9:9:18, Fri Jul 23, 2010] [317] Sending data to thread
[9:9:18, Fri Jul 23, 2010] [0] 2 - Creating a new obj
[9:9:18, Fri Jul 23, 2010] [318] Sending data to thread
[9:9:18, Fri Jul 23, 2010] [0] 1 - Creating a new obj
[9:9:19, Fri Jul 23, 2010] [0] Memory usage at end thread 4: 214.355968MB (obj cache: 136)
[9:9:19, Fri Jul 23, 2010] [0] Memory usage at idle thread 4: 214.355968MB (obj cache: 136)
[9:9:19, Fri Jul 23, 2010] [0] Memory usage at end thread 1: 214.355968MB (obj cache: 136)
[9:9:19, Fri Jul 23, 2010] [0] Memory usage at idle thread 1: 214.355968MB (obj cache: 136)
[9:9:20, Fri Jul 23, 2010] [0] Memory usage at end thread 3: 214.482944MB (obj cache: 136)
[9:9:20, Fri Jul 23, 2010] [0] Memory usage at idle thread 3: 214.482944MB (obj cache: 136)
[9:9:20, Fri Jul 23, 2010] [0] Memory usage at end thread 2: 214.482944MB (obj cache: 136)
[9:9:20, Fri Jul 23, 2010] [0] Memory usage at idle thread 2: 214.482944MB (obj cache: 136)
ОБНОВЛЕНИЕ (8/12/2010): Просто запустил его на один день с новой скомпилированной версией Perl 5.12 с потоками и системой malloc.Странно, я получаю такое же поведение.Потеряйте куски МБ за один раз, медленно.Можешь попробовать Вальгринда, чтобы понять, почему я его теряю.Пока я играл с чем-то другим, я думал о чем-то другом.Мой скрипт создает и уничтожает (якобы) много SSL-сокетов.Возможно ли, что широко используемый модуль, такой как IO :: Socket :: SSL, немного просачивается?Или, может быть, OpenSSL?(Используя v0.9.8o).Попытка синхронизации доступа к модулю SSL, чтобы увидеть, имеет ли он какой-либо эффект, может иметь проблемы с доступом к нему потоков.
ОБНОВЛЕНИЕ: Попытка загрузки модулей отдельно в каждом потоке, более быстрая памятьиспользование.Попытка блокировки областей с использованием функций сокетов, чтобы их использовал только один поток, все равно теряла память так же, как и раньше.Увеличено количество рабочих потоков с 4 до 10 при одинаковом объеме работы.Память не длилась 30 минут.Приводит меня к мысли, что это либо внутренняя проблема Perl с его реализацией потока, либо проблема стека (без каламбура).Я попытался изменить размер стека, используя встроенные методы потока, но тот же результат.Собираюсь искать другой путь.Может быть, путь более низкого уровня.Увеличение количества потоков заставляет память работать быстрее ... кажется, что-то с реализацией стека потоков или размером стека
ОБНОВЛЕНИЕ (15.09.2010): Нашел этот интересный кусок в документе IO :: Socket :: SSL ...
Это связано с тем, что для одновременной работы сокетов IO :: Socket :: SSL требуется циклическая ссылкакак объекты и глобальные ссылки.
"Циркулярная ссылка", а?Другое возможное объяснение состоит в том, что все эти сокеты некоторое время торчат, хотя я явно их не нашел.Собираюсь заглянуть в Weaken, чтобы узнать, что это делает с сокетами.Дадим вам знать, если я найду что-нибудь интересное.
РЕШЕНО (16.09.2010): См. Мой ответ, который я отправил, содержащий решение