偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

深入理解golang:內(nèi)存分配原理

開發(fā) 前端
在說明golang內(nèi)存分配之前,先了解下Linux系統(tǒng)內(nèi)存相關(guān)的基礎(chǔ)知識,有助于理解golang內(nèi)存分配原理。

一、Linux系統(tǒng)內(nèi)存

在說明golang內(nèi)存分配之前,先了解下Linux系統(tǒng)內(nèi)存相關(guān)的基礎(chǔ)知識,有助于理解golang內(nèi)存分配原理。

1.1 虛擬內(nèi)存技術(shù)

在早期內(nèi)存管理中,如果程序太大,超過了空閑內(nèi)存容量,就沒有辦法把全部程序裝入到內(nèi)存,這時怎么辦? 在許多年前,人們采用了一種叫做覆蓋技術(shù),這樣一種解決方案。

這是一種什么樣的解決方案?

就是把程序分為若干個部分,稱為覆蓋塊(overlay),核心思想就是分解(跟現(xiàn)代架構(gòu)技術(shù)中分解、分模塊思想很相近)。然后只把那些需要用到的指令和數(shù)據(jù)保存在內(nèi)存中,而把其余的指令和數(shù)據(jù)保存在內(nèi)存外。關(guān)鍵是需要程序員手動來分塊。

這種技術(shù)有什么問題呢?

這種技術(shù)必須由程序員手工把一個大的程序劃分為若干個小的功能模塊,并確定各個模塊之間的調(diào)用關(guān)系。手工做這種事情很費時費力,使得編程復(fù)雜度增加。但是,程序員總是愛“偷懶”的,于是,人們?nèi)ふ腋玫姆桨浮?/p>

這個方案就是虛擬內(nèi)存技術(shù),它的基本思路:

  • 程序運行進程的總大小可以超過實際可用的物理內(nèi)存的大小。每個進程都可以有自己獨立的虛擬地址空間。然后通過CPU和MMU把虛擬內(nèi)存地址轉(zhuǎn)換為實際物理地址。

這個就相當(dāng)于在物理內(nèi)存和程序之間增加了一個中間層,虛擬內(nèi)存。

虛擬存儲也可以看作是對內(nèi)存的一種抽象。而且這種抽象帶來諸多好處:

  • 它將內(nèi)存看成是一個存儲在磁盤上的地址空間的高速緩存,在內(nèi)存中只保留了活動區(qū)域,可以根據(jù)需要在磁盤和內(nèi)存間來回傳送數(shù)據(jù),高效使用內(nèi)存。
  • 它為每個進程提供了一致的地址空間,簡化了存儲的管理。

對進程起到保護作用,不被其他進程地址空間破壞,因為每個進程的地址空間都是相互獨立。

  • (程序:靜態(tài)的程序;進程:動態(tài)的,可以看作是程序的一個實例)
  • 壞處:就是復(fù)雜度進一步增加,這也是必然的。不過相比帶來的好處,復(fù)雜度的增加還是可以接受,并克服。

Linux中對進程的處理抽象成了一個結(jié)構(gòu)體 task_struct ,我前面文章有對這個結(jié)構(gòu)體的介紹。下面就看看進程的內(nèi)存。

1.2 進程的內(nèi)存

進程內(nèi)存在linux(32位)中的布局:

 

深入理解golang:內(nèi)存分配原理

來自: https://manybutfinite.com/post/anatomy-of-a-program-in-memory/

最高位的1GB是linux內(nèi)核空間,用戶代碼不能寫,否則觸發(fā)段錯誤。下面的3GB是進程使用的內(nèi)存。

  • Kernel space:linux內(nèi)核空間內(nèi)存
  • Stack:進程??臻g,程序運行時使用。它向下增長,系統(tǒng)自動管理
  • Memory Mapping Segment:內(nèi)存映射區(qū),通過mmap系統(tǒng)調(diào)用,將文件映射到進程的地址空間,或者匿名映射。
  • Heap:堆空間。這個就是程序里動態(tài)分配的空間。linux下使用malloc調(diào)用擴展(用brk/sbrk擴展內(nèi)存空間),free函數(shù)釋放(也就是縮減內(nèi)存空間)
  • BSS段:包含未初始化的靜態(tài)變量和全局變量
  • Data段:代碼里已初始化的靜態(tài)變量、全局變量
  • Text段:代碼段,進程的可執(zhí)行文件

二、內(nèi)存管理中的一些常見問題

  1. 未能釋放已經(jīng)不再使用的內(nèi)存 - 內(nèi)存泄漏
  2. 指向不可用的內(nèi)存指針 - 野指針
  3. 指針?biāo)赶虻膶ο笠呀?jīng)被回收了,但是指向該對象的指針仍舊指向已經(jīng)回收的內(nèi)存地址 - 懸掛指針
  4. 分配或釋放內(nèi)存太快或者太慢
  5. 分配內(nèi)存大小不合理,造成內(nèi)存碎片問題
  6. 內(nèi)存碎片問題

三、TCMalloc

可以查看前面的文章TCMalloc內(nèi)存分配簡析,TCMalloc內(nèi)存分配器的原理和golang內(nèi)存分配器原理相近,所以理解了TCMalloc,golang內(nèi)存分配原理也就理解大半,不過golang對它也有一些改動。

四、golang內(nèi)存

4.1 golang怎么解決常見內(nèi)存問題

golang是怎么解決 二 的內(nèi)存管理中的常見問題的呢?

