2009-08-25 55 views
1

這裏是單聲道Continuations'continuation_store(...)。從看一下下面的代碼,它看起來好像商店()遵循以下兩個分支:單聲道延續 - 存儲後存儲器不斷增加()

  1. cont->saved_stack && num_bytes <= cont->stack_alloc_size
    • 使用內存直接
  2. 其他
    • GC釋放使用內存,並創建一些新的內存。

然而,奇怪的是,如果我重複使用continuation_store(),內存使用率增加,直到在後面的步驟一個巨大的和laggy 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; 
} 

回答

1

注意調用mono_gc_free_fixed什麼也不做默認貝姆收集:https://github.com/mono/mono/blob/master/mono/metadata/boehm-gc.c#L528

else分支只是刪除從keepalive_stacks哈希表的內存。這個散列表保留了對分配內存的引用,所以它不會被垃圾回收。一旦指向分配的內存的指針從該哈希表中刪除,它將在下一次垃圾回收期間被回收。一旦達到一定量的內存分配,稍後觸發該集合。