成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一文徹底搞懂“內存管理”

原創
存儲 存儲軟件
筆者面試過不少業務后臺開發候選人,當問起內存管理的相關問題時,往往都會答出 JVM 的垃圾回收機制,并對 Serial、Parallel、CMS 等收集器如數家珍,侃侃而談。

【51CTO.com原創稿件】筆者面試過不少業務后臺開發候選人,當問起內存管理的相關問題時,往往都會答出 JVM 的垃圾回收機制,并對 Serial、Parallel、CMS 等收集器如數家珍,侃侃而談。

[[408196]]

圖片來自 包圖網

然而對于應用層以下的內存管理機制卻鮮有人能答出來,甚至于認為 JVM 直接管理了物理內存。

誠然,許多的高級語言如 Java、Go、Python 等已經內置了完善的自動內存管理機制,開發者可以"開箱即用"。

但如果只知其表,不知其里,在出現系統性能問題時往往手足無措,無法全面思考解決問題。

今天筆者嘗試從 0 開始,用一篇文章講明內存管理。

V1.0:直接使用物理地址

最開始的時候,計算機只允許運行一個進程,內存也只有幾百 KB 大小,那時候的世界很簡單也很美好,保留一部分內存空間給 OS 使用,剩下的都是這個進程的專屬空間,想怎么用怎么用,如圖 1-1。

但為了更高效地利用 CPU 的計算資源,OS 需要支持"同時"運行多個進程,此時內存空間按固定大小被瓜分為幾塊,分屬于各個進程使用,如圖 1-2。

由于是直接使用內存物理地址,如果這些進程都很"本分",只訪問自己的空間,那么一切都還正常,但如果某個進程闖入他人的領地,胡作非為呢?可控性是個問題。

V2.0:增加抽象轉換層,使用虛擬地址

當考慮到增加管控、安全校驗、動態分配等問題時,增加一層抽象進行"代理"往往是一個通用的解決方案。

到 2.0,進程不再被允許直接使用物理內存空間,而是使用從 0 開始編碼的虛擬地址,經由 MMU(Memory Management Unit)轉換得到實際地址,然后才能到內存中獲取到數據。

中間層 MMU 會檢查虛擬地址的有效性和合法性,從而保證安全性。

考慮到內存空間使用的靈活性,內存按固定大小進行分頁(Paging),通常是 4KB,連續的虛擬地址頁(VP,Virtual Page),映射到物理地址頁(PP, Physical Page)上,可以是分散的,這種靈活的設計可以提升物理內存的空間利用率,減少內存碎片。

既然有映射,自然需要存儲映射關系表,即頁表(Page Table),Key 值是虛擬地址頁號(Virtual Page Number)。

Value 值是包含有物理地址頁號(PPN,Physical Page Number)的數據結構(PTE,Page Table Entry),值得一提的是,頁表不存在 MMU 里面,同樣也是存在內存里。

圖 2-1 簡要地展示了虛擬地址到物理地址的轉換過程:

為了方便說明,這里頁大小設置為 16 字節(2^4,offset 占用 4bit),總的物理內存大小有 8 頁(2^3,PPN 占用 3bit)即 128 字節,虛擬內存至多使用 4 個頁(2^2,vpn 占用 2bit)。

MMU 將一個 6bit 的虛擬地址轉化為 7bit 的物理地址,其中通過頁表完成 vpn 到 PPN 的轉換,而 offset 部分保持不動。

①V2.1 時間優化:增加 TLB 緩存

在計算機領域,當考慮性能提升的問題時,使用緩存是個萬金油般的解決方案。

其背后主要是基于時空局限性理論(temporal/spatial locality):時間上,一個剛被訪問過的數據,很可能在不久之后被再次訪問;空間上,一個剛被訪問過的空間 x,很可能在不久之后 x 的鄰近空間也被訪問。

很自然地,我們可以在 MMU 里面加入一小塊緩存空間,即快表 TLB(Translation Lookasid Buffer),里面保存著最近的 vpn->PPN 映射關系。

如果緩存命中(TLB Hit),將極大地提升地址轉換速度,如果緩存未命中(TLB Miss),則重新從頁表中查詢。

遺憾的是,空間和時間永遠是一對矛盾,TLB 容量越大,訪問速度也隨著降低,你無法實現一個足夠大的 TLB 去替換掉內存上的頁表,因此當 TLB 快滿時,通常會使用近似 LRU 的算法將最少被使用的單元踢除。

圖 2-2 和 2-3 分別展示了 TLB 命中和未命中情況下的流程,如果命中,則只需一次物理內存訪問;如果未命中,則會先到物理內存中查詢 PTE,并更新至 TLB,然后再訪問真正的數據地址。

②V2.2 空間優化:多級頁表和交換分區

進行時間優化后,我們再來思考空間上有哪些可以優化的。我們注意到,原始的線性頁表會隨著虛擬內存的增大而增大。

試算一下,一個 32bit 大小的虛擬地址(2^32),分頁大小為 4KB(2^12),則會有 1M 個分頁 (2^20)。

假如一個映射單元 PTE 占用 4 個字節,則光存儲這個進程的映射表就需要 4MB。

如果機器上同時運行了 100 個進程,那么將吃掉 400MB 大小的內存空間!這對于整個系統來說將是極大的浪費。

避免這種浪費的關鍵在于,并非所有的虛擬分頁都需要保存其映射關系,對于還未被使用的分頁群,可以只使用一個 PTE(Page Table Entry)表示,而對于連續使用的分片群,可以使用多級映射來定位。