針對上面的1、2、3 這三種問題,golang使用自動垃圾回收機制,一般情況下,都不使用指針運算(要運算用unsafe包),很少的指針使用。當(dāng)然,內(nèi)存泄漏問題不能完全根除,但是可以解決一大部分問題。

針對下面的4、5、6 這三種問題,golang采用了多級緩存,預(yù)分配的方法,來加快內(nèi)存分配和釋放回收,盡量減少內(nèi)存碎片。詳見TCMalloc內(nèi)存分配簡析 。

4.2 為什么要重新寫一個內(nèi)存分配器

內(nèi)核已經(jīng)有一個malloc的內(nèi)存分配器,為什么還有重寫一個內(nèi)存分配器?

可以看到,malloc是一個很悠久的內(nèi)存分配器,但是隨著時代的發(fā)展,多核多線程已經(jīng)普及,為了更好的應(yīng)用多線程,提高程序效率,以及改進內(nèi)存碎片,所以重新寫了一個內(nèi)存分配器。從這里TCMalloc內(nèi)存分配簡析 可以看出TCMaloc的優(yōu)點,它將內(nèi)存劃分為多級別,減少鎖的開銷。而且每個線程的緩存又分開了多個小的對象,以減少內(nèi)存碎片。等等優(yōu)化改進。

所以go內(nèi)存分配也繼承了這些優(yōu)點。go還有一個原因,那就是go還有GC,需要配合內(nèi)存的垃圾回收。

4.3 內(nèi)存管理到底管理哪個區(qū)域

從上面的進程內(nèi)存布局圖,可以看出一個進程的內(nèi)存劃分了好多不同的區(qū)域,而內(nèi)存管理主要管理的就是Stack和Heap,其中Stack (棧)區(qū)主要由編譯器和系統(tǒng)管理,程序語言主要管理Heap(堆)。而且這里的進程內(nèi)存指的是虛擬內(nèi)存。

4.4 golang內(nèi)存中的概念

golang內(nèi)存分配的基本思想來自TCMalloc,所以go內(nèi)存分配中的幾個概念與TCMalloc很相似,可以看看TCMalloc 中的概念 。

mspan

mspan跟tcmalloc中的span相似,它是golang內(nèi)存管理中的基本單位,也是由頁組成的,每個頁大小為8KB,與tcmalloc中span組成的默認基本內(nèi)存單位頁大小相同。mspan里面按照8*2n大小(8b,16b,32b .... ),每一個mspan又分為多個object。

就連名字也很像,mspan中的m應(yīng)該是memory的第一個字母。

mcache

mcache跟tcmalloc中的ThreadCache相似,ThreadCache為每個線程的cache,同理,mcache可以為golang中每個Processor提供內(nèi)存cache使用,每一個mcache的組成單位也是mspan。

mcentral

mcentral跟tcmalloc中的CentralCache相似,當(dāng)mcache中空間不夠用,可以向mcentral申請內(nèi)存??梢岳斫鉃閙central為mcache的一個“緩存庫”,供mcaceh使用。它的內(nèi)存組成單位也是mspan。

mcentral里有兩個雙向鏈表,一個鏈表表示還有空閑的mspan待分配,一個表示鏈表里的mspan都被分配了。

mheap

mheap跟tcmalloc中的PageHeap相似,負責(zé)大內(nèi)存的分配。當(dāng)mcentral內(nèi)存不夠時,可以向mheap申請。那mheap沒有內(nèi)存資源呢?跟tcmalloc一樣,向OS操作系統(tǒng)申請。

還有,大于32KB的內(nèi)存,也是直接向mheap申請。

總結(jié)

golang內(nèi)存分配幾個相關(guān)概念,用圖來總結(jié)一下:

 

深入理解golang:內(nèi)存分配原理

后面再進一步分析golang的內(nèi)存分配原理。

五、參考

  • 可視化golang內(nèi)存管理
  • 《操作系統(tǒng)的設(shè)計與實現(xiàn)》
  • a-program-in-memory linux內(nèi)核分析很棒的文章

 

責(zé)任編輯:未麗燕 來源: 博客園
相關(guān)推薦

2024-02-21 21:14:20

編程語言開發(fā)Golang

2023-09-19 22:47:39

Java內(nèi)存

2021-11-18 09:20:29

Channel語言代碼

2022-12-28 09:07:41

2020-08-10 18:03:54

Cache存儲器CPU

2024-04-15 00:00:00

技術(shù)Attention架構(gòu)

2023-11-05 12:05:35

JVM內(nèi)存

2024-03-12 00:00:00

Sora技術(shù)數(shù)據(jù)

2022-11-04 09:43:05

Java線程

2021-03-10 10:55:51

SpringJava代碼

2022-09-05 08:39:04

kubernetesk8s

2024-11-01 08:57:07

2013-06-20 10:25:56

2020-03-17 08:36:22

數(shù)據(jù)庫存儲Mysql

2019-07-01 13:34:22

vue系統(tǒng)數(shù)據(jù)

2022-09-05 22:22:00

Stream操作對象

2023-10-13 13:30:00

MySQL鎖機制

2020-03-26 16:40:07

MySQL索引數(shù)據(jù)庫

2022-09-26 08:01:31

線程LIFO操作方式

2022-01-14 12:28:18

架構(gòu)OpenFeign遠程
點贊
收藏

51CTO技術(shù)棧公眾號