Mono Continuations - store() 之后内存不断增加
这是 Mono Continuations 的 continuation_store (...)。从下面的代码来看,store() 似乎遵循这两个分支:
cont->saved_stack && num_bytes <= cont->stack_alloc_size
- 直接使用内存
- else
- gc 释放已使用的内存,并创建一些新内存。
然而,奇怪的是,如果我重复使用 continuation_store(),内存使用量会增加,直到稍后的步骤完成一个巨大且滞后的 GC 操作。谁能解释为什么会发生这种情况?
谢谢
static int
continuation_store (MonoContinuation *cont, int state, MonoException **e)
{
MonoLMF *lmf = mono_get_lmf ();
gsize num_bytes;
if (!cont->domain)
*e = mono_get_exception_argument ("cont", "Continuation not initialized");
if (cont->domain != mono_domain_get () || cont->thread_id != GetCurrentThreadId ())
*e = mono_get_exception_argument ("cont", "Continuation from another thread or domain");
cont->lmf = lmf;
cont->return_ip = __builtin_return_address (0);
cont->return_sp = __builtin_frame_address (0);
num_bytes = (char*)cont->top_sp - (char*)cont->return_sp;
/*g_print ("store: %d bytes, sp: %p, ip: %p, lmf: %p\n", num_bytes, cont->return_sp, cont->return_ip, lmf);*/
if (cont->saved_stack && num_bytes <= cont->stack_alloc_size)
{
/* clear to avoid GC retention */
if (num_bytes < cont->stack_used_size)
memset ((char*)cont->saved_stack + num_bytes, 0, cont->stack_used_size - num_bytes);
}
else
{
tasklets_lock ();
internal_init ();
if (cont->saved_stack) {
mono_g_hash_table_remove (keepalive_stacks, cont->saved_stack);
mono_gc_free_fixed (cont->saved_stack);
}
cont->stack_used_size = num_bytes;
cont->stack_alloc_size = num_bytes * 1.1;
cont->saved_stack = mono_gc_alloc_fixed (cont->stack_alloc_size, NULL);
mono_g_hash_table_insert (keepalive_stacks, cont->saved_stack, cont->saved_stack);
tasklets_unlock ();
}
memcpy (cont->saved_stack, cont->return_sp, num_bytes);
return state;
}
Here's Mono Continuations' continuation_store (...). From looking at the code below, it appears as though store() follows these two branches:
cont->saved_stack && num_bytes <= cont->stack_alloc_size
- use the memory directly
- else
- gc free the used memory, and create some new memory.
However, the weird thing is if I repeatedly use continuation_store(), the memory usage increases until at a later step a huge and laggy GC operation is done. Can anyone explain why this happens?
Thanks
static int
continuation_store (MonoContinuation *cont, int state, MonoException **e)
{
MonoLMF *lmf = mono_get_lmf ();
gsize num_bytes;
if (!cont->domain)
*e = mono_get_exception_argument ("cont", "Continuation not initialized");
if (cont->domain != mono_domain_get () || cont->thread_id != GetCurrentThreadId ())
*e = mono_get_exception_argument ("cont", "Continuation from another thread or domain");
cont->lmf = lmf;
cont->return_ip = __builtin_return_address (0);
cont->return_sp = __builtin_frame_address (0);
num_bytes = (char*)cont->top_sp - (char*)cont->return_sp;
/*g_print ("store: %d bytes, sp: %p, ip: %p, lmf: %p\n", num_bytes, cont->return_sp, cont->return_ip, lmf);*/
if (cont->saved_stack && num_bytes <= cont->stack_alloc_size)
{
/* clear to avoid GC retention */
if (num_bytes < cont->stack_used_size)
memset ((char*)cont->saved_stack + num_bytes, 0, cont->stack_used_size - num_bytes);
}
else
{
tasklets_lock ();
internal_init ();
if (cont->saved_stack) {
mono_g_hash_table_remove (keepalive_stacks, cont->saved_stack);
mono_gc_free_fixed (cont->saved_stack);
}
cont->stack_used_size = num_bytes;
cont->stack_alloc_size = num_bytes * 1.1;
cont->saved_stack = mono_gc_alloc_fixed (cont->stack_alloc_size, NULL);
mono_g_hash_table_insert (keepalive_stacks, cont->saved_stack, cont->saved_stack);
tasklets_unlock ();
}
memcpy (cont->saved_stack, cont->return_sp, num_bytes);
return state;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请注意,对 mono_gc_free_fixed 的调用在默认的 boehm 收集器中不会执行任何操作: https://github.com/mono/mono/blob/master/mono/metadata/boehm-gc.c#L528
else 分支只是从 keepalive_stacks 哈希表中删除内存。该哈希表保留对已分配内存的引用,因此不会被垃圾回收。一旦从该哈希表中删除指向已分配内存的指针,它将在下一次垃圾收集期间被回收。一旦达到一定的内存分配量,就会稍后触发此收集。
Note the call to mono_gc_free_fixed does nothing in the default boehm collector: https://github.com/mono/mono/blob/master/mono/metadata/boehm-gc.c#L528
The else branch just removes the memory from the keepalive_stacks hash table. This hash table keeps a reference to the allocated memory so it is not garbage collected. Once the pointer to the allocated memory is removed from this hash table, it will then be reclaimed during the next garbage collection. This collection is triggered at a later time once reaching a certain amount of memory allocation.