欧美一区二区三区,国内熟女精品熟女A片视频小说,日本av网,小鲜肉男男GAY做受XXX网站

從底層架構(gòu)上應(yīng)該具備哪些能力

從底層架構(gòu)上應(yīng)該具備哪些能力?

上層應(yīng)用開發(fā)的多了之后,對(duì)底層技術(shù)的接觸就越來越少了。以至于很多人有了“底層技術(shù)無用論”的觀點(diǎn)。很多人認(rèn)為學(xué)習(xí)框架多好啊,大家都在用,跳槽的時(shí)候也能用的上。學(xué)習(xí)那些底層技術(shù)干啥,平時(shí)都用不到。

本號(hào)并不這么認(rèn)為。我們先舉一個(gè)活生生的例子,比如我們現(xiàn)在有個(gè)Web服務(wù)應(yīng)用,崩潰重啟后在綁定套接字的時(shí)候出現(xiàn)報(bào)錯(cuò)(socket_bind(): unable to bind address [98]: Address already in use。),導(dǎo)致服務(wù)端無法工作。問題比較明確,是地址(端口)被占用了。你這時(shí)候可能會(huì)猜測(cè)那個(gè)程序占了端口呢?大家都清楚,服務(wù)器端口的使用都是嚴(yán)格受限的,肯定是這個(gè)程序。但是可能會(huì)疑惑:“這個(gè)程序不是剛剛起來嗎?!”如果你只是使用API,不懂得底層的原理,別說解決問題,可能都不知道如何下手。這個(gè)問題我們先放到這里,后面再具體解釋,這里只是想說明一下底層技術(shù)的重要性。

另外一個(gè)比較典型的例子是關(guān)于前端開發(fā)的。很多人熱衷于學(xué)習(xí)各種框架。框架雖然能幫助我們解決一些問題,節(jié)省開發(fā)成本并降低開發(fā)周期。但是,學(xué)習(xí)框架并不能掌握技術(shù)的根本,從而導(dǎo)致自己能力沒有本質(zhì)的提升。我們以前端框架為例,在過去的幾年當(dāng)中,JQuery、Bootstrap、Angular和Vue等等等等,輪番上陣。這個(gè)框架你還沒用熟悉呢,結(jié)果又來了一個(gè)新的框架,讓你應(yīng)接不暇。而這些框架最本質(zhì)的東西其實(shí)就是JS、CSS和HTML等內(nèi)容,只有學(xué)會(huì)這些基礎(chǔ)技術(shù),才能游刃有余。如果這些基礎(chǔ)技術(shù)不熟悉,而投入大量精力學(xué)習(xí)框架,這就好像還沒學(xué)會(huì)走,就想著跑,最后自己可能摔得滿頭是包。

可能扯的有點(diǎn)遠(yuǎn),前面的例子只是想告訴大家底層技術(shù)的重要性。對(duì)于我們搞軟件開發(fā)的人來說,底層技術(shù)其實(shí)相當(dāng)于大廈的地基,地基不穩(wěn),大廈是很危險(xiǎn)的。當(dāng)然,計(jì)算機(jī)技術(shù)的細(xì)分領(lǐng)域很多,每個(gè)領(lǐng)域又有自己的底層技術(shù),因此我們不可能都有涉及。今天我們介紹的底層技術(shù)則是最為通用的技術(shù),也就是計(jì)算、存儲(chǔ)、網(wǎng)絡(luò)和數(shù)據(jù)結(jié)構(gòu)與算法。

關(guān)于計(jì)算相關(guān)的內(nèi)容

計(jì)算機(jī)技術(shù)自然核心是計(jì)算了。毫不夸張的說,所有應(yīng)用都要依賴于計(jì)算,小到單機(jī)小游戲,大到電商或者云計(jì)算平臺(tái)。因此,計(jì)算問題自然是我們最為關(guān)心的問題了。說到計(jì)算,最主要的自然是程序的性能了,如果我們開發(fā)的程序的性能提升一倍,就相當(dāng)于硬件成本降低了50%。對(duì)于互聯(lián)網(wǎng)這種需要大量計(jì)算資源的應(yīng)用,其價(jià)值可見一斑。

我們先看一個(gè)具體的例子。下面是一段C語言的代碼,代碼很簡(jiǎn)單,就是將二維數(shù)組中的內(nèi)容做加一操作。但是如果你測(cè)試一下兩段代碼的耗時(shí)的話,就會(huì)發(fā)現(xiàn)兩者有四倍的性能差異。大家可以觀察一下圖中兩端代碼的差異,并思考一下為什么有如此之大的差異。

