Go語言自亮相以來并沒有展示一個(gè)明確的方向,Google員工將Go語言稱為一個(gè)“試驗(yàn)性語言”,稱其試圖融合Python等動(dòng)態(tài)語言的開發(fā)速度和C或C++等編譯語言的性能和安全。一位Go語言的支持者概括而言Go語言如下:簡(jiǎn)單、快速、安全、并發(fā)、快樂編程、開源;但Go語言缺乏方向以及其“集大成者”的嘗試很容易會(huì)導(dǎo)致其學(xué)貓不成學(xué)狗也不成,淪為四不像。盡管如此,編者仍然覺得Go語言有相當(dāng)大的潛力:很多開發(fā)者對(duì)它感興趣——不僅它的最初設(shè)計(jì)者陣容強(qiáng)大,而且在參與修改源代碼的人群中也不乏大牛級(jí)人物。這很有可能幫助Go語言找到適合自己的方向,開拓系統(tǒng)編程的新方向。
站在用戶的角度思考問題,與客戶深入溝通,找到永仁網(wǎng)站設(shè)計(jì)與永仁網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、網(wǎng)絡(luò)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋永仁地區(qū)。
1、學(xué)習(xí)曲線
它包含了類C語法、GC內(nèi)置和工程工具。這一點(diǎn)非常重要,因?yàn)镚o語言容易學(xué)習(xí),所以一個(gè)普通的大學(xué)生花一個(gè)星期就能寫出來可以上手的、高性能的應(yīng)用。在國(guó)內(nèi)大家都追求快,這也是為什么國(guó)內(nèi)Go流行的原因之一。
2、效率
Go擁有接近C的運(yùn)行效率和接近PHP的開發(fā)效率,這就很有利的支撐了上面大家追求快速的需求。
3、出身名門、血統(tǒng)純正
之所以說Go語言出身名門,是因?yàn)槲覀冎繥o語言出自Google公司,這個(gè)公司在業(yè)界的知名度和實(shí)力自然不用多說。Google公司聚集了一批牛人,在各種編程語言稱雄爭(zhēng)霸的局面下推出新的編程語言,自然有它的戰(zhàn)略考慮。而且從Go語言的發(fā)展態(tài)勢(shì)來看,Google對(duì)它這個(gè)新的寵兒還是很看重的,Go自然有一個(gè)良好的發(fā)展前途。我們看看Go語言的主要?jiǎng)?chuàng)造者,血統(tǒng)純正這點(diǎn)就可見端倪了。
4、組合的思想、無侵入式的接口
Go語言可以說是開發(fā)效率和運(yùn)行效率二者的完美融合,天生的并發(fā)編程支持。Go語言支持當(dāng)前所有的編程范式,包括過程式編程、面向?qū)ο缶幊桃约昂瘮?shù)式編程。
5、強(qiáng)大的標(biāo)準(zhǔn)庫
這包括互聯(lián)網(wǎng)應(yīng)用、系統(tǒng)編程和網(wǎng)絡(luò)編程。Go里面的標(biāo)準(zhǔn)庫基本上已經(jīng)是非常穩(wěn)定,特別是我這里提到的三個(gè),網(wǎng)絡(luò)層、系統(tǒng)層的庫非常實(shí)用。
6、部署方便
我相信這一點(diǎn)是很多人選擇Go的最大理由,因?yàn)椴渴鹛奖?,所以現(xiàn)在也有很多人用Go開發(fā)運(yùn)維程序。
7、簡(jiǎn)單的并發(fā)
它包含降低心智的并發(fā)和簡(jiǎn)易的數(shù)據(jù)同步,我覺得這是Go最大的特色。之所以寫正確的并發(fā)、容錯(cuò)和可擴(kuò)展的程序如此之難,是因?yàn)槲覀冇昧隋e(cuò)誤的工具和錯(cuò)誤的抽象,Go可以說這一塊做的相當(dāng)簡(jiǎn)單。
8、穩(wěn)定性
Go擁有強(qiáng)大的編譯檢查、嚴(yán)格的編碼規(guī)范和完整的軟件生命周期工具,具有很強(qiáng)的穩(wěn)定性,穩(wěn)定壓倒一切。那么為什么Go相比于其他程序會(huì)更穩(wěn)定呢?這是因?yàn)镚o提供了軟件生命周期的各個(gè)環(huán)節(jié)的工具,如go
tool、gofmt、go test。
在開始之前,希望你計(jì)算一下 Part1 共占用的大小是多少呢?
輸出結(jié)果:
這么一算, Part1 這一個(gè)結(jié)構(gòu)體的占用內(nèi)存大小為 1+4+1+8+1 = 15 個(gè)字節(jié)。相信有的小伙伴是這么算的,看上去也沒什么毛病
真實(shí)情況是怎么樣的呢?我們實(shí)際調(diào)用看看,如下:
輸出結(jié)果:
最終輸出為占用 32 個(gè)字節(jié)。這與前面所預(yù)期的結(jié)果完全不一樣。這充分地說明了先前的計(jì)算方式是錯(cuò)誤的。為什么呢?
在這里要提到 “內(nèi)存對(duì)齊” 這一概念,才能夠用正確的姿勢(shì)去計(jì)算,接下來我們?cè)敿?xì)的講講它是什么
有的小伙伴可能會(huì)認(rèn)為內(nèi)存讀取,就是一個(gè)簡(jiǎn)單的字節(jié)數(shù)組擺放
上圖表示一個(gè)坑一個(gè)蘿卜的內(nèi)存讀取方式。但實(shí)際上 CPU 并不會(huì)以一個(gè)一個(gè)字節(jié)去讀取和寫入內(nèi)存。相反 CPU 讀取內(nèi)存是 一塊一塊讀取 的,塊的大小可以為 2、4、6、8、16 字節(jié)等大小。塊大小我們稱其為 內(nèi)存訪問粒度 。如下圖:
在樣例中,假設(shè)訪問粒度為 4。 CPU 是以每 4 個(gè)字節(jié)大小的訪問粒度去讀取和寫入內(nèi)存的。這才是正確的姿勢(shì)
另外作為一個(gè)工程師,你也很有必要學(xué)習(xí)這塊知識(shí)點(diǎn)哦 :)
在上圖中,假設(shè)從 Index 1 開始讀取,將會(huì)出現(xiàn)很崩潰的問題。因?yàn)樗膬?nèi)存訪問邊界是不對(duì)齊的。因此 CPU 會(huì)做一些額外的處理工作。如下:
從上述流程可得出,不做 “內(nèi)存對(duì)齊” 是一件有點(diǎn) "麻煩" 的事。因?yàn)樗鼤?huì)增加許多耗費(fèi)時(shí)間的動(dòng)作
而假設(shè)做了內(nèi)存對(duì)齊,從 Index 0 開始讀取 4 個(gè)字節(jié),只需要讀取一次,也不需要額外的運(yùn)算。這顯然高效很多,是標(biāo)準(zhǔn)的 空間換時(shí)間 做法
在不同平臺(tái)上的編譯器都有自己默認(rèn)的 “對(duì)齊系數(shù)”,可通過預(yù)編譯命令 #pragma pack(n) 進(jìn)行變更,n 就是代指 “對(duì)齊系數(shù)”。一般來講,我們常用的平臺(tái)的系數(shù)如下:
另外要注意,不同硬件平臺(tái)占用的大小和對(duì)齊值都可能是不一樣的。因此本文的值不是唯一的,調(diào)試的時(shí)候需按本機(jī)的實(shí)際情況考慮
輸出結(jié)果:
在 Go 中可以調(diào)用 unsafe.Alignof 來返回相應(yīng)類型的對(duì)齊系數(shù)。通過觀察輸出結(jié)果,可得知基本都是 2^n ,最大也不會(huì)超過 8。這是因?yàn)槲沂痔幔?4 位)編譯器默認(rèn)對(duì)齊系數(shù)是 8,因此最大值不會(huì)超過這個(gè)數(shù)
在上小節(jié)中,提到了結(jié)構(gòu)體中的成員變量要做字節(jié)對(duì)齊。那么想當(dāng)然身為最終結(jié)果的結(jié)構(gòu)體,也是需要做字節(jié)對(duì)齊的
接下來我們一起分析一下,“它” 到底經(jīng)歷了些什么,影響了 “預(yù)期” 結(jié)果
在每個(gè)成員變量進(jìn)行對(duì)齊后,根據(jù)規(guī)則 2,整個(gè)結(jié)構(gòu)體本身也要進(jìn)行字節(jié)對(duì)齊,因?yàn)榭砂l(fā)現(xiàn)它可能并不是 2^n ,不是偶數(shù)倍。顯然不符合對(duì)齊的規(guī)則
根據(jù)規(guī)則 2,可得出對(duì)齊值為 8?,F(xiàn)在的偏移量為 25,不是 8 的整倍數(shù)。因此確定偏移量為 32。對(duì)結(jié)構(gòu)體進(jìn)行對(duì)齊
Part1 內(nèi)存布局:axxx|bbbb|cxxx|xxxx|dddd|dddd|exxx|xxxx
通過本節(jié)的分析,可得知先前的 “推算” 為什么錯(cuò)誤?
是因?yàn)閷?shí)際內(nèi)存管理并非 “一個(gè)蘿卜一個(gè)坑” 的思想。而是一塊一塊。通過空間換時(shí)間(效率)的思想來完成這塊讀取、寫入。另外也需要兼顧不同平臺(tái)的內(nèi)存操作情況
在上一小節(jié),可得知根據(jù)成員變量的類型不同,其結(jié)構(gòu)體的內(nèi)存會(huì)產(chǎn)生對(duì)齊等動(dòng)作。那假設(shè)字段順序不同,會(huì)不會(huì)有什么變化呢?我們一起來試試吧 :-)
輸出結(jié)果:
通過結(jié)果可以驚喜的發(fā)現(xiàn),只是 “簡(jiǎn)單” 對(duì)成員變量的字段順序進(jìn)行改變,就改變了結(jié)構(gòu)體占用大小
接下來我們一起剖析一下 Part2 ,看看它的內(nèi)部到底和上一位之間有什么區(qū)別,才導(dǎo)致了這樣的結(jié)果?
符合規(guī)則 2,不需要額外對(duì)齊
Part2 內(nèi)存布局:ecax|bbbb|dddd|dddd
通過對(duì)比 Part1 和 Part2 的內(nèi)存布局,你會(huì)發(fā)現(xiàn)兩者有很大的不同。如下:
仔細(xì)一看, Part1 存在許多 Padding。顯然它占據(jù)了不少空間,那么 Padding 是怎么出現(xiàn)的呢?
通過本文的介紹,可得知是由于不同類型導(dǎo)致需要進(jìn)行字節(jié)對(duì)齊,以此保證內(nèi)存的訪問邊界
那么也不難理解,為什么 調(diào)整結(jié)構(gòu)體內(nèi)成員變量的字段順序 就能達(dá)到縮小結(jié)構(gòu)體占用大小的疑問了,是因?yàn)榍擅畹販p少了 Padding 的存在。讓它們更 “緊湊” 了。這一點(diǎn)對(duì)于加深 Go 的內(nèi)存布局印象和大對(duì)象的優(yōu)化非常有幫
網(wǎng)站名稱:go語言cpu優(yōu)化,go 編譯優(yōu)化
標(biāo)題URL:http://jinyejixie.com/article20/dsedejo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器、網(wǎng)站制作、動(dòng)態(tài)網(wǎng)站、網(wǎng)站建設(shè)、網(wǎng)站導(dǎo)航、做網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)