欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

內(nèi)存優(yōu)化之重新認(rèn)識內(nèi)存-創(chuàng)新互聯(lián)

我們知道,手機(jī)的內(nèi)存是有限的,如果應(yīng)用內(nèi)存占用過大,輕則引起卡頓,重則導(dǎo)致應(yīng)用崩潰或被系統(tǒng)強(qiáng)制殺掉,更嚴(yán)重的情況下會影響應(yīng)用的留存率。因此,內(nèi)存優(yōu)化是性能優(yōu)化中非常重要的一部分。但是,很多開發(fā)者對內(nèi)存的認(rèn)識還停留在應(yīng)用開發(fā)這一層,平時只是參考網(wǎng)上的方案,對內(nèi)存進(jìn)行比較淺顯的優(yōu)化。想要深入進(jìn)行內(nèi)存優(yōu)化,我們需要從操作系統(tǒng)的層面了解內(nèi)存是怎么管理的,又是如何被使用的。

成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供溫州網(wǎng)站建設(shè)、溫州做網(wǎng)站、溫州網(wǎng)站設(shè)計、溫州網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、溫州企業(yè)網(wǎng)站模板建站服務(wù),十多年溫州做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。

可能會有人疑問:“為什么做個內(nèi)存優(yōu)化需要從操作系統(tǒng)層了解內(nèi)存呢?”我們確實可以在網(wǎng)上搜到很多內(nèi)存優(yōu)化的文章,但它們都是從上層應(yīng)用出發(fā)進(jìn)行優(yōu)化的,而不同的應(yīng)用因為環(huán)境不一樣、業(yè)務(wù)不一樣,很多優(yōu)化方法都不能通用。因此,只有當(dāng)我們從底層掌握了內(nèi)存的原理,從下而上地制定優(yōu)化方案,才能適用于任何業(yè)務(wù),甚至當(dāng)我們轉(zhuǎn)型到 iOS、前端或者后端都能通用。

接下來,我們就從操作系統(tǒng)底層出發(fā),重新認(rèn)識內(nèi)存。

我們先將目光放到操作系統(tǒng)的早期,在這個環(huán)境下,程序都是直接操作物理內(nèi)存的。比如一個程序執(zhí)行如下指令:

MOV REGISTER1,0

計算機(jī)會將位置為 0 的物理內(nèi)存中的內(nèi)容移到 REGISTER1 的寄存器中。在這種情況下,如果第二個程序在 0 的位置寫入一個新的值,就會擦掉第一個程序存放在相同位置上的所有內(nèi)容,導(dǎo)致第一個程序崩潰。

正因為應(yīng)用程序可以直接操作物理內(nèi)存,所以我們完全可以修改其他程序在內(nèi)存中的數(shù)據(jù),導(dǎo)致程序崩潰或者產(chǎn)生安全問題。因此,對當(dāng)時的操作系統(tǒng)來說,同時運行多個程序很困難。

為了解決這個問題,我們自然而然會想到:不允許應(yīng)用程序直接操作物理內(nèi)存。于是虛擬內(nèi)存的技術(shù)誕生了。

為了更好地了解什么是虛擬內(nèi)存,我們先看看早期直接操作物理內(nèi)存系統(tǒng)下的內(nèi)存模型長什么樣。從下面內(nèi)存模型的簡化圖中我們可以看到,物理內(nèi)存中存在兩塊數(shù)據(jù),一個是操作系統(tǒng)的數(shù)據(jù),一個是應(yīng)用程序的數(shù)據(jù)。除此之外,其實還會有設(shè)備驅(qū)動程序的數(shù)據(jù),它們不是我們了解的重點就先不列上去了。

image.png

什么是虛擬內(nèi)存?

虛擬內(nèi)存技術(shù)相當(dāng)于給每個程序一個獨占且連續(xù)的內(nèi)存,比如 32 位系統(tǒng)下是 4G(2^32),只不過這個內(nèi)存是虛擬的。同時,虛擬內(nèi)存需要能夠映射到真實的物理內(nèi)存。簡化的內(nèi)存模型如下

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-haHe4vHL-1670148923898)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/edd00859a2094eaa964f8ce588df1f18~tplv-k3u1fbpfcp-watermark.image?)]
從上圖的簡化內(nèi)存模型,我們可以看到,每個程序都可以獨享一塊虛擬內(nèi)存。在 Linux 系統(tǒng)上,一個進(jìn)程代表著一個程序,這里我們可以理解成每個進(jìn)程都獨享一塊虛擬內(nèi)存,這塊虛擬內(nèi)存在 32 位系統(tǒng)下是 4G(2^32),64 位系統(tǒng)下是 2^48,即 256TB(這里不是 2^64,是因為 256TB 已經(jīng)足夠大了,如果用 2^64,會有大量的尋址空間浪費)。