問題先放一下,我們回到我們今天的主角,CPU。CPU是計(jì)算依賴的硬件,大家都知道計(jì)算是在CPU內(nèi)完成的。我們先看一下CPU長(zhǎng)什么樣。CPU是計(jì)算機(jī)的核心單元,它負(fù)責(zé)從存儲(chǔ)設(shè)備讀取數(shù)據(jù),經(jīng)過計(jì)算后將生成的新數(shù)據(jù)再存儲(chǔ)起來。這就好像一個(gè)大型工廠的生產(chǎn)車間,將原材料加工成半成品或者成品(我們后面單獨(dú)用一個(gè)章節(jié)介紹CPU相關(guān)的內(nèi)容)。

了解了CPU的基本功能,我們?cè)俳馄柿丝纯此奈迮K六腑長(zhǎng)什么樣。下圖是一個(gè)簡(jiǎn)化的CPU內(nèi)部結(jié)構(gòu)圖,最為核心的組件就是計(jì)算單元(ALU)、寄存器(很多寄存器)和高速緩存。另外就是通過總線接口與外部的內(nèi)存進(jìn)行連接。這里面最核心的組件就是ALU了,其原理很簡(jiǎn)單,就是完成加減乘除運(yùn)算。

CPU要進(jìn)行運(yùn)算,就需要原料,而原料需要從內(nèi)存搬運(yùn)。有一個(gè)事實(shí)我們需要記住,就是訪問內(nèi)存的代價(jià)(延時(shí))是訪問寄存器的100倍左右。最早的CPU是直接訪問內(nèi)存的,后來隨著ALU性能的提升,發(fā)現(xiàn)有問題,就在ALU和內(nèi)存之間增加了緩存。現(xiàn)代CPU緩存通常為3級(jí)緩存,分別是L1、L2和L3,其中L1和L2是CPU核獨(dú)有的,而L3是同一顆CPU的多核共享的。其基本的架構(gòu)如下圖所示。

這里面有個(gè)關(guān)鍵問題是緩存的容量是遠(yuǎn)遠(yuǎn)小于主(內(nèi))存的容量的,因此,緩存中的數(shù)據(jù)通常是主存數(shù)據(jù)的很小的一部分。由于應(yīng)用訪問數(shù)據(jù)有區(qū)域局部性的特點(diǎn),因此緩存中的數(shù)據(jù)通常是程序需要的數(shù)據(jù),也就是ALU接下來要用的數(shù)據(jù)。另外一個(gè)需要注意的地方是從主存讀取數(shù)據(jù)到緩存是有一定粒度(專業(yè)術(shù)語叫緩存行)的,當(dāng)前處理器通常是64字節(jié)。如下圖所示,主存中的內(nèi)容被讀取到緩存中。

然后,我們回到一開始的關(guān)于上面兩段程序的性能問題來。上面代碼中一個(gè)是逐行訪問二維數(shù)組,另外一個(gè)是逐列訪問二維數(shù)組。具體示意圖如下圖所示。

在逐行訪問時(shí),訪問的地址是以4字節(jié)為單位跳躍的,由于緩存行大小是64字節(jié),因此很容易命中緩存。而逐列訪問時(shí),每次跳躍4096字節(jié),遠(yuǎn)遠(yuǎn)超越了緩存行的大小,從而導(dǎo)致數(shù)據(jù)大部分是從內(nèi)存讀取的。也正是因?yàn)檫@個(gè),導(dǎo)致兩個(gè)程序有四倍的性能差異。

通過上面的介紹,我們應(yīng)該記住兩個(gè)關(guān)鍵點(diǎn),一個(gè)是訪問內(nèi)存的代價(jià)比較高,因此在編程時(shí)盡量減少對(duì)內(nèi)存的直接訪問;另外一個(gè)是充分利用緩存的優(yōu)勢(shì)。關(guān)于如何做到上面兩點(diǎn),具體細(xì)節(jié)我們后續(xù)專門介紹。

關(guān)于存儲(chǔ)相關(guān)的內(nèi)容

數(shù)據(jù)最終都要存儲(chǔ)在存儲(chǔ)設(shè)備上,否則系統(tǒng)一斷電所有東西都丟了,這個(gè)道理大家都懂。這里的存儲(chǔ)包括磁盤和SSD硬盤等內(nèi)容。本文主要從存儲(chǔ)設(shè)備及管理設(shè)備的文件系統(tǒng)分析存儲(chǔ)相關(guān)關(guān)鍵技術(shù)。存儲(chǔ)中最為重要的有兩個(gè)方面,一個(gè)是存儲(chǔ)數(shù)據(jù)的可靠性,另外一個(gè)是存儲(chǔ)數(shù)據(jù)的性能。

本文先從存儲(chǔ)的性能說起,可靠性我們后續(xù)專門介紹。在存儲(chǔ)領(lǐng)域使用最多的還是普通機(jī)械磁盤。機(jī)械磁盤的內(nèi)部解剖圖如下圖所示,其數(shù)據(jù)的讀寫是通過一個(gè)機(jī)械臂完成的。機(jī)械臂擺來擺去,想想就知道不會(huì)太快。機(jī)械磁盤是IBM發(fā)明的,第一塊磁盤的尋道時(shí)間(機(jī)械臂定位到目的位置的時(shí)間)在600毫秒左右。而現(xiàn)代的機(jī)械磁盤尋道時(shí)間有了比較明顯的改善,但由于其機(jī)械特性的原因,其耗時(shí)還是比較長(zhǎng)的,大概是4-8毫秒的樣子。

