Lua GC 控制 gcstepmul 和 gcpause

Lua gc 是分步進行的,什麼時候開始做呢??
通過GCthreshold控制GC開始時機,GCthreshold就是觸發GC的邊界值。當一輪GC完整的完成後,GCthreshold 被設置成當前estimate的 gcpause / 100倍。estimate是剔除了userdata後的內存。
帶_gc元方法的userdata在第一次被處理時只調用_gc元方法,第二次纔是真正回收。在分配新內存時,通過luaC_checkGC檢測 總內存是否超過GCthreshold,超過就觸發一步GC。

那每步處理多少?
處理多少受gcstepmul影響

void luaC_step (lua_State *L) {
  global_State *g = G(L);
  //計算這一步要處理多少單位   0 的話就全部處理
  l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
  if (lim == 0)
    lim = (MAX_LUMEM-1)/2;  /* no limit */
  // 計算負債多少  預計是g->GCthreshold; 開始處理   但是現在已經 g->totalbytes 了
  g->gcdept += g->totalbytes - g->GCthreshold;
  do {
    //計算本次還剩多少要處理的
    lim -= singlestep(L);
    if (g->gcstate == GCSpause)
      break;
  } while (lim > 0);

  if (g->gcstate != GCSpause) {
    //處理完這次的量了
    if (g->gcdept < GCSTEPSIZE)
        // 欠債不太多了 那就擴大邊界值
      g->GCthreshold = g->totalbytes + GCSTEPSIZE;  /* - lim/g->gcstepmul;*/
    else {
     // 欠債太多了 怎麼辦  那就不停下繼續GC吧
      g->gcdept -= GCSTEPSIZE;
      g->GCthreshold = g->totalbytes;
    }
  }
  else {
    lua_assert(g->totalbytes >= g->estimate);
    //做了一次完整GC 重新設置邊界值 爲當前內存(扣除userdata)  *  gcpause /100  
    setthreshold(g);
  }
}


單步GC處理後將界限值調高了GCSTEPSIZE,也就是漲GCSTEPSIZE內存才發生GC。而每步GC處理的限制 (GCSTEPSIZE/100) * g->gcstepmul。
由此可見   處理  / 漲內存 = ((GCSTEPSIZE/100) * g->gcstepmul ) / GCSTEPSIZE = g->gcstepmul / 100  所以說gcstepmul就是相對於回收速率/分配速率的一個比值。
當gcstepmul <= 100 時 ,每步處理速率 <= 分配速率 ,可能導致無法完成一個完整的GC。gcstepmul越大,代表每步處理的對象越多,同時也會增加處理時間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章