爲了追求更快,CPU、內存、I/O都作了哪些努力?

背景

前段時間,寫了一篇《高性能開發十大技術》,有讀者給我私信交流,····程序員

曾經,我面試的時候有兩個最怕的。一怕問算法,二怕問高併發。面試

算法這個,自從關注了「小浩算法」,刷了很多LeetCode,發現仍是有套路可循的,雖不敢說算法能力有多強,至少沒有之前那麼怕了(纔怪)。算法

而第二個,高性能高併發技術,感受有好多技術要學,東學一點,西學一點,不成體系。直到有一次面試,遇到了一個大牛,問到了這方面,結果被虐的體無完膚。幸運的是,這位大牛不但技術一流,還認真跟我交流了學習心得,怎麼樣去有體系的系統去梳理這方面的技術知識,而不是瞎學。數據庫

CPU

無論什麼樣的編程語言,什麼樣的代碼框架,最終都是由CPU去執行完成的(固然這麼說不太準確,也有GPU、TPU、協處理器等其餘狀況,固然這不是本文探討的重點)。編程

因此要想提升性能,提升併發量,首要問題就是如何讓CPU跑的更快?c#

這個問題,也是一直以來CPU廠商一直在努力追求的方向。後端

如何讓CPU更快?CPU廠商作了兩個方面的努力:緩存

  • 加快指令執行的速度服務器

  • 加快CPU讀取數據的速度網絡

對於第一個方向,CPU執行指令的快慢,是跟CPU的主頻緊密相關的,如何更快的取指令、指令譯碼、執行,縮短CPU的指令週期,提高主頻在至關長一段時間裏都是很是有效的辦法。

從幾百MHz,到現在到幾GHz,CPU主頻有了長足的進步,相同時間裏可以執行的指令數變的更多了。

對於第二個方向,如何提高CPU讀取數據的速度,答案就是加緩存,利用局部性原理將內存中常常會訪問的數據搬運到CPU中,這樣大大提高了存取速度。

從一級緩存,到二級緩存,乃至三級緩存,CPU緩存的層級和容量也在不斷提高,讀寫數據的時間省了很多。

但隨着時間到推移,尤爲進入21世紀以後,處理器廠商發現,進一步提高主頻變得愈來愈困難了,CPU的緩存也很難進一步擴容。

怎麼辦呢?既然一我的幹活的速度已經很難再提高,那何很少找幾我的一塊兒幹?因而,多核技術來了,一個CPU裏面有多個核心,衆人划槳開大船,CPU的速度再一次騰飛~

甚至,讓一個核在「閒暇時間」,利用「閒置資源」去執行另外的線程,誕生了讓一個核「同時」執行兩個線程的超線程技術

上面簡單交代了爲了提高性能,CPU所作的努力。可是光是CPU快是沒用的,還須要咱們更好的去利用開發,不然就是對CPU算力的浪費。

上面提到了線程,是的,如何提升性能,提升併發量?使用多線程技術固然是一個很是好的思路。

但多線程的引入,就不得不提到兩個跟線程有關的話題:

  • 線程同步

  • 線程阻塞

多個線程協同工做,必然會引入同步的問題,常規解決方案是加鎖,加鎖的線程通常會進入阻塞。

線程遇到阻塞了,就須要切換,而切換是有必定的成本開銷的,不只是系統調度的時間開銷,還可能有CPU緩存失效的損失。

若是線程頻頻加鎖,頻頻阻塞,那這個損失就至關可觀了。爲了提高性能,無鎖編程技術就出現了,利用CPU提供的機制,提供更輕量的加鎖方案。

同時,爲了讓切換後的線程仍然可以在以前的CPU核心上運行,下降緩存損失,線程的CPU親和性綁定技術也出現了。

現代操做系統都是以時間片的形式來調度分配給多個線程使用。若是時間片還沒用完就由於這樣或那樣的緣由將執行機會拱手相讓,那線程也太虧了。

因而,有人提出要充分利用CPU,別讓線程阻塞,交出執行權,本身在應用層實現多個執行流的調度,這裏阻塞了,就去執行那裏,總之要把時間片充分用完,這就誕生了協程技術,阻塞了沒關係,我還能幹別的,不要輕易發生線程切換。

內存

與CPU工做相關的第一親密夥伴就是內存了,兩者協做才能唱好一齣戲。

提高內存訪問的速度,一樣是高性能開發話題重要組成部分!

那如何提高呢?硬件層面程序員是很難改變的,我們只好從軟件層面下功夫。

內存的管理經歷了從實地址模式到分頁式內存管理,現在的計算機中,CPU拿的的地址都是虛擬地址,這中間就會涉及到地址的轉換,在這裏就有文章可作,有兩個方向能夠努力:

  • 減小缺頁異常

  • 使用大頁技術

現代操做系統,基本上都會使用一個叫換頁/交換文件的技術:內存空間有限,但進程愈來愈多,對內存空間的需求愈來愈大,用完了怎麼辦?因而在硬盤上劃分一塊區域出來,把內存中好久不用的數據轉移到這塊區域上來,等程序用到的時候,觸發訪問異常,再在異常處理函數中將其從硬盤讀取進來。

能夠想象,若是程序訪問的內存總是不在內存中,而是被交換到了硬盤上,就會頻繁觸發缺頁異常,那程序的性能確定大打折扣,因此減小缺頁異常也是提高性能的好辦法。

從虛擬地址尋址真實的物理內存,這個過程是CPU完成的,具體來講,就是經過查表,從頁表->一級頁目錄->二級頁目錄->物理內存。

