multiprocessing.manager管理的對象需要加鎖嗎_Go: 內存管理和分配

445fcead3e8fc2d05b73614f86b4f2de.png

本文基于Go1.13

當不再使用內存時,標準庫會自動執行Go的內存管理即從分配到回收。盡管開發者不需要處理它,但是Go的底層管理進行了很好的優化并且充滿了有趣的概念。

堆上的分配

內存管理被設計可以在并發環境快速執行并且集成了gc。讓我們從一個例子開始:

package maintype smallStruct struct {a, b int64c, d float64
}func main() {smallAllocation()
}//go:noinline
func smallAllocation() *smallStruct {return &smallStruct{}
}

注釋//go:noinline 將會阻止內聯優化,以避免內聯通過移除函數的方式優化這段代碼,從而造成最終沒有分配內存的情況。

運行逃逸分析命令go tool compile "-m" main.go可以確認Go執行了分配:

main.go:14:9: &smallStruct literal escapes to heap

借助go tool compile -S main.go 輸出的程序匯編代碼,同樣可以明確的展示了分配:

0x001d 00029 (main.go:14)   LEAQ   type."".smallStruct(SB), AX
0x0024 00036 (main.go:14)  PCDATA $0, $0
0x0024 00036 (main.go:14)  MOVQ   AX, (SP)
0x0028 00040 (main.go:14)  CALL   runtime.newobject(SB)

函數newobject是新分配對象和代理mallocgc的內置函數,該函數在堆上管理它們。Go中有兩種策略,一種用于較小的分配,一種用于較大的分配。

小分配

對于低于32kb的小分配,Go將會嘗試從本地mcache 緩存中獲取內存。此緩存包含一組mspan

7ec3f12e49405473dc00790d9b4187e6.png

每個M 被分配給一個處理器P并且一次只能處理一個goroutine。當需要分配內存時,當前goroutine會使用它當前P的本地緩存來從中尋找第一個可用空閑對象。使用本地緩存不需要加鎖會使得分配更加高效。

mspan被分為約70個尺寸類型,從8字節到32k字節。

e7db4fee4567edd156b78556f440f358.png

每個mspan會存在2次:一個不包含指針,一個包含指針。這種區別會使得gc更加容易因為它不需要掃描那些不包含指針的mspan。

在我們之前的例子里,結構體是32字節所以它適合于32 字節的mspan。

2ce8e3a43953f926200b4889f22c5e4e.png

現在會疑惑如果mspan在內存分配時候沒有空閑插槽會發生什么。Go維護了包含全尺寸類型的中央鏈表mcentral,其中包含空閑和非空閑對象的mspan:

6a72c51d03ca5abd88acc042d5a0fc53.png

mcentral 維護著mspan的雙向鏈表; 在非空鏈表(non-empty list:尚有空閑object的mspan鏈表) — 非空(“non-empty” )代表鏈表中至少有一個插槽是空閑可供分配 — 可能包含一些正在使用的內存。當gc 清理內存時,他會清理一部分mspan標記不再使用,并放回非空鏈表(non-empty list)

我們程序可以在插槽耗盡后向中央鏈表申請mspan:

74eeeec828b46a00d4363d49e73415b1.png

如果空鏈表中沒有可用的mspan,Go需要為中央鏈表獲取新的mspan。新的mspan會從堆上分配并鏈接到中央鏈表上:

0a7a3b546d662041ad1b827a0f558b1a.png

堆在需要時從OS中提取內存。如果需要更多內存,堆會分配一個叫做 arena 的大塊內存, 在 64 位架構下為 64Mb,在其他架構下大多為 4Mb。arena 同樣使用mspan來映射內存:

b834f377fae25807e1dfbfb2d36d4fe2.png

大分配

Go并不適用本地緩存來管理較大的內存空間分配。對于超過 32kb 的分配,會向上取整到頁的大小,并直接從堆上分配。

e64af3636225fe3d93a0f9b188018984.png

全景圖

現在我們對內存分配的時候發生了什么有了更好的認識。現在將所有的組成部分放在一起來得到全景圖:

84355ad99e1c1dca9dbfc9f770604e24.png
編譯整理自 Go: Memory Management and Allocationhttps://medium.com/a-journey-with-go/go-memory-management-and-allocation-a7396d430f44

db05ec903f465f389d878919fd3a6e62.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374010.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374010.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374010.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

NYOJ 35表達式求值

表達式求值 時間限制:3000 ms | 內存限制:65535 KB難度:4描述 ACM隊的mdd想做一個計算器,但是,他要做的不僅僅是一計算一個AB的計算器,他想實現隨便輸入一個表達式都能求出它的值的計算器,現在請…

Java EE6 CDI,命名組件和限定符

Java EE6的最大承諾之一就是簡化了依賴注入的使用。 他們做到了,使用CDI 。 CDI代表Java EE的上下文和依賴注入,它提供了一個基礎集,用于在企業應用程序中應用依賴注入。 在CDI之前,EJB 3還引入了依賴注入,但這有點基礎…

c#獲取當前目錄的一些方法

【內容來源地址】:http://www.cnblogs.com/marcozh/archive/2008/10/19/1314667.html Assembly myAssembly Assembly.GetEntryAssembly(); string path myAssembly.Location; DirectoryInfo dr new DirectoryInfo(path); pathd…

linux里的進程簡介

/sbin/init 內核啟動的第一個用戶級進程,引導用戶空間服務 [kthreadd] 內核線程管理[migration/0] 用于進程在不同的CPU間遷移[ksoftirqd/0] 內核調度/管理第0個CPU軟中斷的守護進程[migration/1] 管理多核心[ksoftirqd/1] 內核調度/管…

