這些術語關乎你的程序執行效率

Cache 與 Memory

由於CPU的速度遠高於Memory,Cache 是位於CPU與內存(Memory,RAM)之間的臨時存儲器,它的容量比內存小但交換速度快,寄存了RAM位置的地址及數據內容。當CPU要讀取RAM位置數據時,首先從Cache中查找,如果找到就立即讀取並送給CPU處理;如果沒有找到,就從Memory中讀取並送給CPU處理,同時把這個數據所在的數據塊調入Cache中。對Cache寫數據須標註或Memory同步。Cache又分爲一級(L1)、二級(L2)和三級(L3),L1/L2 Cache集成在CPU內部,L3 Cache焊在主板上。

 

Cache 與 Buffer

Cache與Buffer有可能指硬件實現,如硬盤自帶緩存、CPU Cache,也可能指軟件實現也有,如web服務器緩存、瀏覽器緩存。一般而言,Cache更傾向於讀相關,Buffer更偏向於寫相關,但在某些場景下讀與寫是兼備的。下邊講的cache和buffer是內存空間中的概念,運行 free -m 時將輸出如下信息:

cenze@kylin:~$ free -m
              total        used        free      shared  buff/cache   available
Mem:           3898        2003         185         229        1709        1390
Swap:          3914           0        3914

buffer (cache)指塊設備的讀寫緩衝,linux有一個守護進程定期寫buffer內容(包括已修改的 i-node、已延遲的塊 I/O 和讀寫映射文件)到disk,或手動運行sync命令寫buffer數據到disk;(page) cache指文件系統緩存;shared主要用於不同進程之間共享數據,是進程間通信的一種方法,一般的應用程序不會申請使用共享內存。 

A buffer is something that has yet to be written to disk. 
A cache is something that has been read from the disk and stored for later use.

引文中的Buffer和Cache還是指的系統爲Disk分配的內存空間。Disk Buffer主要是爲寫(緩衝)用的,多次數據寫可以先寫入Disk Buffer,最後一次性做慢速的Disk寫,能起到保護Disk的作用;Disk Cache主要是爲讀(緩存)用的,這裏不再贅述。 

 

堆(Heap)與棧(Stack)

在不同語境下,堆與棧的含義不同。

 ◊ 內存中的堆棧分區
(1)是爲線程執行預留的內存空間,每一個線程都有一個對應的棧,棧數據不能在棧間共享(Java棧內部多個值相等的變量是可以指向同一個地址的)。棧由編譯器自動分配釋放 ,臨時存放函數參數、局部變量等大小和生存期確定的數據,用完立即釋放。

函數調用過程中的返回地址、參數和局部變量都採用棧的方式存放。
在函數調用時,在大多數的C編譯器中,第一個進棧的是發生函數調用的下一條執行語句地址(即返回地址),
然後參數由右往左入棧,再然後是函數中的局部變量。
棧以LIFO方式存取,系統爲棧使用一級緩存,速度較快;
棧是機器系統提供的數據結構,計算機在硬件底層對棧提供支持,如分配專門的寄存器存放棧的地址和
執行壓棧出棧指令,因此棧的訪問效率高。
棧空間連續,最大容量有限制(當棧空間耗盡時產生棧溢出錯誤:Stack Overflow),
cenze@kylin:~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15398
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15398
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
從ulimit -a的輸出信息可知,本機的棧空間大小上限是8192K(8M),POSIX message queues 指可用於IPC的隊列最大長度爲819200B(800K)。ulimit可用於shell啓動進程資源佔用限制。

(2)是動態分配的,一般由程序員(malloc或new)分配(free或delete)釋放, 若程序員不釋放,由虛擬機或程序退出後由OS回收。堆空間分配會遍歷空閒內存地址鏈表,系統爲堆使用二級緩存,存取速度較慢;