其次,虛擬內(nèi)存都由應(yīng)用程序和操作系統(tǒng)這兩部分組成。其中,應(yīng)用程序這部分虛擬內(nèi)存是應(yīng)用獨占的,操作系統(tǒng)這部分虛擬內(nèi)存則由所有進(jìn)程共享,而所有進(jìn)程的操作系統(tǒng)這部分虛擬內(nèi)存都指向了同一段物理內(nèi)存。虛擬內(nèi)存到物理內(nèi)存的映射由操作系統(tǒng)來實現(xiàn),操作系統(tǒng)在做映射操作時會尋找可用的物理內(nèi)存,不可能出現(xiàn)覆蓋其他數(shù)據(jù)的情況,這讓同時運行多個程序成為了可能。

上圖的虛擬內(nèi)存是一個簡化的模型。實際上,虛擬內(nèi)存和物理內(nèi)存都是按照頁來管理和映射的,一頁的大小為 4KB,我們來看一個 32 位 Android 系統(tǒng)、物理內(nèi)存為 2G 的設(shè)備的內(nèi)存模型。

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-ysAU5ah2-1670148923899)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/efb87e2370624ccdb09642d2018c0581~tplv-k3u1fbpfcp-watermark.image?)]

可以看到,物理內(nèi)存和虛擬內(nèi)存是通過 4K 大小的頁一一對應(yīng)的。這個時候,如果我們再用文章最開頭的那個指令:

MOV REGISTER1,0

在虛擬內(nèi)存技術(shù)的加持下,此時計算機(jī)就不會直接將物理地址為 0 的內(nèi)存移到 REGISTER1 寄存器了,而是先尋找虛擬地址 0 對應(yīng)的物理地址 4096,然后將物理地址為 4096 的內(nèi)容移到 REGISTER1 寄存器中

MOV REGISTER1,4096

虛擬地址轉(zhuǎn)換成物理地址是由計算機(jī)的內(nèi)存管理單元(MMU)完成的,它屬于硬件部分而不是系統(tǒng)軟件部分,所以轉(zhuǎn)換速度很快。

虛擬內(nèi)存的內(nèi)存模型

知道了虛擬內(nèi)存由操作系統(tǒng)和應(yīng)用程序兩部分組成,并且虛擬內(nèi)存都由頁來維護(hù)和管理之后,我們再深入了解一下 Linux 系統(tǒng)中虛擬內(nèi)存的內(nèi)存模型,它需要和 Linux 系統(tǒng)的可執(zhí)行文件,也就是 ELF 文件一起配合來看。

image.png

為了讓你理解起來更簡單,這里的 ELF 文件格式也被我簡化了,后面用到的時候再進(jìn)行深入介紹。在 Linux 系統(tǒng)中,存放操作系統(tǒng)的虛擬內(nèi)存區(qū)域被稱為內(nèi)核空間,剩下的存放應(yīng)用的虛擬內(nèi)存區(qū)域稱為用戶空間。 內(nèi)核空間占用了 1G,位于虛擬地址的高地址區(qū)域,而 ELF 文件的一些數(shù)據(jù),是存放在低地址的區(qū)域(即從地址 0 開始)。下面我詳細(xì)解釋一下內(nèi)存模型中的幾個區(qū)域

  1. 棧:由編譯器自動分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。

  2. 堆:動態(tài)內(nèi)存分配,可以由開發(fā)者自己分配和釋放(malloc 和 free 函數(shù)實現(xiàn)),Android 開發(fā)時不需要我們手動分配和釋放,因為虛擬機(jī)程序已經(jīng)幫我們做了。堆的開始地址由變量 start_brk 描述,堆的當(dāng)前地址由變量 brk 描述。

  3. BSS:存放全局未初始化,靜態(tài)未初始化數(shù)據(jù)。

  4. 數(shù)據(jù)段:存放全局初始化,靜態(tài)初始化數(shù)據(jù)。

  5. 程序代碼區(qū):存放的是 ELF 文件代碼段。

可以看到,棧內(nèi)存的分配是從上到下的,而堆內(nèi)存的分配是從下到上的,這種方式可以大程度利用虛擬內(nèi)存的空間。

虛擬內(nèi)存分配

前面我們已經(jīng)知道,應(yīng)用是沒法直接操作物理內(nèi)存的,所以我們在開發(fā) App 時分配的內(nèi)存實際都是虛擬內(nèi)存。那么我們怎么申請?zhí)摂M內(nèi)存呢?

開發(fā) Android 應(yīng)用時,并不需要我們自己去分配內(nèi)存,直接 new 一個對象,聲明一個變量或者常量即可,也不需要我們自己去做釋放,但所有的數(shù)據(jù)都需要內(nèi)存,這些都是虛擬機(jī)幫我們做。虛擬機(jī)分配申請內(nèi)存主要使用的是 malloc() 函數(shù),它是 C 語言庫的一個標(biāo)準(zhǔn)函數(shù)。

void *malloc(size_t size)

