<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          go中的物理內(nèi)存釋放

          共 1915字,需瀏覽 4分鐘

           ·

          2022-02-11 13:13

          madvice是go1.16版本引入的系統(tǒng)調(diào)用參數(shù)配置,本文解釋了它的原理和作用。

          go 使用 madvise 系統(tǒng)調(diào)用來(lái)釋放物理內(nèi)存給操作系統(tǒng),該方法主要有兩種歸還類(lèi)型可選:

          • MADV_DONTNEED:立即歸還物理內(nèi)存給操作系統(tǒng),如果下次訪問(wèn)到該范圍的內(nèi)存,則會(huì)觸發(fā) page fault 異常,需要重新分配物理頁(yè),使用該類(lèi)型可以減少程序的RSS占用
          • MADV_FREE:告訴操作系統(tǒng)這塊內(nèi)存已經(jīng)不需要使用了,可以回收了,如果內(nèi)存緊張,操作系統(tǒng)就會(huì)將其回收。這實(shí)際是一個(gè)lazily的釋放過(guò)程。如果再次訪問(wèn)這塊內(nèi)存的時(shí)候,操作系統(tǒng)還沒(méi)有將其回收,是不會(huì)觸發(fā) page fault 的。使用該類(lèi)型,可能程序的RSS不會(huì)減少。

          當(dāng)前實(shí)現(xiàn),首先嘗試使用?MADV_FREE,如果失敗了,再?lài)L試使用?MADV_DONTNEED。MADV_FREE需要linux內(nèi)核4.5及以上:

          var?adviseUnused?=?uint32(_MADV_FREE)
          func?sysUnused(v?unsafe.Pointer,?n?uintptr)?{
          ????......
          ????
          ????var?advise?uint32
          ????//?如果設(shè)置了`GODEBUG=madvdontneed=1`,強(qiáng)制使用MADV_DONTNEED
          ????if?debug.madvdontneed?!=?0?{
          ????????advise?=?_MADV_DONTNEED
          ????}?else?{
          ????????advise?=?atomic.Load(&adviseUnused)
          ????}
          ????//?首先嘗試使用`MADV_FREE`
          ????if?errno?:=?madvise(v,?n,?int32(advise));?advise?==?_MADV_FREE?&&?errno?!=?0?{
          ????????//?MADV_FREE?was?added?in?Linux?4.5.?Fall?back?to?MADV_DONTNEED?if?it?is
          ????????//?not?supported.
          ????????atomic.Store(&adviseUnused,?_MADV_DONTNEED)
          ????????madvise(v,?n,?_MADV_DONTNEED)
          ????}
          }

          MADV_FREE的性能會(huì)好一點(diǎn),但是會(huì)讓程序的RSS占用不會(huì)減少,可以通過(guò)GODEBUG=madvdontneed=1強(qiáng)制使用MADV_DONTNEED。

          go中堆內(nèi)存主要使用mmap來(lái)申請(qǐng)的。首先,使用mmap來(lái)reserve一段內(nèi)存:

          func?sysReserve(v?unsafe.Pointer,?n?uintptr)?unsafe.Pointer?{
          ?p,?err?:=?mmap(v,?n,?_PROT_NONE,?_MAP_ANON|_MAP_PRIVATE,?-1,?0)
          ?if?err?!=?0?{
          ??return?nil
          ?}
          ?return?p
          }

          可以看到,使用匿名映射一塊內(nèi)存,并且指定了 PROT_NONE ,即這塊內(nèi)存是不可以被訪問(wèn)的,因此就不會(huì)分配物理內(nèi)存了。當(dāng)需要真正分配內(nèi)存的時(shí)候,在這塊保留的內(nèi)存中分配:

          func?sysMap(v?unsafe.Pointer,?n?uintptr,?sysStat?*uint64)?{
          ?mSysStatInc(sysStat,?n)?//?內(nèi)存統(tǒng)計(jì)
          ?//?修改前面保留的內(nèi)存的指定區(qū)域?yàn)榭勺x寫(xiě)
          ?p,?err?:=?mmap(v,?n,?_PROT_READ|_PROT_WRITE,?_MAP_ANON|_MAP_FIXED|_MAP_PRIVATE,?-1,?0)
          ?if?err?==?_ENOMEM?{
          ??throw("runtime:?out?of?memory")
          ?}
          ?if?p?!=?v?||?err?!=?0?{
          ??throw("runtime:?cannot?map?pages?in?arena?address?space")
          ?}
          }

          當(dāng)我們查看進(jìn)程的內(nèi)存占用時(shí),主要關(guān)注的是RSS,而reserve的內(nèi)存是不能被訪問(wèn)的,不會(huì)分配物理內(nèi)存頁(yè),并不會(huì)影響RSS的值。

          文章轉(zhuǎn)載:Go開(kāi)發(fā)大全

          (版權(quán)歸原作者所有,侵刪)


          點(diǎn)擊下方“閱讀原文”查看更多

          瀏覽 163
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天av干 | 九九九精品视频 | 免费操 | www毛片 | 2021国产精彩精品视频 |