操作系統有一個記錄堆棧空閒內存地址的鏈表,
當收到程序的申請時,會從低地址向高地址遍歷該鏈表,尋找第一個空間大於所申請空間的結點,
然後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序;
大多數系統會在這塊內存空間中的首地址處記錄本次分配的大小,
這樣代碼中的delete或free語句就能夠正確釋放其所佔的內存空間;另外,
由於找到的結點的大小不一定正好等於所申請的大小,系統會將多餘的那部分重新放入空閒鏈表中。

堆空間不連續,尺寸上限受限於有效的虛擬內存,另外每一個應用程序通常只有一個堆(內存分配使用多個堆的情況也有)。

 ◊ 數據結構中的堆棧:堆指一種滿足堆排序性質的數據結構,如優先隊列;棧是一種先進後出的數據結構。

 

下圖展示了Linux 系統的虛擬內存分段映射(32位系統4GB內存),用戶程序將被映射到用戶空間中的不同分段,擁有自己的地址空間:

 
 
 注:地址段映射發生隨機偏移(Random Offset)是爲了防止潛在的漏洞攻擊引用絕對地址,如堆棧地址、庫函數地址等。下邊這段來自Wikipedia關於Memory-mapped file
 A memory-mapped file is a segment of virtual memory that has been assigned a direct byte-for-byte
correlation with some portion of a file or file-like resource. This resource is typically a file that is physically
present on disk, but can also be a device, shared memory object, or other resource that the operating
system can reference through a file descriptor. Once present, this correlation between the file and the
memory space permits applications to treat the mapped portion as if it were primary memory.
......
A possible benefit of memory-mapped files is a "lazy loading", thus using small amounts of RAM even for
a very large file. Trying to load the entire contents of a file that is significantly larger than the amount of
memory available can cause severe thrashing as the operating system reads from disk into memory and
simultaneously writes pages from memory back to disk. Memory-mapping may not only bypass the page
file completely, but the system only needs to load the smaller page-sized sections as data is being edited,
similarly to demand paging scheme used for programs.

 

多核CPU與多CPU

 ◊ 多核CPU:指單個CPU內包含了多個核心,可分爲原生多核和封裝多核兩種,前者抗壓能力強,性能穩定。通過 cat /proc/cpuinfo 可查看本機CPU相關信息如下:

processor	: 3
...
stepping	: 7
microcode	: 0x14
cpu MHz		: 799.968
cache size	: 3072 KB
physical id	: 0
siblings	: 4
core id		: 1
cpu cores	: 2
...

上表顯示了本機CPU信息的一部分,processor = 3 表示本機編號3的邏輯處理器單元(當前CPU使用了超線程技術),physical id = 0 表示編號0的CPU,siblings = 4 表示當前CPU共有4個邏輯處理器單元(4核),core id = 1 表示當前CPU編號爲1的物理核心,cpu cores = 2 表示本機擁有的物理核心數。

vCPU是虛擬機中對CPU的稱謂,一般按照物理核心數與服務器總vCPU數的比例以1:5 ~1:10來分配較爲合理。更多內容可參考 VM設計之一vCPU

 ◊ 多CPU:多見於企業級產品,如MPP、NUMA系統。多CPU架構最大的瓶頸就是CPU之間的I/O通訊成本。

 ◊ 多核CPU與多CPU的差別
  • 多核CPU功耗低,多個CPU功耗大;
  • 多核CPU是單體體積小,多個CPU多體體積大;
  • 多核CPU核心之間數據交換快,多個CPU之間數據交換慢;
  • 多核CPU共用內存,多個CPU各自配備專屬內存。

 

注:超線程(Hyper-Threading,HT)把物理核心模擬成了多個邏輯處理器單元,讓應用程序在同一時間裏可以使用芯片的不同部分,使芯片能同時進行多個線程處理,讓芯片性能得到提升;但對某些程序或未多線程編程的程序而言,它反而會降低效能。 

 

並行(Parallellism)與併發(Concurrency)

