(2)Linux性能調優之Linux內存體系

1、前言

上一節咱們談了Linux的進程管理:緩存

(1)Linux性能調優之Linux進程管理bash

這一節咱們將談下Linux的內存體系架構

2、概覽

進程執行過程當中,Linux內核根據須要給進程分配一塊內存區域。進程就把這片區域做爲工做區,按要求執行操做。這就像給你分配一張本身的桌子,你能夠在桌子上擺放文檔,備忘錄,開展本身的工做。區別在於,內核以更加動態的方式分配空間。系統上運行的進程常常是成千上萬的,可是內存倒是有限的。因而,Linux必須高效的處理內存問題。在本節中,將介紹Linux內存架構、地址佈局、以及Linux如何高效管理內存空間。app

先簡單總結下,若是內存有限的狀況下,好比8G,你開啓了大量的應用,勢必會致使電腦卡頓,運行緩慢,甚至無反應的!函數

3、內存體系

  • 3.1 物理和虛擬內存

現實中,咱們常常會面臨32位仍是64位操做系統的選擇(雖然如今32位已經基本淘汰了),對用戶來講,它們間最大的差異是可否支持4GB以上的虛擬內存空間。站在性能的角度來理解32位和64位的系統,Linux映射物理內存到虛擬內存的區別是十分有趣的。以下圖所示,能夠明顯看出內存映射方式在32位和64位系統上的區別。咱們不去詳盡探索物理內存映射到虛擬內存的細節,對於性能調優,咱們只須要了解一下Linux的內存架構的一些知識就夠了。佈局

32位架構的機器上,Linux內核只能直接映射第一個GB的的物理內存(896M,由於還要考慮到保留的空間)。在此上的內存被稱做ZONE_NORMAL,這部分空間必須映射到最下面的1GB。這種映射對應用程序是徹底透明的,可是分配內存頁到ZONE_HIGHMEM會形成一點 點性能損耗。post

另外一方面,在64位系統上,例如在IA-64上面,ZONE_NORMAL一直延伸到64GB或者128GB。如你所見,把內存頁從ZONE_HIGHMEM映射到ZONE_NORMAL這種損耗在64位系統上是不存在的。性能

下圖展現了32位和64位架構Linux系統的虛擬尋址佈局:spa

在32位架構上,單個進程能夠利用的最大地址空間是4GB,這是受到了32位虛擬內存映射的限制。在標準的32位環境中,虛擬地址被劃分爲3GB的用戶空間和1GB的內存空間,現實中也存在一些4GB/4GB地址佈局。操作系統

再說64位架構,由於沒有內存限制存在,每一個進程可以都有可能使用巨大的地址空間。

  • 3.2 虛擬內存管理器

因爲操做系統把全部內存都映射成虛擬內存,因此,操做系統的物理內存架構對用戶和應用程序一般都是不可見的。若是咱們要掌握Linux內存調優的辦法,就必須先理解Linux如何處理虛擬內存。如3.1所說的那樣,應用程序不使用物理內存,而是向Linux內核請求一個特定大小的內存映射,而且收到一個虛擬內存的映射。以下圖所示,虛擬內存沒必要要必定是物理內存的映射,若是某個應用程序使用了一塊超大的虛擬內存,這虛擬內存其中某一部分多是由磁盤上的swap空間映射來的。

從圖中能夠看出來,應用程序常常不是直接寫入磁盤子系統,而是首先寫入cache或者buffer,而後,在pdflush空閒的時候、或者某個文件大小超出buffer和cache的時候,由pdflush內核線程把buffer或cache中的數據寫入磁盤。參考後面的寫入髒buffer部分。

Linux內核管理磁盤緩存的方式,和內核寫數據到文件系統的方式有緊密聯繫。和其它操做系統都只分配特定的部份內存做爲磁盤緩存的方式相比,Linux處理內存資源更加高效。

虛擬內存管理器默認配置把全部的可用空閒內存空間做爲磁盤緩存,因此,常常能夠見到Linux系統明明擁有數GB級的內存,卻只有20M處於空閒狀態。

Linux一樣高效利用swap空間,當操做系統開始使用swap空間的時候,並不表示系統出現了內存瓶頸,而是證實了Linux如何有效的使用系統資源。參考頁幀回收(page frame reclaiming)。

下面簡單介紹下幾個重要概念:

  1. 頁幀分配(Page frame allocation)

頁是物理內存或虛擬內存中一組連續的線性地址,Linux內核以頁爲單位處理內存,頁的大小一般是4KB。當一個進程請求必定量的頁面時,若是有可用的頁面,內核會直接把這些頁面分配給這個進程,不然,內核會從其它進程或者頁緩存中拿來一部分給這個進程用。內核知道有多少頁可用,也知道它們的位置。

  1. 夥伴系統(Buddy system)

