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

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 7.8 內存統計 Go 運行時對用戶提供只讀的內存統計信息,通過`runtime.MemStats`支持。 公共方法只有一個:`ReadMemStats`。但調用這個方法的代價非常之大: ``` func ReadMemStats(m *MemStats) { stopTheWorld("read mem stats") systemstack(func() { readmemstats_m(m) }) startTheWorld() } ``` 讀取前后需要付出 STW 的成本。對于`readmemstats_m`而言,是將運行時用于內存統計的 變量`memstats`中的值拷貝到用戶態的`MemStats`中,不過這樣進行`memove`操作 是發生在系統棧上的,因此這部分的內存實際上是 OS 棧上的內存,因此最后還給用戶加上`stats.StackInuse`的值來保證完整性: ``` func readmemstats_m(stats *MemStats) { updatememstats() // 將運行時 memstats 變量拷貝到 stats 中 memmove(unsafe.Pointer(stats), unsafe.Pointer(&amp;memstats), sizeof_C_MStats) // 因為 memstats.stacks_sys 是唯一直接映射到 OS 棧的內存。 // 所以這里加上了堆分配的棧內存以供用戶使用。 stats.StackSys += stats.StackInuse } ``` 而上方拷貝前的`updatememstats`是為了將 STW 之后未完整統計的內存信息統一更新到`memstats`中: ``` //go:nowritebarrier func updatememstats() { memstats.mcache_inuse = uint64(mheap_.cachealloc.inuse) memstats.mspan_inuse = uint64(mheap_.spanalloc.inuse) memstats.sys = memstats.heap_sys + memstats.stacks_sys + memstats.mspan_sys + memstats.mcache_sys + memstats.buckhash_sys + memstats.gc_sys + memstats.other_sys // 將 stacks_inuse 作為系統內存進行計算 memstats.sys += memstats.stacks_inuse // 計算內存分配器統計信息。 // 在程序執行期間,運行時只計算釋放的數量和釋放的內存量。 // 堆中當前活動對象的數量和活動堆內存的數量 // 通過掃描所有 span 計算。 // malloc 的總數計算為 frees 數和活動對象數。 // 類似地,分配的內存總量計算為釋放的內存量 // 加上活躍堆內存的數量。 memstats.alloc = 0 memstats.total_alloc = 0 memstats.nmalloc = 0 memstats.nfree = 0 for i := 0; i &lt; len(memstats.by_size); i++ { memstats.by_size[i].nmalloc = 0 memstats.by_size[i].nfree = 0 } // Flush mcaches 到 mcentral, TODO: 這個地方不是很明白為什么還要切一次系統棧? systemstack(flushallmcaches) // 匯總本地統計數據。 cachestats() // 統計分配信息,因為 STW 所以安全 var smallFree, totalAlloc, totalFree uint64 // 搜集每個 span 等級的統計 for spc := range mheap_.central { // mcaches 現在為空,因此 mcentral 統計已經是最新的了 c := &amp;mheap_.central[spc].mcentral memstats.nmalloc += c.nmalloc i := spanClass(spc).sizeclass() memstats.by_size[i].nmalloc += c.nmalloc totalAlloc += c.nmalloc * uint64(class_to_size[i]) } // 收集每個大小等級的信息 for i := 0; i &lt; _NumSizeClasses; i++ { if i == 0 { memstats.nmalloc += mheap_.nlargealloc totalAlloc += mheap_.largealloc totalFree += mheap_.largefree memstats.nfree += mheap_.nlargefree continue } // The mcache stats have been flushed to mheap_. memstats.nfree += mheap_.nsmallfree[i] memstats.by_size[i].nfree = mheap_.nsmallfree[i] smallFree += mheap_.nsmallfree[i] * uint64(class_to_size[i]) } totalFree += smallFree memstats.nfree += memstats.tinyallocs memstats.nmalloc += memstats.tinyallocs // 計算派生數據 memstats.total_alloc = totalAlloc memstats.alloc = totalAlloc - totalFree memstats.heap_alloc = memstats.alloc memstats.heap_objects = memstats.nmalloc - memstats.nfree } ``` ``` //go:nowritebarrier func flushallmcaches() { for i := 0; i &lt; int(gomaxprocs); i++ { flushmcache(i) } } //go:nowritebarrier func flushmcache(i int) { p := allp[i] c := p.mcache if c == nil { return } c.releaseAll() stackcache_clear(c) } //go:systemstack func stackcache_clear(c *mcache) { (...) lock(&amp;stackpoolmu) for order := uint8(0); order &lt; _NumStackOrders; order++ { x := c.stackcache[order].list for x.ptr() != nil { y := x.ptr().next stackpoolfree(x, order) x = y } c.stackcache[order].list = 0 c.stackcache[order].size = 0 } unlock(&amp;stackpoolmu) } ``` ``` //go:nowritebarrier func cachestats() { for _, p := range allp { c := p.mcache if c == nil { continue } purgecachedstats(c) } } //go:nosplit func purgecachedstats(c *mcache) { // Protected by either heap or GC lock. h := &amp;mheap_ memstats.heap_scan += uint64(c.local_scan) c.local_scan = 0 memstats.tinyallocs += uint64(c.local_tinyallocs) c.local_tinyallocs = 0 h.largefree += uint64(c.local_largefree) c.local_largefree = 0 h.nlargefree += uint64(c.local_nlargefree) c.local_nlargefree = 0 for i := 0; i &lt; len(c.local_nsmallfree); i++ { h.nsmallfree[i] += uint64(c.local_nsmallfree[i]) c.local_nsmallfree[i] = 0 } } ``` 這里只是讀取時候對全部信息進行的同步,在分配的過程中還有很多直接統計的代碼。
                  <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>

                              哎呀哎呀视频在线观看