2009-08-25 6 views
1

Hier ist Mono Continuations 'continuation_store (...). Vom Blick unten auf den Code, scheint es, als ob Speicher() folgt diese beiden Zweige:Mono-Fortsetzungen - Der Speicher nimmt nach dem Speichern weiter zu()

  1. cont->saved_stack && num_bytes <= cont->stack_alloc_size
    • den Speicher verwenden, um direkt
  2. sonst
    • gc die frei verwendet Speicher und erstellt etwas neuen Speicher.

Allerdings ist die seltsame Sache, wenn ich continuation_store wiederholt(), bis die Speicherauslastung erhöht sich bei einem späteren Schritt eine große und laggy GC Betrieb durchgeführt wird. Kann jemand erklären, warum das passiert?

Dank

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; 
} 

Antwort

1

Hinweis des Anruf tut nichts in dem Standard-Boehm Kollektor mono_gc_free_fixed: https://github.com/mono/mono/blob/master/mono/metadata/boehm-gc.c#L528

Der andere Zweig entfernt nur die Speicher aus der keepalive_stacks Hash-Tabelle. Diese Hash-Tabelle enthält einen Verweis auf den zugewiesenen Speicher, so dass keine Garbage Collection stattfindet. Sobald der Zeiger auf den zugewiesenen Speicher aus dieser Hash-Tabelle entfernt wurde, wird er bei der nächsten Speicherbereinigung zurückgewonnen. Diese Sammlung wird zu einem späteren Zeitpunkt ausgelöst, sobald eine bestimmte Speicherzuweisung erreicht ist.