頁目錄和頁表是存在內存中的,毫無疑問,內存尋址是一個很是很是高頻的事情,時時刻刻都在發生,而屢次查表勢必是很慢的,有鑑於此,CPU引入了一個叫TLB(Translation Look- aside buffer)的東西,使用緩存頁表項的方式來減小內存查表的操做,加快尋址速度。

默認狀況下,操做系統是以4KB爲單位管理內存頁的,對於一些須要大量內存的服務器程序(Redis、JVM、ElascticSearch等等),動輒就是幾十個G,按照4KB的單位劃分,那得產生多少的頁表項啊!

而CPU中的TLB的大小是有限的,內存越多,頁表項也就越多,TLB緩存失效的機率也就越大。因此,大頁內存技術就出現了,4KB過小,就弄大點。大頁內存技術的出現,減小了缺頁異常的出現次數,也提升了TLB命中的機率,對於提高性能有很大的幫助。

在一些高配置的服務器上,內存數量龐大,而CPU多個核都要經過內存總線訪問內存,可想而知,CPU核數上去之後,內存總線的競爭勢必也會加重。因而NUMA架構出現了,把CPU核心劃分不一樣的分組,各自使用本身的內存訪問總線,提升內存的訪問速度。

I/O

CPU和內存都夠快了,但這仍是不夠。咱們的程序平常工做中,除了一些CPU密集型的程序(執行數學運算,加密解密,機器學習等等)之外,至關一部分時間都是在執行I/O,如讀寫硬盤文件、收發網絡數據包等等。

因此,如何提高I/O的速度,是高性能開發技術領域一個重要的話題

由於I/O會涉及到與外設(硬盤、網卡等)的交互,而這些外設又一般是很是慢(相對CPU執行速度)的,因此正常狀況下,線程執行到I/O操做時不免會阻塞,這也是前面在CPU部分提到過的。

阻塞之後那就沒辦法幹活了,爲了能幹活,那就開多個線程。但線程資源是很昂貴的,沒辦法大量使用,何況線程多了,多個線程切換調度一樣是很花時間的。

那可不可讓線程執行I/O時不阻塞呢?因而,新的技術又出現了:

  • 非阻塞I/O

  • I/O多路複用

  • 異步I/O

原來的阻塞I/O是一直等,等到I/O的完成,非阻塞I/O通常是輪詢,能夠去幹別的事,過一下子就來問一下:好了沒有?

但每一個線程都去輪詢也不是個事兒啊,乾脆交給一個線程去專門負責吧,這就是I/O多路複用,經過select/poll的方式只用一個線程就能夠處理多個I/O目標。再而後,再改進一下,用epoll,連輪詢也不用了,改用內核喚醒通知的機制,同時處理的I/O目標還更多了。

異步I/O就更爽了,設置一個回調函數,本身幹別的事去了,回頭操做系統叫你來收數據就行了。

再說回到I/O自己,會將數據在內存和外設之間傳輸,若是數據量很大,讓CPU去搬運數據的話,既耗時又沒有技術含量,這是對CPU算力的很大浪費。

因此,爲了將CPU從中解放出來,又誕生了一門技術:直接內存訪問DMA,把數據的傳輸工做外包出去,交由DMA控制器來完成,CPU只在背後發號施令便可。

有了DMA,不再用麻煩CPU去執行數據的搬運工做。但對於應用程序而言,想要把文件經過網絡發送出去,仍是要把數據在內核態空間和用戶態空間來回折騰兩次,這兩步還得CPU出馬去複製拷貝,屬於一種浪費,爲了解決這個問題,提高性能,又進一步產生了零拷貝技術,完全爲CPU減負。

算法架構

CPU、內存、I/O都夠快了,單臺計算機的性能已經很難提高了。不過,如今的服務器不多是單打獨鬥了,接下來就要把目光轉移到算法、架構上來了。

一臺服務器搞不定,那就用硬件堆出性能來,分佈式集羣技術負載均衡技術就派上用場了。

這年頭,哪一個後端服務沒有數據庫?如何讓數據庫更快?該輪到索引技術上了,經過給數據庫創建索引,提高檢索速度。

但數據庫這傢伙的數據畢竟是存在硬盤上的,讀取的時候勢必會慢,要是大量的數據請求都懟上來,這誰頂得住?因而基於內存的數據庫緩存Redis、Memcached應運而生,畢竟,訪問內存比從數據庫查詢快得多。

算法架構這一塊的技術實在太多了,也是從一個普通碼農通往架構師的必經之路,我們下回再聊。

總結

高性能、高併發是後端開發永恆追求的話題。

每一項技術都不是憑空出現的,必定是爲了解決某個問題而提出。咱們在學這些技術的時候,掌握它出現的緣由,和其餘技術之間的關聯,在本身的大腦中創建一座技術知識層級圖,必定能事半功倍。

這幅圖中的絕大多數技術,我以前都有對應的趣味故事文章進行闡述,歡迎你們去翻一番~

關於本文,你有什麼想說的呢,或者有什麼重要技術被我遺漏了,歡迎留言討論。


1.看明白了CAN的錯幀漏檢,車廠就不能敷衍你了!

2.Gartner發佈2021年重要戰略科技趨勢!

3.設計電路時,哪些蠢哭咱們青春的事...

4.Linux x86 和ARM什麼區別?

5.探討STM32啓動文件中的幾個問題~

6.在生產中使用Rust的著名公司及他們選擇的理由!

免責聲明:本文系網絡轉載,版權歸原做者全部。如涉及做品版權問題,請與咱們聯繫,咱們將根據您提供的版權證實材料確認版權並支付稿酬或者刪除內容。

相關文章
相關標籤/搜索