Потоки Perl медленно используют память

Я выполняю сервер Perl с 10 потоками. Они никогда не уничтожаются до выходов программы, но это - что-то, что я намереваюсь иметь как можно больше времени работы, таким образом, вот почему это - проблема для меня. Потоки много раз справляются с простой задачей. Когда я запускаю сервер, и все потоки запускаются, я вижу, что у меня есть свободных 288,30 МБ. После пары повторений через каждый поток это сообщает о свободных 285,96 МБ. Это не настолько плохо.. возможно, это - просто некоторое выделяемое стековое пространство или что-то во время тех повторений. Но после 15 минут, свободная память снижается до 248,24 МБ! Что произошло с моей памятью?? Теперь, интересно, это ДЕЙСТВИТЕЛЬНО выравнивается. Это продолжает медленно использовать, но не так быстро как сначала. Я думал, возможно, что это был мой отказ, таким образом, я пытался проверить объем дважды всех своих переменных и даже не определить всех их в конце цикла потока.

Я распечатываю свободное пространство после КАЖДОГО повторения потоков, таким образом, я могу наблюдать, что оно медленно понижается. Теперь то, что также интересно, - то, что это не уменьшается каждый раз. Иногда свободная память остается такой же после итерации.

Я использую Perl 5.8.8 созданных из источника на Linux 2.6

У кого-либо есть какие-либо идеи вообще или даже предложения относительно того, что может вызывать это? Я полагаю, что обновление моего Perl к более поздней версии исключает утечку памяти в ядре Perl.

ОБНОВЛЕНИЕ: это могло быть проблемой размера стопки потока? Я мог выделять больше памяти для стека, чем мне нужно. Когда я создаю свои потоки, я не изменяю сходить со значения по умолчанию. Должен я? В документе потоков говорится, что значение по умолчанию обычно - 16 МБ в зависимости от системы. 16x10 threads=160MB->, который мог быть преступником. Мысли?

ОБНОВЛЕНИЕ: Я создал и установил Perl 5.12.1 и восстановил модули и все. Запущение скрипта приблизительно в течение часа теперь и вот - то, что я заметил. Использование памяти управляемо теперь, но не идеально.

  • Вначале сразу после порождения моих потоков, казалось, был немного ниже. Вниз от ~60-66MB, выделенного моим 10 потокам к ~45-50MB.
  • После некоторых повторений, их использования, увеличенного общим количеством 3 МБ (о том же как прежде).
  • До этой точки то, что я ожидал. Вся эта память заранее для порождения, и затем просто немного для переменных я использую в своих потоках. Это - первая часть, не любят. После выполнения в течение приблизительно 10 минут я теряю дополнительные 65 МБ! Почему это делает это? Если это уже выполнило итерации несколько раз прекрасный со всего 3 МБ, почему продолжают выделять?
  • Это работало в течение полутора часов в этой точке, и они не используют дополнительные 65 МБ больше, это - дополнительные 84 МБ!
  • Медленно требуется больше памяти, НО странная вещь состоит в том, что объем свободной памяти не уменьшает каждое повторение. Я распечатываю свободную память прежде и после каждого повторения, и это будет оставаться таким же некоторое время или колебаться + - вокруг определенного числа некоторое время и затем изменяться 5-10MB внезапно. Я не могу оставить это выполнение больше чем одним, вершины двух дней, потому что оно начинает быть рядом с 80/90% моей доступной памяти.

Есть ли какие-либо другие идеи? Кто-либо вообще я мог попробовать? Я уже - undef'ing все свои переменные.

ОБНОВЛЕНИЕ: Я действительно хочу продолжать перекомпилировать Perl с glibc как последнее прибежище, так как я нашел некоторые отчеты, что на некоторых разновидностях Linux он будет segfault. Таким образом, так как я в последний раз отправил, я исследовал далее возможность циклов в моих хешах. Найденный ничем. Таким образом, я провел последние несколько дней, анализируя мою подпрограмму и кэшируя что-либо, что привыкает в другом повторении. Много нового материала воссоздается, каждый раз и Perl не очищают все это даже если я явно undef все это. Таким образом, если это не будет сотрудничать, я просто не уничтожу его. Будет видеть при кэшировании моей справки объектов вообще. Отправит статистику использования памяти позже.