以下是付費(fèi)內(nèi)容

這個(gè)耗時(shí)是內(nèi)存的近10萬倍,是寄存器耗時(shí)的千萬倍。因此機(jī)械磁盤的速度相對(duì)內(nèi)存來說,無異于蝸牛對(duì)高鐵的速度。鑒于機(jī)械磁盤的上述缺陷,在軟件層面做了很多考量,從而保證性能最佳。

我們通常在使用硬盤的時(shí)候不會(huì)直接寫代碼訪問(不排除個(gè)例),而是通過操作系統(tǒng)提供的接口訪問。這個(gè)操作系統(tǒng)的接口通常是文件系統(tǒng)的接口。為了便于理解,我們先看一下對(duì)于Linux操作系統(tǒng)來說,磁盤系統(tǒng)的整個(gè)軟硬件棧,從上到下分別是:文件系統(tǒng)、通用塊層、設(shè)備驅(qū)動(dòng)層和設(shè)備層(具體的硬件設(shè)備,可以理解為磁盤)。

在這里有兩個(gè)層面的軟件對(duì)磁盤的訪問做了優(yōu)化,一個(gè)是文件系統(tǒng),另外一個(gè)是通用塊層。其中文件系統(tǒng)的核心功能是磁盤數(shù)據(jù)管理的功能,但考慮到磁盤的缺點(diǎn),因此在讀寫數(shù)據(jù)方法做了一些性能方面的優(yōu)化。而通用塊層則主要是針對(duì)磁盤的特性進(jìn)行了各種優(yōu)化。

文件系統(tǒng)對(duì)磁盤訪問的性能優(yōu)化是通過頁緩存(頁緩存其實(shí)就是內(nèi)存)完成的,這個(gè)頁緩存與CPU中的緩存有異曲同工之妙。文件系統(tǒng)通過頁緩存在數(shù)據(jù)寫和讀兩方面分別作了優(yōu)化。

寫方面的優(yōu)化主要是延遲批量寫,也就是數(shù)據(jù)先寫到頁緩存中,經(jīng)過積累后再磁盤驅(qū)動(dòng)提交。這種積累和延遲寫主要目的是為了增加數(shù)據(jù)的連續(xù)性,也就是為了規(guī)避磁盤機(jī)械臂的擺動(dòng),因?yàn)榇疟P機(jī)械臂擺動(dòng)是最耗時(shí)的。

讀方面的優(yōu)化主要是預(yù)讀功能,預(yù)讀就是根據(jù)當(dāng)前應(yīng)用讀取數(shù)據(jù)的模式,提前將數(shù)據(jù)讀到內(nèi)存當(dāng)中。由于應(yīng)用訪問數(shù)據(jù)的區(qū)域局部性特點(diǎn),這種預(yù)讀就可以避免應(yīng)用直接從磁盤讀取數(shù)據(jù)的延時(shí),從而提高讀性能。

通用塊層的主要作用是針對(duì)磁盤做IO調(diào)度,通俗的講就是決定哪個(gè)IO先發(fā)送到磁盤,哪個(gè)后發(fā)送到磁盤。

針對(duì)機(jī)械磁盤來說,最為重要的就是通用塊層會(huì)進(jìn)行IO的重排序(根據(jù)邏輯地址排序)。如上圖所示,假設(shè)上層應(yīng)用按時(shí)間順序發(fā)送1、2、3、4和5等5個(gè)請(qǐng)求的時(shí)候。此時(shí),通用塊層并不會(huì)按照時(shí)間順序發(fā)送給磁盤,而是按照?qǐng)D中紅色虛線箭頭的順序(1、5、2、4、3)發(fā)送給我。這樣,磁盤的機(jī)械臂就不用來回?cái)[動(dòng),從而大大提升其性能。

其實(shí)說了半天,這里有一點(diǎn)是需要我們注意的,那就是機(jī)械磁盤不善于處理IO地址差異比較大的請(qǐng)求(會(huì)導(dǎo)致機(jī)械臂頻繁擺動(dòng)),這是我們?cè)谧黾軜?gòu)設(shè)計(jì)的時(shí)候需要注意的。雖然操作系統(tǒng)和通用塊層為我們做了很多工作,但其能力畢竟有限,因此我們?cè)谠O(shè)計(jì)的時(shí)候也必須考慮。后面我們會(huì)通過實(shí)例給大家介紹大牛公司在設(shè)計(jì)應(yīng)用的時(shí)候是如何考慮的。

css底層機(jī)制,從底層架構(gòu)上應(yīng)該具備哪些能力