malloc 函數(shù)是一個 C 語言庫的函數(shù),所以它分配內(nèi)存最終還是得調(diào)用 Linux 系統(tǒng)提供的函數(shù),讓 Linux 內(nèi)核去幫我們申請一塊內(nèi)存。內(nèi)核會調(diào)用 mmap() 函數(shù),在堆中分配我們想要的內(nèi)存空間大小。 mmap() 函數(shù)是 Linux 系統(tǒng)一個很重要的函數(shù),我們需要深刻認(rèn)識它。

void *mmap(void *addr,size_t length,int prot,int flags,int fd, off_t offset);
  • 參數(shù) addr 指向欲映射的內(nèi)存起始地址,通常設(shè)為 NULL,代表讓系統(tǒng)自動選定地址,映射成功后返回該地址;
  • 參數(shù) length 表示將文件中多大的部分映射到內(nèi)存;
  • 參數(shù) prot 指定映射區(qū)域的讀寫權(quán)限;
  • 參數(shù) flags 指定映射時的特性,如是否允許其他進(jìn)程映射這段內(nèi)存;
  • 參數(shù) fd 指定映射內(nèi)存的文件描述符;
  • 參數(shù) offset 指定映射位置的偏移量,一般為 0。

mmap 函數(shù)有 2 種用法:

  1. 映射磁盤文件到用戶空間中;
  1. 匿名映射,不映射磁盤文件,而是向映射區(qū)申請一塊內(nèi)存,此時的 fd 入?yún)?-1。

第 1 種用法可以讓我們讀文件的效率更高(比如 Android 讀取 dex 文件就是通過 mmap 來提高讀取速度),也可以用來實現(xiàn)數(shù)據(jù)跨進(jìn)程傳輸(比如 Android 共享內(nèi)存機(jī)制、Binder 通信都是通過 mmap 來實現(xiàn)的)。malloc() 函數(shù)使用了 mmap 函數(shù)的第 2 種用法,即在 Heap 區(qū)域中申請一塊內(nèi)存。

需要注意的,這里申請的內(nèi)存都是虛擬內(nèi)存,并且這個時候并不會分配真正的物理內(nèi)存,只有當(dāng)我們真正要往這塊虛擬內(nèi)存區(qū)域?qū)懭霐?shù)據(jù)時,操作系統(tǒng)檢查到對應(yīng)的虛擬內(nèi)存沒有映射到物理內(nèi)存,便會發(fā)生缺頁中斷,然后分配一塊同樣大小的物理內(nèi)存,并建立映射關(guān)系。這是一種懶加載技術(shù),也是內(nèi)存優(yōu)化的方案之一。

malloc() 函數(shù)在申請內(nèi)存小于 128k 時會使用 sbrk() 函數(shù),sbrk() 會將堆頂指針(即前面提到的 brk)向高地址移動,獲得新的虛存空間,這些策略都是基于性能考慮的。比如 Android 虛擬機(jī)在分配大對象時,也會專門放在 LargeObjectSpcace 中,這些就不展開講了。至于 Linux 系統(tǒng)是如何發(fā)生缺頁中斷,如何分配物理內(nèi)存,如何建立映射關(guān)系的,都屬于 Linux 系統(tǒng)相關(guān)知識了,更詳細(xì)的知識點會在后面的篇章中結(jié)合實戰(zhàn)項目穿插著講解。

小結(jié)

事實上,直接操作物理內(nèi)存的操作系統(tǒng)并沒有消失,我們現(xiàn)在的嵌入式設(shè)備,如冰箱,微波爐等等都能直接操作物理內(nèi)存。這其實也符合它們的使用場景,直接操作物理內(nèi)存會讓性能開銷更小,操作也更方便。但需要同時運行多個軟件的系統(tǒng)都有虛擬內(nèi)存,可以說虛擬內(nèi)存是現(xiàn)代操作系統(tǒng)最重要的發(fā)明之一了。

當(dāng)我們重新認(rèn)識了內(nèi)存后,我們再來看內(nèi)存優(yōu)化,它其實分為兩部分。

  • 一是物理內(nèi)存的優(yōu)化:也就是這個程序?qū)嶋H消耗的物理內(nèi)存。
  • 二是虛擬內(nèi)存的優(yōu)化:在前面我們也知道了 32 位機(jī)只有 3G 的虛擬內(nèi)存可用,所以一個比較大的Android 程序,很容易就會出現(xiàn)虛擬內(nèi)存不足的情況(64 位系統(tǒng)就完全不用擔(dān)心這個問題)。

在后面的章節(jié)中,我會針對這兩部分,總結(jié)出體系的優(yōu)化方法論,再搭配講解一些優(yōu)化實踐。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前名稱:內(nèi)存優(yōu)化之重新認(rèn)識內(nèi)存-創(chuàng)新互聯(lián)
本文鏈接:http://chinadenli.net/article14/dedgge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站虛擬主機(jī)響應(yīng)式網(wǎng)站小程序開發(fā)動態(tài)網(wǎng)站微信公眾號

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)