Linux內核使用名爲夥伴系統(Buddy system)的機制維護空閒頁。夥伴系統維護空閒頁面,而且嘗試給發來頁面申請的進程分配頁面,它還努力保持內存區域是連續的。若是不考慮到零散的小頁面可能會致使內存碎片,並且在要分配一個連續的大內存頁時將變得很困難,這就可能致使內存使用效率下降和性能降低。下圖說明了夥伴系統如何分配內存頁:

若是嘗試分配內存頁失敗,就啓動回收機制。能夠在/proc/buddyinfo文件看到夥伴系統的信息:

  1. 頁幀回收

若是在進程請求指定數量的內存頁時沒有可用的內存頁,內核就會嘗試釋放特定的內存頁(之前使用過,如今沒有使用,而且基於某些原則仍然被標記爲活動狀態)給新的請求使用。這個過程叫作內存回收。kswapd內核線程和try_to_free_page()內核函數負責頁面回收。

kswapd一般在task interruptible狀態下休眠,當一個區域中的空閒頁低於閾值的時候,它就會被夥伴系統喚醒。它基於最近最少使用原則(LRU,Least Recently Used)在活動頁中尋找可回收的頁面。最近最少使用的頁面被首先釋放。它使用活動列表和非活動列表來維護候選頁面。kswapd掃描活動列表,檢查頁面的近期使用狀況,近期沒有使用的頁面被放入非活動列表中。使用vmstat -a命令能夠查看有分別有多少內存被認爲是活動和非活動狀態:

kswapd還要遵循另一個原則。頁面主要有兩種用途:頁面緩存(page cahe)和進程地址空間(process address space)。頁面緩存是指映射到磁盤文件的頁面;進程地址空間的頁面(又叫作匿名內存,由於不是任何文件的映射,也沒有名字)使用來作堆棧使用的。在回收內存時,kswapd更偏向於回收頁面緩存。

若是大部分的頁面緩存和進程地址空間來自於內存回收,在某些狀況下,可能會影響性能。咱們能夠經過修改/proc/sys/vm/swappiness文件來控制這個行爲:

  1. swap分區

在發生頁面回收時,屬於進程地址空間的處於非活動列表的候選頁面會發生page out。擁有交換空間自己是很正常的事情。在其它操做系統中,swap無非是保證操做系統能夠分配超出物理內存大小的空間,可是Linux使用swap的空間的辦法更加高效。虛擬內存由物理內存和磁盤子系統或者swap分區組成。在Linux中,若是虛擬內存管理器意識到內存頁已經分配了,可是已經好久沒有使用,它就把內存頁移動到swap空間。

Page out和swap out:「page out」和「swap out」很容易混淆。「page out」意思是把一些頁面
(整個地址空間的一部分)交換到swap;"swap out"意味着把全部的地址空間交換到swap。
複製代碼

4、更通俗的理解

虛擬內存由物理內存和磁盤子系統或者swap分區組成。這話的意思是,物理內存,磁盤還有swap分區這些物理設備合在一塊兒被抽象虛擬成了一個大內存,叫作虛擬內存。進程在虛擬內存上分配的地址會被映射道物理設備上,因此可能部分在物理內存,可能在swap分區,多是磁盤上(我的理解)。

基於上述,有一下幾點理解:

  1. 每一個進程都有本身獨立的4G內存空間而這4G內存空間只是虛擬內存空間,每次訪問內存空間的某個地址,都須要把地址翻譯爲實際物理內存地址

  2. 一個新進程創建的時候,將會創建起本身的內存空間,此進程的數據,代碼等從磁盤拷貝到本身的進程空間,哪些數據在哪裏,都由進程控制表中的task_struct記錄,task_struct中記錄中一條鏈表,記錄中內存空間的分配狀況,哪些地址有數據,哪些地址無數據,哪些可讀,哪些可寫,均可以經過這個鏈表記錄

  3. 全部進程共享同一物理內存,每一個進程只把本身目前須要的虛擬內存空間映射並存儲到物理內存上(參考3.1)。

  4. 進程要知道哪些虛擬內存地址上的數據在物理內存上,哪些不在,還有在物理內存上的位置,須要用頁表來記錄

  5. 頁表的每個表項分兩部分,第一部分記錄此頁是否在物理內存上,第二部分記錄物理內存頁的地址(若是在的話)

  6. 當進程訪問某個虛擬地址,去看頁表,若是發現對應的數據不在物理內存中,則缺頁異常。缺頁異常的處理過程,就是把進程須要的數據從磁盤上拷貝到物理內存中,若是內存已經滿了,沒有空地方了,那就找一個頁覆蓋,固然若是被覆蓋的頁曾經被修改過,須要將此頁寫回磁盤

5、下一節是???

談完Linux的內存體系,下一節將會談一下Linux的文件系統

相關文章
相關標籤/搜索