計(jì)算機(jī)是如何跑起來的?
1
在學(xué)習(xí)工作中,經(jīng)常會(huì)遇到些讓我腦子短路無法回血的問題?
你去評(píng)估下這項(xiàng)目需要幾臺(tái)機(jī)器能維持穩(wěn)定性,CPU要幾核,內(nèi)存要多大?
X模塊偶發(fā)出現(xiàn)內(nèi)存飆升的情況,你追查下原因順便想想如何優(yōu)化?
瞬間,鴉雀無聲甚至氣氛一度及其尷尬。作為一個(gè)CURD男孩,寫代碼就是一把梭復(fù)制粘貼,那能管那么寬?仔細(xì)一想,我也是學(xué)過計(jì)算機(jī)組成原理、操作系統(tǒng)原理的男孩,豈能說慫就慫?
這時(shí),馮·諾依曼、寄存器、內(nèi)存、二進(jìn)制、補(bǔ)碼這些詞忽隱忽現(xiàn)的飄過,就像一堆雜亂無章的思緒擠地鐵一樣擠入我的腦海。然而,我發(fā)現(xiàn)這跟上面的問題并沒有絲毫聯(lián)系,仿佛我有一把方天畫戟卻切不動(dòng)一盤菜的感覺,并沒有什么用。
我相信,大多數(shù)同學(xué)在熟練編寫業(yè)務(wù)代碼后,會(huì)在出現(xiàn)一些復(fù)雜問題后被委以重任,這就非常考驗(yàn)大家的基本功了。
于是,我趁疫情在家時(shí)間充裕,花了一些時(shí)間閱讀書籍和思考,嘗試再去總結(jié)下計(jì)算機(jī)的基礎(chǔ)知識(shí)。
2
??
首先,我先從計(jì)算機(jī)的三大原則開始說起。
1. 是什么?計(jì)算機(jī)是執(zhí)行輸入、運(yùn)算、輸出的機(jī)器

