Утечка памяти в приложении узла - как исследовать на Mac OS X?
У меня есть приложение с билдом restify.js
и я обнаружил утечку памяти. Мне повезло, потому что утечка памяти "тяжелая", и я могу легко ее воспроизвести. Он ведет себя одинаково на моем локальном Mac и на Heroku, где размещено приложение. В качестве доказательства приведем статистику использования памяти из дополнения Librato на Heroku:
Использование памяти увеличивается, когда я делаю запросы:). К сожалению, я не могу отследить, где именно происходит утечка памяти... Это происходит для всех маршрутов / конечных точек, однако память растет быстрее, когда запрос занимает больше времени для завершения... В любом случае я могу использовать пробники restify.js dtrace, но только для получения промежуточного программного обеспечения / задержка обработчика. Я использую следующий скрипт DTRACE:
#!/usr/sbin/dtrace -s
#pragma D option quiet
restify*:::route-start
{
track[arg2] = timestamp;
}
restify*:::handler-start
/track[arg3]/
{
h[arg3, copyinstr(arg2)] = timestamp;
}
restify*:::handler-done
/track[arg3] && h[arg3, copyinstr(arg2)]/
{
@[copyinstr(arg2)] = quantize((timestamp - h[arg3, copyinstr(arg2)]) / 1000000);
h[arg3, copyinstr(arg2)] = 0;
}
restify*:::route-done
/track[arg2]/
{
@[copyinstr(arg1)] = quantize((timestamp - track[arg2]) / 1000000);
track[arg2] = 0;
}
И вывод для скрипта, например:
handler-4
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
pre_apiVersion
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
pre_authenticate
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
pre_restifyCors
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
pre_restifyFullResponse
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
use_authorize
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
use_errors
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
use_language
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
use_modules
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
use_restifyBodyParserParseBody
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
use_restifyBodyParserReadBody
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
use_restifyQueryParser
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
use_restifyRequestLogger
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
use_validate
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 7
1 | 0
pre
value ------------- Distribution ------------- count
-1 | 0
0 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 6
1 |@@@@@@ 1
2 | 0
use_restifyGzipResponse
value ------------- Distribution ------------- count
0 | 0
1 |@@@@@@ 1
2 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 6
4 | 0
handler
value ------------- Distribution ------------- count
16 | 0
32 |@@@@@@@@@@@ 2
64 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 5
128 | 0
route_module_list001
value ------------- Distribution ------------- count
16 | 0
32 |@@@@@@@@@@@ 2
64 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 5
128 | 0
Мои вопросы:
Есть ли возможность написать этот сценарий DTRACE, чтобы не считать задержки, а считать разницу в использовании памяти? Тогда я мог бы проверить каждое промежуточное ПО, сколько памяти он выделяет? Хм, я думаю, Javascript в V8 выделяет память в пакетах только при необходимости, я прав?
Может быть, у вас есть другие идеи, как исследовать эту утечку памяти? Я попытался прокомментировать некоторые промежуточные программы и так далее, но все еще не могу найти источник проблемы:(.
РЕДАКТИРОВАТЬ: здесь сравниваются два снимка кучи - первый выполняется после 1 запроса, а второй после 100 запросов. Кто-нибудь может сказать мне, что это значит?