並行如多個CPU同時執行多個任務,是真同時進行的;而併發如單個CPU通過CPU調度算法交替執行多個任務,讓用戶看上去是同時進行的,但實際上在即時時間點只處理單一任務。下圖是 Erlang 之父 Joe Armstrong 對這個問題的形象解釋:
 

 

SMP、MPP和NUMA

◊ SMP(Symmetric Multi-Processor)對稱多處理器架構

  • SMP包含多個處理器(核心),每個處理器都有自己的控制單元、算術邏輯單元和寄存器;
  • 每個處理器都可以通過某種互聯機制(通常是系統總線)訪問一個共享的主存和I/O設備,還可以通過存儲器中共享地址空間中的消息和狀態信息相互通信;
  • SMP廣泛應用於PC和移動設備領域,並行度很高,能夠顯著提升性能,但擴展能力有限;
  • SMP系統只運行操作系統的一個拷貝,不同處理器被授權均勻訪問(Uniform Memory Access,UMA亦稱作統一尋址技術或統一內存存取)存儲器的不同部分,但同一時間只能有一個處理器訪問存儲器。

 ◊ MPP(Massively Parallel Processing)大規模並行處理架構

  • MPP每個SMP單元都只訪問本地資源(總線、內存、I/O等),彼此完全無共享(Share Nothing), 節點互聯是在節點間通過 I/O 實現的(稱爲數據重分配Data Redistribution ,對用戶是透明的);
  • MPP每個SMP單元內都有操作系統和數據庫的實例;
  • MPP需要一種複雜的機制來調度和平衡各個節點的負載和並行處理過程,節點之間的信息交互與節點本身的處理是並行的;
  • MPP擴展能力最好,理論上其擴展無限制,目前的技術可實現512個節點互聯,數千個 CPU。

 ◊ NUMA(Non-Uniform Memory Access)非統一內存訪問架構:因本地內存的訪問速度遠遠高於遠地內存的訪問速度而得名

  • NUMA與SMP架構類似,所有SMP節點的處理器都可以訪問全系統中的物理存儲器,節點互聯是在同一個物理服務器內部實現的;
  • NUMA採用分佈式存儲器模式,通過提供分離的存儲器給各個處理器,避免SMP中多個處理器無法同時訪問存儲器的問題;
  • NUMA中每個處理器訪問本節點存儲器所需要的時間,可能比訪問其他節點存儲器所花的時間要少得多;
  • NUMA既保持了SMP單一操作系統拷貝、簡便應用程序編程以及易於管理的特點,又繼承了大規模並行處理MPP的可擴充性,可以有效地擴充系統的規模。

   

NUMA架構局部內存的訪存延遲低於遠地內存訪存延遲,因此Linux採用局部結點分配策略:當一個任務請求分配內存時,首先在自己的結點內尋找空閒頁,如果沒有則到相鄰的結點中尋找空閒頁,如果還沒有則到遠程結點中尋找空閒頁,從而在操作系統級優化了訪存性能。 

◊ 架構類型選擇

  • 數據倉庫 + MPP:數據倉庫環境具有大量複雜的數據處理和綜合分析,要求系統具有很高的 I/O 處理能力,並且內存儲系統需要提供足夠的 I/O 帶寬與之匹配。MPP的並行處理能力更優越,節點的 I/O 性能突出,更適合於複雜的數據綜合分析與處理環境,當然需要藉助於支持 MPP 技術的關係數據庫系統來屏蔽節點之間負載平衡與調度的複雜性。
  • OLTP + NUMA:OLTP每個交易所涉及的數據不多,要求系統具有很高的聯機事務處理能力,能夠在單位時間裏處理儘量多的交易。而NUMA在一個物理服務器內集成許多 CPU,使系統具有較高的事務處理能力,但遠地訪存延時長於本地,所以要儘量減少不同節點之間的數據交互。

 但這些並不是絕對的,性能的好壞由很多因素組成,單從服務器架構一個方面分析性能有一定的片面性。

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章