計(jì)算機(jī)本質(zhì)上就是一臺(tái)機(jī)器,機(jī)器的工作模式:接收指令(輸入)、理解指令(運(yùn)算)、做出動(dòng)作(輸出)。工作模式很簡(jiǎn)單,關(guān)鍵是計(jì)算機(jī)如何理解指令的呢?
舉個(gè)例子:在一個(gè)陽(yáng)光明媚的早上,你對(duì)你對(duì)象說:不去上班行不行?你對(duì)象嬌滴滴的回答:不去上班你養(yǎng)我啊?
針對(duì)這橋段,你仔細(xì)想想你對(duì)象腦子里是怎么流轉(zhuǎn)的?
輸入:聲音(漢語(yǔ))
理解:
接收聲信號(hào)
分析聲信號(hào)是鳥語(yǔ)、英語(yǔ)、日語(yǔ)還是漢語(yǔ)?
從腦庫(kù)存(內(nèi)存)中抽取積累的信息(學(xué)習(xí)所得),自我翻譯理解
輸出:表情(嬌滴滴) + 聲音(漢語(yǔ))
其實(shí),計(jì)算機(jī)也有三大基礎(chǔ)元件。
CPU(處理器):負(fù)責(zé)解釋、執(zhí)行程序。
內(nèi)存:負(fù)責(zé)存儲(chǔ)程序和數(shù)據(jù)。
I/O(Input/Output):負(fù)責(zé)將計(jì)算機(jī)和外部設(shè)備(周邊設(shè)備)連接在一起。
簡(jiǎn)單說,I/O就相當(dāng)于五官跟大自然連接的器官,內(nèi)存就相當(dāng)于你的腦庫(kù)存(腦知識(shí)庫(kù)),CPU就相當(dāng)于你的腦神經(jīng)中樞。
2. 怎么交流?計(jì)算機(jī)只能理解數(shù)字
不同人種,不同的生物,有不同的語(yǔ)言。機(jī)器也不例外,它也有獨(dú)特的語(yǔ)言,你只有跟它說數(shù)字才能理解。
你可能質(zhì)疑道:放屁,我明明在我的瀏覽器用搜索引擎搜索關(guān)鍵字「靚仔」,它給我輸出「博主照片」,它明明可理解中文。
其實(shí),這功勞就要?dú)w功于程序,程序充當(dāng)了中間翻譯官。比如,我們?nèi)祟惐旧硎菬o法識(shí)別語(yǔ)言的,有些人上知天文下知地理,而有些人卻只會(huì)牛逼和臥槽。這一切,取決于我們的腦庫(kù)存的知識(shí),這些知識(shí)會(huì)把外界的信息進(jìn)行翻譯讓大腦能夠理解。
于是,計(jì)算機(jī)中的內(nèi)存是程序的載體,計(jì)算機(jī)只能理解數(shù)字,那么程序就必須被翻譯成數(shù)字才能在計(jì)算機(jī)中運(yùn)行。 程序要想運(yùn)行起來,它將經(jīng)歷:程序 -> 編譯(翻譯)-> 機(jī)器語(yǔ)言。
這時(shí)候,你可能會(huì)想:程序到底是什么東西,能解釋清楚嗎?
3. 程序是什么?指令和數(shù)據(jù)的集合
程序就像是我們腦庫(kù)存中的知識(shí)庫(kù)一樣,數(shù)據(jù)相當(dāng)于人的記憶,指令相當(dāng)于人的邏輯。
舉個(gè)例子:
例子 1:
1 + 1 = 2
1是數(shù)據(jù),+運(yùn)算是指令
例子 2:
int i = 1; // 數(shù)據(jù)
int j = 0; // 數(shù)據(jù)
// 指令:順序、條件、循環(huán)
if (i > 0) {
j = i + i;
} else {
j = i - i;
}
3
?
通過敘述,大概解釋清楚了計(jì)算機(jī)的硬核元件是CPU、內(nèi)存、I/O,程序的硬核內(nèi)容是數(shù)據(jù)、指令,程序存儲(chǔ)在內(nèi)存中供CPU讀取執(zhí)行運(yùn)算。
那么,我們用Java、C還是Php寫程序,到底在寫什么?
本質(zhì)上,寫程序就是在輸入初始值(申請(qǐng)內(nèi)存),執(zhí)行運(yùn)算(順序、條件、循環(huán)),輸出預(yù)期值(寫入內(nèi)存)。