圖 2-4 展示了二級頁表的尋址過程,圖中一級頁表的一個 PTE 可以代表 1 千個 VP。

這樣對于中段大量空閑的 VP,只需使用若干個 PTE 即可表示,顯著地減小了頁表的總大小,對于大容量且稀疏的虛擬地址空間,可以依此類推,再增加幾級頁表。

為了更高效使用我們珍貴的內存空間,除了通過多級頁表節流之外,我們還能通過使用部分磁盤空間,即交換分區,作為虛擬內存來達到開源的效果。

具體來說,我們提供給上層應用的虛擬內存空間是可以大于實際可用的內存空間的。

只要 OS 時不時將一些不常用的內存數據復制到交換分區然后從內存清除,就可以源源不斷地提供新的內存空間。

當讀取到這部分虛擬內存時,再從交換分區恢復到內存就可以了,當然了,這種操作會一定程度上降低內存的讀寫速度。

圖 2-5 展示了增加了交換分區后的工作流程,當 OS 發現要查找的 PTE 既不在 TLB 中,也不在內存中,就會拋出一個 Page Fault 異常,OS 再異步地從交換分區中查找出 PTE 并寫回內存,完成后 CPU 再發起重試就可以了。

V3.0:無招勝有招,自動管理內存

通過上述的設計,操作系統為上層應用搭建了一個安全舒適的虛擬樂園,在這個樂園里面,應用無需關注真實的內存轉換、尋址等繁瑣事項,只管在需要時 malloc 申請內存,不需要時 free 掉即可。

然而隨著應用復雜度的快速上升,即使是自己的一畝三分地,也常常因為疏漏或者 Bug 導致申請的內存未及時釋放,造成內存泄露最終導致應用崩潰。

由此以 JVM 為代表的一系列自動內存管理平臺應運而生,通過定期掃描內存中的數據對象,使用引用計數法或者可達性分析,區分出數據對象是否可回收,再結合標記-清除算法、復制算法等實現內存垃圾回收。

關于垃圾回收器的具體實現業界仍在不斷地更迭出新,這里不再細述。

結語

本文嘗試從最基礎的設計開始,逐步引入虛擬地址轉換,隨后進行時間和空間上的優化,最后介紹應用層的自動內存管理機制,循序漸進,希望能幫你構建出一幅內存管理的基本藍圖。

當然,基于篇幅的限制,真實的系統設計細節遠比本文介紹復雜得多,會引入更多層級的緩存、映射,并基于硬件特性做更多的優化策略以提升內存使用效率。

但大道至簡,理解其最核心的設計思路,再去看技術細節,相信會幫你更快地理解領悟。

作者:李騰輝

簡介:Akulaku 高級開發工程師,目前負責金融借貸平臺架構設計及核心建設工作,對微服務體系、JVM 虛擬機及操作系統原理機制有較深入的研究,擅長定位并解決線上疑難問題。

編輯:陶家龍

征稿:有投稿、尋求報道意向技術人請添加小編微信 gordonlonglong

【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】

 

責任編輯:武曉燕 來源: 51CTO技術棧
相關推薦

2020-03-18 14:00:47

MySQL分區數據庫

2022-06-07 10:13:22

前端沙箱對象

2020-12-07 06:19:50

監控前端用戶

2021-07-08 10:08:03

DvaJS前端Dva

2019-11-06 17:30:57

cookiesessionWeb

2024-08-08 14:57:32

2022-04-11 10:56:43

線程安全

2021-08-05 06:54:05

觀察者訂閱設計

2023-04-12 08:38:44

函數參數Context

2023-11-23 06:50:08

括號

2020-12-18 09:36:01

JSONP跨域面試官

2024-04-12 12:19:08

語言模型AI

2022-03-24 08:51:48

Redis互聯網NoSQL

2021-01-06 13:52:19

zookeeper開源分布式

2021-10-20 08:49:30

Vuexvue.js狀態管理模式

2023-09-15 12:00:01

API應用程序接口

2023-09-08 08:20:46

ThreadLoca多線程工具

2021-03-22 10:05:59

netstat命令Linux

2019-12-04 13:50:07

CookieSessionToken

2023-01-27 18:55:37

Python內置函數
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 不用播放器看的av | 国产一区二区三区四区五区3d | 久久精品久久久 | 国精品一区二区 | 国产高清视频在线 | 精品久久一区 | 久久久久国产 | 国产成人精品午夜视频免费 | 一级一片在线观看 | 美女在线观看国产 | 亚洲巨乳自拍在线视频 | 九一视频在线观看 | 在线不卡一区 | 91精品久久久久久久久久 | 欧洲av在线 | 国产精品爱久久久久久久 | 亚洲成人播放器 | aaa大片免费观看 | 福利精品在线观看 | 国产在线网站 | 青青草网站在线观看 | 久久夜色精品国产 | 日韩中文一区 | 一区二区三区在线免费观看 | 天天草草草 | 久久精品视频免费观看 | 欧美精品久久久 | 亚洲一区二区在线 | 国产午夜精品久久久 | 亚洲午夜三级 | 精品精品 | 久久精品一区 | 精品一区二区三区在线视频 | 亚洲一区二区三区免费视频 | 亚洲欧美一区二区三区在线 | 精品一区二区三区四区五区 | 亚洲二区精品 | 在线一区视频 | 狠狠躁夜夜躁人人爽天天高潮 | 精品欧美一区二区三区久久久 | 天天色官网 |