-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update from 2025-02-01T13:03:55.154551Z
- Loading branch information
1 parent
93e5011
commit 4601200
Showing
2 changed files
with
70 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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).** |