Skip to content

Commit

Permalink
Update from 2025-02-01T13:03:55.154551Z
Browse files Browse the repository at this point in the history
  • Loading branch information
svetlyak40wt committed Feb 1, 2025
1 parent 93e5011 commit 4601200
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
54 changes: 54 additions & 0 deletions raw/channel/1002102092834/msg-14.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"message_id": 55,
"from": {
"id": 76226374,
"is_bot": false,
"first_name": "Alexander ƛrtemenko",
"last_name": "svetlyak40wt",
"username": "svetlyak40wt",
"language_code": "en",
"is_premium": true
},
"date": 1738415033,
"chat": {
"id": 76226374,
"type": "private",
"username": "svetlyak40wt",
"first_name": "Alexander ƛrtemenko",
"last_name": "svetlyak40wt"
},
"forward_origin": {
"type": "channel",
"date": 1737192361,
"chat": {
"id": -1002102092834,
"type": "channel",
"title": "40 Ants – новости про проекты студии, IT, программирование и много ❤️ к Common Lisp",
"username": "the40ants"
},
"message_id": 14
},
"text": "Почему GC SBCL может не освобождать память?\n\nПоследнее время я работаю над новой версией фреймфорка для создания Telegram ботов. Этот фреймворк использует библиотеку реализующую акторы. И нем обнаружился досадный баг, который я намеревался исправить. Однако в процессе исправления оказалось, что оно может повлиять на производительность. Хорошо что у автора отыскался benchmark с помощью которого можно проверить скорость работы актора.\n\nК моему удивлению этому бенчмарку не хватало 4G памяти для хоть сколько-нибудь длительной работы. Более того, если бенчмарк запустить ненадолго, то оказывалось, что после его работы процесс \"толстел\" на 2.5G и не отпускал эту память до тех пор, пока не сделаешь вручную (sb-ext:gc :full t).\n\nЭто поведение показалось крайне странным. Как вообще можно использовать это язык в production, если он не отпускает память!?\n\nТак я оказался втянут в исследование того, почему garbage collector SBCL не очищает кучу мусора оставшуюся после теста.\n\nПрошло три дня.\n\nПосле некоторых исследований у меня появилась гипотеза, почему GC не очищает память.\n\nДело в том, что в бенчмарке N потоков генерят сообщения к одному актору. Если актор не успевает разгребать сообщения, то те накапливаются в очереди. Тест заканчивается, когда все сообщения в очереди обработаны.\n\nКогда в очереди много сообщений и срабатывает GC, то он видит, что на эти сообщения есть ссылки, и не может их подчистить, а потому перекладывает эти объекты в более старшее поколение. И чем дольше разгребается очередь в процессе генерации объектов, тем больше таких объектов оказывается в старших поколениях garbage collector.\n\nКогда тест заканчивается, то ссылок на сообщения уже нет, но из-за того, что GC поместил их в старшие поколения, при регулярных запусках он до этих объектов не добирается и они так и остаются висеть в памяти. А вот (gc :full t) их подбирает и подчищает.\n\nКак я это понял? Хотелось бы ответить: \"Очень просто!\", но нет \uD83D\uDE41\n\nСначала я решил поисследовать природу объектов, остающихся висеть в памяти после бенчмарка и написал вот такую функциюЖ\n\n\n(defun get-random-dynamic-object ()\n (let ((count 0))\n (sb-vm:map-allocated-objects (lambda (obj type size)\n (declare (ignore obj type size))\n (incf count))\n :dynamic)\n (let ((random-idx (random count))\n (found-obj nil)\n (current-idx 0))\n (sb-vm:map-allocated-objects (lambda (obj type size)\n (declare (ignore type size))\n (when (= current-idx random-idx)\n (setf found-obj\n (trivial-garbage:make-weak-pointer obj)))\n (incf current-idx))\n :dynamic)\n (values found-obj\n random-idx\n count))))\n\n\nона достает из памяти случайны объект и возвращает weak указатель на него. Почему weak указатель? Чтобы не возникло лишней ссылки\nна объект.\n\nВыяснилось, что значительная часть объектов, это сообщения из очереди актора:\n\n\n#<weak pointer: (#<ACTOR path: /user/actor-365, cell: #<ACTOR actor-365, running: NIL, state: NIL, message-box: #<MESSAGE-BOX/BT mesgb-366, processed messages: 8000001, max-queue-size: 0, queue: #<QUEUE-UNBOUNDED {70050E0113}>>>>\n NIL NIL)>\n\n\nДалее я попытался выяснить а не держит ли кто ссылки на эти объекты. Для этого в SBCL есть функция поиска корней:",
"entities": [
{
"offset": 708,
"length": 19,
"type": "code"
},
{
"offset": 1836,
"length": 12,
"type": "code"
},
{
"offset": 2064,
"length": 876,
"type": "pre"
},
{
"offset": 3163,
"length": 261,
"type": "pre"
}
]
}
16 changes: 16 additions & 0 deletions ru/posts/pochemu-gc-sbcl-mozhet-14.post
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
;;;;;
title: Почему GC SBCL может не освобождать память?
tags:
created-at: 2025-01-18
format: md
tg-chat-id: -1002102092834
tg-message-id: 14
;;;;;







**Обсудить пост в [Telegram канале](https://t.me/c/2102092834/14).**

0 comments on commit 4601200

Please sign in to comment.