LINUX.ORG.RU

Серверное приложение на Haskell: что происходит с памятью.

 


1

3

Здравствуйте.

Есть сервер, который на скорости в 10 qps (в будущем может и поболее) обрабатывает короткие запросы. В самом начале он кушает 8032 КБ по показаниям RSS, через сутки или даже поболее — 15980 КБ.

Является ли подобное поведение свидетельством утечки или это норма для GC и программ на Haskell?


Память в сервер за рубли, поди, покупал?

Может быть и GC, помноженный на ленивость, тогда объём используемой памяти стабилизируется. Может быть и утечка через неотпущенные референсы на ненужные объекты.

mv ★★★★★
()

А под нагрузкой погонять не пробовали? Если утечка, то ещё и не то отожрет.

Weres ★★★
()

профилировка и смотреть на графики, если ничего не течет - то роста памяти быть не должно.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

обычно можно получить утечки из-за просто ошибки в коде, ленивости, ссылок на bytestring. Для внутренних данных в программе крайне не рекомендуется использовать ByteStrings, а использовать или ShortByteString (если они короткие) или Text или Vector.Primitive Char8 в зависимости от задачи, если все же нужно ByteString то ни в коем случае не забывать сделать copy перед тем как их хранить. Ещё если ты хранишь хэндлеры легких процессов, то память выделенная под них (сколько там минимальный стек дается) тоже не будет освобождена до тех пор пока хэндлы живы.

Вот, как-то так.

qnikst ★★★★★
()

Потестируй локально на 1000qps.

anonymous
()
Ответ на: комментарий от qnikst

ни в коем случае не забывать сделать copy

Т.е. скопировать полученное извне значение и уже его использовать дальше в программе? Ок, понял.

Я как раз думал, что если ByteString — эффективная штука, с которой можно быстро работать, то и следует их использовать. Не со String же возиться было…

Почитал про ShortByteString, понял. Да, отчасти, видимо, в этом проблема. Буду решать.

Спасибо всем ответившим. Тему не закрываю, посмотрю, что профилировщик покажет.

HolyBoy
() автор топика
Ответ на: комментарий от HolyBoy

Т.е. скопировать полученное извне значение и уже его использовать дальше в программе? Ок, понял.

Не совсем. Copy нужен чтобы освободить память, если ты вытаскиваешь небольшую подстроку из строки. Если ты хранишь полученные данные полностью или не хранишь их вообще, то copy не поможет.

hateyoufeel ★★★★★
()
Ответ на: комментарий от HolyBoy

Я как раз думал, что если ByteString — эффективная штука, с которой можно быстро работать, то и следует их использовать. Не со String же возиться было…

ByteString очень эффективная штука, но я одной очень интересной проблемой - она использует PinnedMemory [1]. Соотвественно gc не может перемещать блоки из pinned memory, т.к. на них могут ссылкаться переменные из foreign кода или вызовов, что приводит к фрагментации памяти. Более того, весь блок не может быть освобожден пока байтострока держится в памяти, конечно сейчас используется стратегия, при которой перемещаемые и неперемещаемые обьекты стараются хранить в разных блоках, но это не всегда спасает, соотвественно ShortByteStrings, Vector.Primitive, Text тут помогают.

Более того, вся строгая байтстрока не может быть осводождена если есть хоть одна ссылка на неё, т.е. напр. если ты считал от клиента 4096байт, и сделал slice 8ми байт, то все строка будет держаться в памяти пока slice не освободится (против этого спасает copy). Ленивые байтостроки частично уменьшают проблему, т.к. в них чанк на который никто не ссылается может быть удален.

Про профилировщик помогу и текстовый отчет по статистике, можно увидеть, что какая-то функция выделяет больше, чем ожидается, так и график потребления памяти.

[1] https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/GC/Pinned

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Смущает, что собраны данные только за 1.5 секунды, хотя процесс висел гораздо дольше. Это нормально?

Нормой, как понимаю, должно быть поведение, например, как у Network.Wai или LDAP или аналогичных данных.

HolyBoy
() автор топика
Последнее исправление: HolyBoy (всего исправлений: 2)
Ответ на: комментарий от HolyBoy

Это процессорное время, так что нормально.

unC0Rr ★★★★★
()
Ответ на: комментарий от qnikst

Переписал часть приложения, оставив ByteString только на входе в приложение и на выходе. Теперь, картинка такая:

http://tinypic.com/r/2znpq2p/8

Хоть RSS и растёт потихоньку, видимо, это вполне ограниченный рост будет. Запущу сейчас его надолго, чтобы посмотреть, сколько за несколько часов утечёт, если утечёт.

HolyBoy
() автор топика
Последнее исправление: HolyBoy (всего исправлений: 1)
Ответ на: комментарий от HolyBoy

теперь похоже на правду, но гадать по кофейной гуще о том, можно ли сделать что-либо лучше тяжело :)

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Я имел в виду, что на питоне написать что-то, что жрёт меньше 16 мегабайт это еще сильно уметь надо, потому предложение перейти писать на «нормальных языках» получается не очень логичным.

kost-bebix ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.