У меня есть веб-сервис RESTful на основе Kemal, который возвращает «очень большие» (размером от 10 до 17M) порции данных JSON, которые создаются методом to_json из «большой» структуры Hash.
Согласно предупреждающим сообщениям GC, мой код "может привести к утечкам памяти", а мои собственные измерения показывают, что память "протекает" во время выполнения приложения.
Так что, я думаю, это будет хорошоосвободить память, выделенную для хэша, и ее JSON-строки для представления вручную, но я не знаю, как это сделать: мои эксперименты с плохо документированным методом GC.free не увенчались успехом, и я не знаю, в каком направлении продолжать свои исследования...
Скажите, пожалуйста, что я могу сделать, чтобы избежать утечек памяти?
Вы можете посмотреть не очень свежую, но в целом актуальную версию моего очень простого приложения(фактически он был разработан в закрытом сегменте корпоративной сети) здесь https://github.com/DRVTiny/Druid/blob/master/src/druid_mp.cr
Код, который приводит к утечкам памяти:
get "/service/:serviceid" do |env|
if (svcid = env.params.url["serviceid"]) && svcid.is_a?(String) && svcid =~ /^s?\d+$/
druid.svc_branch_get((svcid[0] == 's' ? svcid[1..-1] : svcid).to_i).to_json
else
halt env, status_code: 404, response: %q({"error": "Wrong service identificator"})
end
rescue ex
halt env, status_code: 503, response: {"error": "Unhandled exception #{ex.message}"}.to_json
end
PS Я вставил ловушку after_all, выполняющую GC.collect послекаждый запрос пользователя.Не знаю, возможно, это может решить мою проблему (но я думаю, что это совсем не так).
UPD: После того, как я добавил GC.collect в ловушку after_all Kemal - утечки памяти исчезают.Но глобальный GC.collect, вероятно, слишком медленный и, как я знаю, он блокирует все волокна и socket.accept ().Пожалуйста, дайте мне знать, если я ошибаюсь.