ОБНОВЛЕНИЕ: Гм, очень странный. Даже после кэширования моих данных, которые будут снова использованы позже, память повышается приблизительно на том же уровне. Это запускается выше теперь, потому что я кэшируюсь, но затем продолжаю подниматься даже при том, что это главным образом использует мои кэшируемые объекты. Это является озадачивающим. Угадайте, что пора дать 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. Странно я получаю то же поведение. Потеряйте блоки MBS за один раз, медленно. Мог бы попробовать Valgrind для наблюдения, почему я теряю его. В то время как я играл вокруг с чем-то еще, хотя я думал о чем-то еще. Мой сценарий создает и уничтожает (предположительно) много много сокетов SSL. Это возможный что широко используемый модуль, такой как IO:: Сокет:: SSL протекает немного? Или возможно OpenSSL? (Используя v0.9.8o). Попытка попытаться синхронизировать доступ к модулю SSL, чтобы видеть, имеет ли это какой-либо эффект, могла бы иметь проблемы с потоками, получающими доступ к нему.

ОБНОВЛЕНИЕ: Испытанная загрузка модулей отдельно в каждом потоке, более быстром использовании памяти. Испытанная блокировка областей с помощью функций сокета так только один поток за один раз использовала их, все еще потерянная память то же как прежде. Увеличенный число рабочих потоков от 4 до 10 с тем же самым объемом работы. Память не продлилась 30 минут. Приводит меня полагать, что это - или проблема Perl внутренне с ее реализацией потока или проблема стека (никакая предназначенная игра слов). Я пытался изменить размер стека с помощью созданного в методах потока, но том же результате. Попытка искать иначе. Возможно, более низкий уровень путь. Увеличение числа потоков заставляет память пойти, быстрее..., кажется, что-то с реализацией стека потоков или размером стека

ОБНОВЛЕНИЕ (9/15/2010): Найденный этим интересным лакомым кусочком в IO:: Сокет:: документ SSL...

Это - то, вследствие того, что циклическая ссылка требуется, чтобы делать IO:: Сокет:: SSL снабжает действие сокетом одновременно как ссылки шарика и объекты.

"Циклическая ссылка" ха? Другое возможное объяснение состоит в том, что эти сокеты все слоняются поблизости некоторое время даже при том, что я явно undef'd их. Попытка изучить Слабеет, чтобы видеть, делает ли это что-нибудь с сокетами. Сообщит, нахожу ли я что-нибудь интересным.

РЕШЕННЫЙ (9/16/2010): См. мой ответ, который я отправил содержащий решение

9
задан 16 revs, 2 users 98% 16 March 2011 в 00:32
поделиться

3 ответа

Ваш Perl устарел на 4 с половиной года. Обновитесь до 5.12. Просто найдите примечания к сборке 5.12 и посмотрите на тонну крупных улучшений потоков, которые могут просто волшебным образом решить вашу туманную проблему:

  • 5.12:: @_ и $_ больше не утекают под потоками (RT #34342 и #41138, также #70602, #70974)'
  • 5.10:: Под ithreads, regex в PL_reg_curpm теперь считается по ссылкам. Это избавляет от множества хакерских обходных путей, чтобы справиться с тем, что он не учитывает ссылки.
  • 5.9:: threads: Несколько исправлений, например, для проблем с join() и утечек памяти. На некоторых платформах (например, Linux), использующих glibc, минимальный объем памяти для одного потока был уменьшен на несколько сотен килобайт.
  • 5.9:: threads::shared Было исправлено множество утечек памяти.

Я имею в виду, что список просто продолжается, когда вы говорите о четырех годах разработки thead и широком спектре вещей, которые могут вызвать эту проблему, посмотрите современный журнал изменений threads::shared

Я прокомментировал ваше сообщение, это был бы мой следующий набор предложений: Если вы не используете glibc и используете perl malloc (по умолчанию), вы никогда не будете освобождать память для ОС. Размер процесса будет представлять максимальный размер, который perl занимал каждый раз. Попробуйте перестроиться с помощью glibc malloc (требует перекомпиляции) и посмотрите, не изменится ли при этом профиль памяти. В остальном, пришло время показать код.

15
ответ дан 4 December 2019 в 09:11
поделиться

Попробуйте обновить threads.pm и threads::shared. Обновление до версии perl 5.12.1 также является хорошей идеей.

1
ответ дан 4 December 2019 в 09:11
поделиться

Я столкнулся с той же проблемой в версии 5.10, и, несмотря на многочисленные заявления о том, что более новый Perl не утекает память при использовании потоков, Perl утекал память при использовании потоков.

Моим решением было использовать Thread::Pool::Simple для создания пула потоков и использовать его вместо создания новых потоков. В моем случае я не ожидал, что у меня будет много одновременных потоков, и что они будут длиться долго (может быть, максимум 30 секунд). Я не знаю, подходит ли это для вас, но если вы действительно хотите, чтобы ваши потоки выполняли простые задачи, это может быть возможно.

1
ответ дан 4 December 2019 в 09:11
поделиться
Другие вопросы по тегам:

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