2012-02-14 3 views
5

나는 간단한 스크립트 언어 API에서 마크 앤 스위프 가비지 콜렉션을 구현 중이며 다양한 가비지 콜렉션 구현에 대해 읽고있다. 루아와 같은 API는 흰색, 회색 및 검은 색 목록이있는 마크 앤 스위프를 사용합니다.왜 GC에서 흰색/회색/검은 색입니까?

문제는 이러한 목록이있는 이유에 대한 설명과 왜 이러한 특정 색을 넣을 수 있는지에 대한 설명을 찾을 수없는 것입니다.

현재 사소한 구현에서 "죽은"또는 "활성"상태 만 사용합니다. 스윕에서 죽은 개체는 삭제됩니다. 네이티브 힙을 사용하고 있으므로 GC에서 움직이지 않습니다. 회색 블록의 모든 후손이 아직 검은 색으로 표시되지 않았을 :

내가 C.

에 쓰고 있어요 것은
// Performs a full garbage collection 
void GorCollect(GorContext *ctx) 
{ 
    Value *v, *end; 
    Collectable *c, *n; 

    // mark stack references 
    end = ctx->stack + ctx->stackTop + 1; 
    v = ctx->stack; 
    while(v != end) 
    { 
     if (gvisgc(v) && v->v.gc) // mark if a collectable obj 
      Mark(v->v.gc); 
     v = v++; 
    } 

    // mark global references 
    if (ctx->global) 
     Mark((Collectable *)ctx->global); // ctx->global is a collectable obj 

    // perform sweep 
    c = ctx->gchead; // full list of collectable objs 
    ctx->gchead = 0; 
    while(c) { 
     n = c->next;  
     // destroy unmarked collectable 
     if (!c->marked) 
      FreeCollectable(ctx, c); 

     // rebuild gc list (singly-linked) 
     else 
     { 
      c->marked = 0; 
      if (!ctx->gchead) 
       c->next = 0; 
      else 
       c->next = ctx->gchead; 
      ctx->gchead = c; 
     } 
     c = n; 
    } 
} 
+0

왜 그들이이 특별한 색을 띠지? - 아름답 기 때문에! – asaelr

+0

"마크 앤 스위프 화이트 그레이 블랙"을 검색하면 http://www.memorymanagement.org/glossary/t.html#tri-color.marking으로 연결됩니다. 이 페이지는 알고리즘의 중요한 속성이 "정확하다"는 점을 지적하기 때문에 순진한 접근 방식은 깨지기 쉬운 부분이 있습니다. – millimoose

+0

또한 http://en.wikipedia.org/wiki/Mark_and_sweep#Naive_mark-and-sweep는 프로세스를 중단하지 않고 수행 할 수 없다는 순진 방식의 주요 단점으로 나열합니다. – millimoose

답변

8

그레이는 "라이브하지만 검색되지"를 의미한다. 회색 색상은 증분 쓰레기 수거통에 필요합니다. 그것은 mark-and-sweep GC가 다음에 마킹을 할 기회를 얻었을 때 그 작업을 계속하는 데 도움이됩니다.

GC가 비 증분 인 경우 회색 색상이 반드시 필요하지는 않은 것처럼 보일 수 있습니다. 만나는 라이브 블록의 모든 하위 항목에 간단하게 항상 반복 할 수 있습니다. 그러나 또 다른 미묘한 문제는이 순진한 비 증분 재귀 알고리즘이 스택을 오버플로 할 수 있다는 것입니다. 회색 색상은 스택 대신 힙에서 다음에 방문 할 항목에 대한 정보를 저장할 수있게 도와줍니다.

이 목적으로 회색을 사용하더라도 효율성을 위해 방문한 채로 남아있는 블록 버퍼를 유지할 수 있습니다. 순진한 재귀 구현의 유일한 차이점은 버퍼가 이미 가득차면 버퍼 업데이트를 중지하고 버퍼가 가득차면 버퍼가 비게되면 회색 객체에 대해 힙을 선형 적으로 스캔한다는 것입니다.

+0

나는 알고리즘이 전체 스캔없이 어떻게 작동 할 수 있는지를 고민하고있다. 내 말은, 회색으로 표시된 집계 객체가 있지만 그 중 하나가 자식 객체가 흰색으로 표시된 경우 흰색 객체가 다른 곳에서 참조되지 않도록 전체 트리를 탐색하지 않아도되는 방법입니다. 전체 참조 계층 구조를 스캔하지 않고 도망 갈 수있는 방법은 실제로 이해가되지 않습니다. 마크 단계가 증분 만되고 마크가 완전히 스캔되면 스위프를 완료해야합니까? 이 경우 마크 사이에 새로운 참조를 관리해야합니다. –

+0

"마크 단계가 점진적으로 증가하지 않고 마크가 완전히 스캔되면 스윕이 완료되어야합니까?" 물론 점진적 마크 앤드 스위프 GC에서는 알고리즘이 여전히 완전한 마크 단계와 완전한 스윕 단계 사이에서 번갈아 나타납니다. 그것이 마크 앤 스위프 (Mark-and-Swep)가 작동하는 방식입니다. 폴 윌슨 (Paul Wilson)의 "Uniprocessor Garbage Collection Techniques"라는 기사가 귀하의 질문에 대답해야한다고 생각합니다. –

0

첫 번째는 세트가 아니고 목록이 아니며 힙의 각 객체는 언제나 세트 중 하나에 있습니다.

둘째로, 모든 마크 & 스윕 구현에서 사용 중이지만, 암시적인 일 수 있습니다. Mark에 대한 구현을 제공하지 않지만 해당 함수에서 세트에서 객체를 이동하고 있습니다.

/* Initally, the white set contains all objects, the black and 
    grey sets are empty. */ 
stack *st = m->mark_stack; 
/* First all roots are added to the gray set. */ 
for (size_t i = 0; i < m->roots->used; i++) { 
    ptr p = m->roots->array[i]; 
    if (p != 0) { 
     /* Mark the root and move it to the gray set. */ 
     AT(p) |= 1; 
     st_push(st, p); 
    } 
} 
while (st->used) { 
    /* Think of popping the object from the mark stack as moving 
     it from the gray to the black set. */ 
    ptr p = st_pop(st); 
    P_FOR_EACH_CHILD(p, { 
     if (!GET_MARK(p_child)) { 
      /* Then mark each non-black child and move it to the 
       gray set. */ 
      AT(p_child) |= 1; 
      st_push(st, p_child); 
     } 
    }); 
} 
/* When control has reached this point, the gray set is empty and 
    the whole heap has been divided into black (marked) and white 
    (condemned) objects. */ 

우리는 대신에 세 세트에 대한 명시 적 데이터 구조를 사용할 수 있습니다 여기에

내 가비지 컬렉터의 마크 단계의 구현입니다. 그러나 스톱 글로브 인 & 스윕 gc의 경우이 구현이 훨씬 효율적입니다.