python畫畫bup_Python中的高效Vector / Point類

實現高效的Vector / Point類的最佳方法是什么(甚至更好:是否有一個),可以在Python 2.7和3.x中使用?我找到了the blender-mathutils,但它們似乎只支持Python 3.x.然后是this Vector class,使用numpy,但它只是一個3D矢量.使用具有靜態屬性(x和y)的像kivy’…

CSDN 編程挑戰——《coder的計算器》

coder的計算器 題目詳情: coder現在已經上初中,也會用計算器實現 ,-,*,/和冪運算^了,但他覺得市場那些計算器太繁瑣了,有很多他不認識的符號,所以他現在很想要能計算帶括號的 ,-,*,/和冪運算^的混合表達式就可以了,你…

OpenShift Express:部署Java EE應用程序(支持AS7)

在過去的幾年中,我越來越聽到有關“云”服務的信息。 最初,我并不是很想嘗試一下。 但是幾個月后(一年?),我決定看看這是怎么回事。 我從事Java EE開發已經超過7年了,所以我決定看看將Java EE應…

07 總結ProgressDialog 異步任務

1,ProgressDialog> //使用對象 設置標題 progressDialog.setTitle("標題"); //設置圖標 progressDialog.setIcon(R.drawable.ic_launcher); //設置展示的內容 progressDialog.setMessage(&q…

python函數封裝計算n運算_在Python里面怎么可以運算出999999999**999999999,求思路?...

>>> 999999999 * math.log(999999999, 2) / 8 / 1024 ** 33.480509950621777所以這個數字本身就差不多需要3.5GB內存,考慮到計算過程中需要存儲臨時結果,還需要翻個兩三倍吧而Python中的long可以到多少呢:#define MAX_LONG_DIGITS \…

C++中const關鍵字的使用總結

const是不變的意思,在C程序中,經常用const來限制對一個對象的操作: 1.1 const變量 例如: const int n3; 則這個變量的值不能改變,即不能對變量賦值。 1.2 const參數 出現在函數參數中的const表示在函數體中不能對這個參數做修改…

php封裝redis負載均衡類

$array array( master > array( "redis://127.0.0.1:6379?timeout1", ), slave > array( "redis://127.0.0.1:6479?timeout1", "redis://127.0.0.1:6579?timeout1", ) ); $redis R…

我今天對JavaFX的了解

如果您沒有聽說過,JavaFX 2是Java的新Desktop / web / client框架。 自JavaFX 1以來,它已經進行了相當大的改動(坦率地說,效果并不那么令人印象深刻)。 自定義腳本語言已經淘汰了,您可以使用標準Java和基于…

怎么解決xp系統不能安裝NET Framework4.0?

.net 4.0安裝不上解決方法: 引用 9 樓 MoreQuestion 的回復: 全部都不行!就是用360軟件管家安裝那個就可以了。用了樓主的方法,果然可行啊 1.先安裝wic。 2.用360安裝.net40 本帖最后由 不懂 于 2014-6-6 00:56 編輯Windows Server 2003 如何…

C++內聯(inline)函數

內聯函數 內聯函數是一種特殊類型的函數,內聯函數在定義或聲明時前面加上“inline”關鍵字。比如: inline int max(int a,int b) { return (a>b)?a:b; } 內聯(inline)是內聯擴展(inline expansion)的簡…

我的python學習筆記全集_記錄我的Python學習筆記

不想再像以前那樣,什么都從頭開始學習語法、總結語法,這樣反而會過分糾結于語法,耽誤了開發,畢竟語言的主要屬性是工具,次要的屬性是語言本身。所以還是先熟練使用語言去進行開發,等足夠熟悉了,…

HDU 5794:A Simple Chess(Lucas + DP)

題目鏈接:http://acm.split.hdu.edu.cn/showproblem.php?pid5794 題意:讓一個棋子從(1,1)走到(n,m),要求像馬一樣走日字型并只能往右下角走。里面還有r個障礙點不能經過或者到達&am…

php源碼分析之PHPAPI宏的作用

在PHP源碼中,我們經常會看到很多函數前面有個PHPAPI,但這是什么呢? 于是我在php源碼/main/php.h中找到了它的定義 #ifdef PHP_WIN32 # include "tsrm_win32.h" # include "win95nt.h" # ifdef PHP_EXPORTS # …

15分鐘內開始使用Amazon Web Services和全自動資源調配

在等待一個新項目時,我想學習一些有用的東西。 而且由于在許多項目中我們需要評估和測試正在開發的應用程序的性能,而很少有足夠的硬件來生成實際負載,因此我決定學習更多有關按需在云中按需配置虛擬機的知識,即Amazon Web Servic…

解析JVM內存區域組成

在方法(代碼塊)中定義一個變量時,java就在棧中為這個變量分配JVM內存空間,當超過變量的作用域后,java會自動釋放掉為該變量所分配的JVM內存空間;而在堆中分配的JVM內存由java虛擬機的自動垃圾回收器來管理。…

python打開瀏覽器后帶cookie_Python爬蟲使用瀏覽器的cookies:browsercookie

很多用Python的人可能都寫過網絡爬蟲,自動化獲取網絡數據確實是一件令人愉悅的事情,而Python很好的幫助我們達到這種愉悅。然而,爬蟲經常要碰到各種登錄、驗證的阻撓,讓人灰心喪氣(網站:天天碰到各種各樣的爬蟲抓我們網…