<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 7.5 小對象分配 小對象分配過程相對就比較復雜了。 ## 從 mcache 獲取 ``` // 計算 size class var sizeclass uint8 if size &lt;= smallSizeMax-8 { sizeclass = size_to_class8[(size+smallSizeDiv-1)/smallSizeDiv] } else { sizeclass = size_to_class128[(size-smallSizeMax+largeSizeDiv-1)/largeSizeDiv] } size = uintptr(class_to_size[sizeclass]) spc := makeSpanClass(sizeclass, noscan) span := c.alloc[spc] // 獲得對應 size 的 span 列表 v := nextFreeFast(span) if v == 0 { v, span, shouldhelpgc = c.nextFree(spc) } x = unsafe.Pointer(v) if needzero &amp;&amp; span.needzero != 0 { memclrNoHeapPointers(unsafe.Pointer(v), size) } ``` 表面上看,小對象的分配過程似乎很少,實際上基于`nextFreeFast`和`nextFree`兩個分配調用隱藏了相當復雜的過程。`nextFreeFast`不涉及正式的分配過程,只是簡單的尋找一個能夠容納當前微型對象的 span: ``` func nextFreeFast(s *mspan) gclinkptr { // 檢查莫為零的個數 theBit := sys.Ctz64(s.allocCache) // 如果小于 64 則說明可以直接使用 if theBit &lt; 64 { result := s.freeindex + uintptr(theBit) if result &lt; s.nelems { freeidx := result + 1 if freeidx%64 == 0 &amp;&amp; freeidx != s.nelems { return 0 } s.allocCache &gt;&gt;= uint(theBit + 1) s.freeindex = freeidx s.allocCount++ return gclinkptr(result*s.elemsize + s.base()) } } return 0 } ``` `allocCache`字段用于計算`freeindex`上的`allocBits`緩存,`allocCache`進行了移位使其最低位對應于 freeindex 位。allocCache 保存 allocBits 的補碼,從而尾零計數可以直接使用它。 ``` func (c *mcache) nextFree(spc spanClass) (v gclinkptr, s *mspan, shouldhelpgc bool) { s = c.alloc[spc] (...) // 獲得 s.freeindex 中或之后 s 中下一個空閑對象的索引 freeIndex := s.nextFreeIndex() if freeIndex == s.nelems { // span 已滿,進行填充 (...) c.refill(spc) (...) // 再次獲取 freeIndex s = c.alloc[spc] freeIndex = s.nextFreeIndex() } (...) v = gclinkptr(freeIndex*s.elemsize + s.base()) // 這部分內容需要被 gc 接管,因此需要計算位置 s.allocCount++ // 分配計數 (...) return } ``` 過程很直接,先嘗試獲取`freeIndex`,如已經獲取到,則直接根據元素的大小來計算需要被 GC 的內存位置。 當 span 已滿時候,會通過`refill`進行填充,而后再次嘗試獲取`freeIndex`。 可以看到`refill`其實是從`mcentral`調用`cacheSpan`方法來獲得 span: ``` func (c *mcache) refill(spc spanClass) { _g_ := getg() _g_.m.locks++ // Return the current cached span to the central lists. s := c.alloc[spc] (...) // Get a new cached span from the central lists. s = mheap_.central[spc].mcentral.cacheSpan() if s == nil { throw("out of memory") } (...) c.alloc[spc] = s } ``` ## 從 mcentral 獲取 ``` func (c *mcentral) cacheSpan() *mspan { (...) lock(&amp;c.lock) (...) retry: var s *mspan for s = c.nonempty.first; s != nil; s = s.next { (...) c.nonempty.remove(s) c.empty.insertBack(s) unlock(&amp;c.lock) goto havespan } (...) unlock(&amp;c.lock) // Replenish central list if empty. s = c.grow() if s == nil { return nil } lock(&amp;c.lock) c.empty.insertBack(s) unlock(&amp;c.lock) // At this point s is a non-empty span, queued at the end of the empty list, // c is unlocked. havespan: (...) n := int(s.nelems) - int(s.allocCount) if n == 0 || s.freeindex == s.nelems || uintptr(s.allocCount) == s.nelems { throw("span has no free objects") } // Assume all objects from this span will be allocated in the // mcache. If it gets uncached, we'll adjust this. atomic.Xadd64(&amp;c.nmalloc, int64(n)) usedBytes := uintptr(s.allocCount) * s.elemsize atomic.Xadd64(&amp;memstats.heap_live, int64(spanBytes)-int64(usedBytes)) (...) freeByteBase := s.freeindex &amp;^ (64 - 1) whichByte := freeByteBase / 8 // Init alloc bits cache. s.refillAllocCache(whichByte) // Adjust the allocCache so that s.freeindex corresponds to the low bit in // s.allocCache. s.allocCache &gt;&gt;= s.freeindex % 64 return s } ``` ## 從 mheap 獲取 ``` func (c *mcentral) grow() *mspan { npages := uintptr(class_to_allocnpages[c.spanclass.sizeclass()]) size := uintptr(class_to_size[c.spanclass.sizeclass()]) n := (npages &lt;&lt; _PageShift) / size s := mheap_.alloc(npages, c.spanclass, false, true) if s == nil { return nil } p := s.base() s.limit = p + size*n heapBitsForAddr(s.base()).initSpan(s) return s } ``` 直接從`mheap_`分配的`alloc`,已經在大對象的分配過程中討論過了,這里便不再贅述了
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看