但是,我們知道內(nèi)存是連續(xù)的,順序執(zhí)行是順理成章的被計(jì)算機(jī)理解,條件/循環(huán)執(zhí)行呢?于是,就出現(xiàn)跳轉(zhuǎn)指令,用于跳轉(zhuǎn)到指定的程序塊。
基于內(nèi)存約束,數(shù)據(jù)也就是連續(xù)存儲(chǔ)在內(nèi)存中。但是,人類對(duì)世界的需求是千奇百怪的,更不是純線性結(jié)構(gòu)的。同時(shí),我們又無法去改變內(nèi)存的結(jié)構(gòu)。
于是,出現(xiàn)了很多的數(shù)據(jù)結(jié)構(gòu)。
線性:鏈表、堆、棧
樹狀:二叉樹
圖狀:鄰接矩陣、鄰接表、逆鄰接表、十字鏈表
那么,這些數(shù)據(jù)結(jié)構(gòu)有什么用?本質(zhì)上來說,是為了適應(yīng)各種運(yùn)算方式從而找到最優(yōu)解也就是算法,我認(rèn)為「數(shù)據(jù)結(jié)構(gòu)」是為「算法」服務(wù)的,這樣才能更好的運(yùn)轉(zhuǎn)。
簡(jiǎn)單說,程序就是「數(shù)據(jù) + 指令」線性存儲(chǔ)在內(nèi)存中供CPU調(diào)遣,CPU運(yùn)算就是在執(zhí)行順序、條件、循環(huán)的運(yùn)算邏輯。為了滿足現(xiàn)實(shí)世界的訴求,人類為了更好讓機(jī)器服務(wù),于是研究出了各種各樣的運(yùn)算法則(算法),算法需要特殊的存儲(chǔ)結(jié)構(gòu)(數(shù)據(jù)結(jié)構(gòu)),這樣在現(xiàn)實(shí)世界與機(jī)器就友好相處了。
4
?
通過上面分析,你仔細(xì)想想學(xué)習(xí)編程語(yǔ)言的過程?
第一課:數(shù)據(jù)類型(int、long、char、指針、bool)
第二課:運(yùn)算符(+-*/)、控制流程(順序、條件、循環(huán))
第三課:數(shù)組、結(jié)構(gòu)體、類
第四課:集合
第五課:文件、網(wǎng)絡(luò)(I/O)
第六課:并發(fā)編程(CPU)
第七課:內(nèi)存管理(內(nèi)存)
其實(shí),邏輯是很簡(jiǎn)單,你按這邏輯去學(xué)習(xí)新編程語(yǔ)言也可以輕松上手,主要關(guān)注不同語(yǔ)言的差異。
學(xué)習(xí)程序基礎(chǔ)結(jié)構(gòu)「數(shù)據(jù) + 指令」。于是,先學(xué)習(xí)數(shù)據(jù)類型,運(yùn)算方式、控制流程、數(shù)組、結(jié)構(gòu)體、類。
為了簡(jiǎn)化我們的使用成本,于是必然會(huì)有很多可復(fù)用的集合「數(shù)據(jù)結(jié)構(gòu) + 算法」,list、map、set一定會(huì)與你相遇,只不過是穿什么大褲衩罷了。
網(wǎng)絡(luò)編程、文件處理,就是計(jì)算機(jī)跟外界接觸的器官,輸入/輸出罷了。
CPU是執(zhí)行運(yùn)算的大腦,為了更好的榨干CPU,那就必然會(huì)并發(fā)編程,至于怎么并就取決于計(jì)算機(jī)有幾核。
內(nèi)存管理就像倉(cāng)庫(kù)管理,你要有進(jìn)有出。那么,內(nèi)存你申請(qǐng)了不釋放,必然會(huì)出現(xiàn)飆升升直到倉(cāng)庫(kù)爆滿掛掉。不同的是,內(nèi)存管理是一項(xiàng)基本工作,大多數(shù)語(yǔ)言有自動(dòng)回收機(jī)制,少數(shù)則需要手動(dòng)回收。
這樣,我們理清楚了計(jì)算機(jī)硬件跟我們寫的程序在宏觀上的一個(gè)關(guān)系。于是,我們回到最初的問題。
問題1: 你去評(píng)估下這項(xiàng)目需要幾臺(tái)機(jī)器能維持穩(wěn)定性,CPU要幾核,內(nèi)存要多大?
根據(jù)監(jiān)控峰值QPS,根據(jù)不同QPS狀況統(tǒng)計(jì)CPU和內(nèi)存的占用情況,根據(jù)實(shí)際情況給個(gè)折中值就好。
問題2: X模塊偶發(fā)出現(xiàn)內(nèi)存飆升的情況,你追查下原因順便想想如何優(yōu)化?
這就是個(gè)內(nèi)存管理問題,主要去review內(nèi)存申請(qǐng)和銷毀的程序邏輯,重點(diǎn)看是否有申請(qǐng)不釋放的代碼,輔之以工具,那就好辦了。
總而言之,有時(shí)候并不是碰到的問題的有多難,而是如何去思考定位關(guān)鍵問題,輔之以工具,不斷實(shí)驗(yàn)和調(diào)試,從根本上解決問題。而不是,胡子眉毛一把抓,或怒氣沖冠大喊尼瑪狗逼,或驚慌失措叨叨涼了涼了。
歡迎關(guān)注“編碼之外”

女朋友為我寫了一個(gè)防猝死插件

大學(xué)四年,我終于把編程學(xué)拉垮了!

再見了!錘子!!!
