bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

go語(yǔ)言量化分析,golang量化

【golang詳解】go語(yǔ)言GMP(GPM)原理和調(diào)度

Goroutine調(diào)度是一個(gè)很復(fù)雜的機(jī)制,下面嘗試用簡(jiǎn)單的語(yǔ)言描述一下Goroutine調(diào)度機(jī)制,想要對(duì)其有更深入的了解可以去研讀一下源碼。

溫宿網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),溫宿網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為溫宿上千余家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的溫宿做網(wǎng)站的公司定做!

首先介紹一下GMP什么意思:

G ----------- goroutine: 即Go協(xié)程,每個(gè)go關(guān)鍵字都會(huì)創(chuàng)建一個(gè)協(xié)程。

M ---------- thread內(nèi)核級(jí)線程,所有的G都要放在M上才能運(yùn)行。

P ----------- processor處理器,調(diào)度G到M上,其維護(hù)了一個(gè)隊(duì)列,存儲(chǔ)了所有需要它來(lái)調(diào)度的G。

Goroutine 調(diào)度器P和 OS 調(diào)度器是通過(guò) M 結(jié)合起來(lái)的,每個(gè) M 都代表了 1 個(gè)內(nèi)核線程,OS 調(diào)度器負(fù)責(zé)把內(nèi)核線程分配到 CPU 的核上執(zhí)行

模型圖:

避免頻繁的創(chuàng)建、銷毀線程,而是對(duì)線程的復(fù)用。

1)work stealing機(jī)制

當(dāng)本線程無(wú)可運(yùn)行的G時(shí),嘗試從其他線程綁定的P偷取G,而不是銷毀線程。

2)hand off機(jī)制

當(dāng)本線程M0因?yàn)镚0進(jìn)行系統(tǒng)調(diào)用阻塞時(shí),線程釋放綁定的P,把P轉(zhuǎn)移給其他空閑的線程執(zhí)行。進(jìn)而某個(gè)空閑的M1獲取P,繼續(xù)執(zhí)行P隊(duì)列中剩下的G。而M0由于陷入系統(tǒng)調(diào)用而進(jìn)被阻塞,M1接替M0的工作,只要P不空閑,就可以保證充分利用CPU。M1的來(lái)源有可能是M的緩存池,也可能是新建的。當(dāng)G0系統(tǒng)調(diào)用結(jié)束后,根據(jù)M0是否能獲取到P,將會(huì)將G0做不同的處理:

如果有空閑的P,則獲取一個(gè)P,繼續(xù)執(zhí)行G0。

如果沒(méi)有空閑的P,則將G0放入全局隊(duì)列,等待被其他的P調(diào)度。然后M0將進(jìn)入緩存池睡眠。

如下圖

GOMAXPROCS設(shè)置P的數(shù)量,最多有GOMAXPROCS個(gè)線程分布在多個(gè)CPU上同時(shí)運(yùn)行

在Go中一個(gè)goroutine最多占用CPU 10ms,防止其他goroutine被餓死。

具體可以去看另一篇文章

【Golang詳解】go語(yǔ)言調(diào)度機(jī)制 搶占式調(diào)度

當(dāng)創(chuàng)建一個(gè)新的G之后優(yōu)先加入本地隊(duì)列,如果本地隊(duì)列滿了,會(huì)將本地隊(duì)列的G移動(dòng)到全局隊(duì)列里面,當(dāng)M執(zhí)行work stealing從其他P偷不到G時(shí),它可以從全局G隊(duì)列獲取G。

協(xié)程經(jīng)歷過(guò)程

我們創(chuàng)建一個(gè)協(xié)程 go func()經(jīng)歷過(guò)程如下圖:

說(shuō)明:

這里有兩個(gè)存儲(chǔ)G的隊(duì)列,一個(gè)是局部調(diào)度器P的本地隊(duì)列、一個(gè)是全局G隊(duì)列。新創(chuàng)建的G會(huì)先保存在P的本地隊(duì)列中,如果P的本地隊(duì)列已經(jīng)滿了就會(huì)保存在全局的隊(duì)列中;處理器本地隊(duì)列是一個(gè)使用數(shù)組構(gòu)成的環(huán)形鏈表,它最多可以存儲(chǔ) 256 個(gè)待執(zhí)行任務(wù)。

G只能運(yùn)行在M中,一個(gè)M必須持有一個(gè)P,M與P是1:1的關(guān)系。M會(huì)從P的本地隊(duì)列彈出一個(gè)可執(zhí)行狀態(tài)的G來(lái)執(zhí)行,如果P的本地隊(duì)列為空,就會(huì)想其他的MP組合偷取一個(gè)可執(zhí)行的G來(lái)執(zhí)行;

一個(gè)M調(diào)度G執(zhí)行的過(guò)程是一個(gè)循環(huán)機(jī)制;會(huì)一直從本地隊(duì)列或全局隊(duì)列中獲取G

上面說(shuō)到P的個(gè)數(shù)默認(rèn)等于CPU核數(shù),每個(gè)M必須持有一個(gè)P才可以執(zhí)行G,一般情況下M的個(gè)數(shù)會(huì)略大于P的個(gè)數(shù),這多出來(lái)的M將會(huì)在G產(chǎn)生系統(tǒng)調(diào)用時(shí)發(fā)揮作用。類似線程池,Go也提供一個(gè)M的池子,需要時(shí)從池子中獲取,用完放回池子,不夠用時(shí)就再創(chuàng)建一個(gè)。

work-stealing調(diào)度算法:當(dāng)M執(zhí)行完了當(dāng)前P的本地隊(duì)列隊(duì)列里的所有G后,P也不會(huì)就這么在那躺尸啥都不干,它會(huì)先嘗試從全局隊(duì)列隊(duì)列尋找G來(lái)執(zhí)行,如果全局隊(duì)列為空,它會(huì)隨機(jī)挑選另外一個(gè)P,從它的隊(duì)列里中拿走一半的G到自己的隊(duì)列中執(zhí)行。

如果一切正常,調(diào)度器會(huì)以上述的那種方式順暢地運(yùn)行,但這個(gè)世界沒(méi)這么美好,總有意外發(fā)生,以下分析goroutine在兩種例外情況下的行為。

Go runtime會(huì)在下面的goroutine被阻塞的情況下運(yùn)行另外一個(gè)goroutine:

用戶態(tài)阻塞/喚醒

當(dāng)goroutine因?yàn)閏hannel操作或者network I/O而阻塞時(shí)(實(shí)際上golang已經(jīng)用netpoller實(shí)現(xiàn)了goroutine網(wǎng)絡(luò)I/O阻塞不會(huì)導(dǎo)致M被阻塞,僅阻塞G,這里僅僅是舉個(gè)栗子),對(duì)應(yīng)的G會(huì)被放置到某個(gè)wait隊(duì)列(如channel的waitq),該G的狀態(tài)由_Gruning變?yōu)開(kāi)Gwaitting,而M會(huì)跳過(guò)該G嘗試獲取并執(zhí)行下一個(gè)G,如果此時(shí)沒(méi)有可運(yùn)行的G供M運(yùn)行,那么M將解綁P,并進(jìn)入sleep狀態(tài);當(dāng)阻塞的G被另一端的G2喚醒時(shí)(比如channel的可讀/寫(xiě)通知),G被標(biāo)記為,嘗試加入G2所在P的runnext(runnext是線程下一個(gè)需要執(zhí)行的 Goroutine。), 然后再是P的本地隊(duì)列和全局隊(duì)列。

系統(tǒng)調(diào)用阻塞

當(dāng)M執(zhí)行某一個(gè)G時(shí)候如果發(fā)生了阻塞操作,M會(huì)阻塞,如果當(dāng)前有一些G在執(zhí)行,調(diào)度器會(huì)把這個(gè)線程M從P中摘除,然后再創(chuàng)建一個(gè)新的操作系統(tǒng)的線程(如果有空閑的線程可用就復(fù)用空閑線程)來(lái)服務(wù)于這個(gè)P。當(dāng)M系統(tǒng)調(diào)用結(jié)束時(shí)候,這個(gè)G會(huì)嘗試獲取一個(gè)空閑的P執(zhí)行,并放入到這個(gè)P的本地隊(duì)列。如果獲取不到P,那么這個(gè)線程M變成休眠狀態(tài), 加入到空閑線程中,然后這個(gè)G會(huì)被放入全局隊(duì)列中。

隊(duì)列輪轉(zhuǎn)

可見(jiàn)每個(gè)P維護(hù)著一個(gè)包含G的隊(duì)列,不考慮G進(jìn)入系統(tǒng)調(diào)用或IO操作的情況下,P周期性的將G調(diào)度到M中執(zhí)行,執(zhí)行一小段時(shí)間,將上下文保存下來(lái),然后將G放到隊(duì)列尾部,然后從隊(duì)列中重新取出一個(gè)G進(jìn)行調(diào)度。

除了每個(gè)P維護(hù)的G隊(duì)列以外,還有一個(gè)全局的隊(duì)列,每個(gè)P會(huì)周期性地查看全局隊(duì)列中是否有G待運(yùn)行并將其調(diào)度到M中執(zhí)行,全局隊(duì)列中G的來(lái)源,主要有從系統(tǒng)調(diào)用中恢復(fù)的G。之所以P會(huì)周期性地查看全局隊(duì)列,也是為了防止全局隊(duì)列中的G被餓死。

除了每個(gè)P維護(hù)的G隊(duì)列以外,還有一個(gè)全局的隊(duì)列,每個(gè)P會(huì)周期性地查看全局隊(duì)列中是否有G待運(yùn)行并將其調(diào)度到M中執(zhí)行,全局隊(duì)列中G的來(lái)源,主要有從系統(tǒng)調(diào)用中恢復(fù)的G。之所以P會(huì)周期性地查看全局隊(duì)列,也是為了防止全局隊(duì)列中的G被餓死。

M0

M0是啟動(dòng)程序后的編號(hào)為0的主線程,這個(gè)M對(duì)應(yīng)的實(shí)例會(huì)在全局變量rutime.m0中,不需要在heap上分配,M0負(fù)責(zé)執(zhí)行初始化操作和啟動(dòng)第一個(gè)G,在之后M0就和其他的M一樣了

G0

G0是每次啟動(dòng)一個(gè)M都會(huì)第一個(gè)創(chuàng)建的goroutine,G0僅用于負(fù)責(zé)調(diào)度G,G0不指向任何可執(zhí)行的函數(shù),每個(gè)M都會(huì)有一個(gè)自己的G0,在調(diào)度或系統(tǒng)調(diào)用時(shí)會(huì)使用G0的??臻g,全局變量的G0是M0的G0

一個(gè)G由于調(diào)度被中斷,此后如何恢復(fù)?

中斷的時(shí)候?qū)⒓拇嫫骼锏臈P畔ⅲ4娴阶约旱腉對(duì)象里面。當(dāng)再次輪到自己執(zhí)行時(shí),將自己保存的棧信息復(fù)制到寄存器里面,這樣就接著上次之后運(yùn)行了。

我這里只是根據(jù)自己的理解進(jìn)行了簡(jiǎn)單的介紹,想要詳細(xì)了解有關(guān)GMP的底層原理可以去看Go調(diào)度器 G-P-M 模型的設(shè)計(jì)者的文檔或直接看源碼

參考: ()

()

六星教育:Python和go語(yǔ)言都很火,我要怎么選?

python和go語(yǔ)言有區(qū)別:1、Python語(yǔ)法使用縮進(jìn)來(lái)指示代碼塊;Go語(yǔ)法基于打開(kāi)和關(guān)閉括號(hào);2、Python是基于面向?qū)ο缶幊痰亩喾妒秸Z(yǔ)言;Go是基于并發(fā)編程范式的過(guò)程編程語(yǔ)言。3、Python是動(dòng)態(tài)類型語(yǔ)言,Go是靜態(tài)類型語(yǔ)言。

Go語(yǔ)言(又稱 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 開(kāi)發(fā)的一種靜態(tài)強(qiáng)類型、編譯型語(yǔ)言。Go 語(yǔ)言語(yǔ)法與 C 相近,但功能上有:內(nèi)存安全,GC(垃圾回收),結(jié)構(gòu)形態(tài)以及 CSP-style 并發(fā)計(jì)算。

python是一種廣泛使用的具有動(dòng)態(tài)語(yǔ)義的解釋型,面向?qū)ο蟮母呒?jí)編程語(yǔ)言。

Python是一種面向?qū)ο蟮母呒?jí)編程語(yǔ)言,具有集成的動(dòng)態(tài)語(yǔ)義,主要用于Web和應(yīng)用程序開(kāi)發(fā)。它在快速應(yīng)用程序開(kāi)發(fā)領(lǐng)域極具吸引力,因?yàn)樗峁﹦?dòng)態(tài)類型和動(dòng)態(tài)綁定選項(xiàng)。

Python是一種解釋型語(yǔ)言,這意味著用Python編寫(xiě)的程序不需要事先編譯就可以運(yùn)行,從而可以輕松地測(cè)試小段代碼并使用Python編寫(xiě)的代碼更容易在平臺(tái)之間移動(dòng)。

python和go語(yǔ)言的區(qū)別:

1、語(yǔ)法

Python的語(yǔ)法使用縮進(jìn)來(lái)指示代碼塊。Go的語(yǔ)法基于打開(kāi)和關(guān)閉括號(hào)。

2、范例

Python是一種基于面向?qū)ο缶幊痰亩喾妒?,命令式和函?shù)式編程語(yǔ)言。它堅(jiān)持這樣一種觀點(diǎn),即如果一種語(yǔ)言在某些情境中表現(xiàn)出某種特定的方式,理想情況下它應(yīng)該在所有情境中都有相似的作用。但是,它又不是純粹的OOP語(yǔ)言,它不支持強(qiáng)封裝,這是OOP的主要原則之一。

Go是一種基于并發(fā)編程范式的過(guò)程編程語(yǔ)言,它與C具有表面相似性。實(shí)際上,Go更像是C的更新版本。

3、并發(fā)

Python沒(méi)有提供內(nèi)置的并發(fā)機(jī)制,而Go有內(nèi)置的并發(fā)機(jī)制。

4、類型化

Python是動(dòng)態(tài)類型語(yǔ)言,而Go是一種靜態(tài)類型語(yǔ)言,它實(shí)際上有助于在編譯時(shí)捕獲錯(cuò)誤,這可以進(jìn)一步減少生產(chǎn)后期的嚴(yán)重錯(cuò)誤。

5、安全性

Python是一種強(qiáng)類型語(yǔ)言,它是經(jīng)過(guò)編譯的,因此增加了一層安全性。Go具有分配給每個(gè)變量的類型,因此,它提供了安全性。但是,如果發(fā)生任何錯(cuò)誤,用戶需要自己運(yùn)行整個(gè)代碼。

6、管理內(nèi)存

Go允許程序員在很大程度上管理內(nèi)存。而,Python中的內(nèi)存管理完全自動(dòng)化并由Python VM管理;它不允許程序員對(duì)內(nèi)存管理負(fù)責(zé)。

7、庫(kù)

與Go相比,Python提供的庫(kù)數(shù)量要大得多。然而,Go仍然是新的,并且還沒(méi)有取得很大進(jìn)展。

8、速度:

Go的速度遠(yuǎn)遠(yuǎn)超過(guò)Python。

Python與Golang對(duì)比:

1、特點(diǎn):

Golang

①靜態(tài)強(qiáng)類型、編譯型、并發(fā)型

靜態(tài)類型語(yǔ)言,但是有動(dòng)態(tài)語(yǔ)言的感覺(jué)。(靜態(tài)類型的語(yǔ)言就是可以在編譯的時(shí)候檢查出來(lái)隱藏的大多數(shù)問(wèn)題,動(dòng)態(tài)語(yǔ)言的感覺(jué)就是有很多的包可以使用,寫(xiě)起來(lái)的效率很高)

可直接編譯成機(jī)器碼,不依賴其他庫(kù),glibc的版本有一定要求,部署就是扔一個(gè)文件上去就完成了。

語(yǔ)言層面支持并發(fā),這個(gè)就是Go最大的特色,天生的支持并發(fā)。Go就是基因里面支持的并發(fā),可以充分地利用多核,很容易地使用并發(fā)。

②垃圾回收機(jī)制

內(nèi)置runtime,支持垃圾回收,這屬于動(dòng)態(tài)語(yǔ)言的特性之一吧,雖然目前來(lái)說(shuō)GC(內(nèi)存垃圾回收機(jī)制)不算完美,但是足以應(yīng)付我們所能遇到的大多數(shù)情況,特別是Go1.1之后的GC。

③支持面向?qū)ο缶幊?/p>

有接口類型和實(shí)現(xiàn)類型的概念,但是用嵌入替代了繼承。

④豐富的標(biāo)準(zhǔn)庫(kù)

Go目前已經(jīng)內(nèi)置了大量的庫(kù),特別是網(wǎng)絡(luò)庫(kù)非常強(qiáng)大。

⑤內(nèi)嵌C支持

Go里面也可以直接包含C代碼,利用現(xiàn)有的豐富的C庫(kù)

Python

①解釋型語(yǔ)言

程序不需要在運(yùn)行前編譯,在運(yùn)行程序的時(shí)候才翻譯,專門(mén)的解釋器負(fù)責(zé)在每個(gè)語(yǔ)句執(zhí)行的時(shí)候解釋程序代碼。這樣解釋型語(yǔ)言每執(zhí)行一次就要翻譯一次,效率比較低。

②動(dòng)態(tài)數(shù)據(jù)類型 

支持重載運(yùn)算符,也支持泛型設(shè)計(jì)。(運(yùn)算符重載,就是對(duì)已有的運(yùn)算符重新進(jìn)行定義,賦予其另一種功能,以適應(yīng)不同的數(shù)據(jù)類型。泛型設(shè)計(jì)就是定義的時(shí)候不需要指定類型,在客戶端使用的時(shí)候再去指定類型)

③完全面向?qū)ο蟮恼Z(yǔ)言

函數(shù),模塊,數(shù)字,字符串都是對(duì)象,在Python中,一切接對(duì)象

完全支持繼承,重載,多重繼承 

④擁有強(qiáng)大的標(biāo)準(zhǔn)庫(kù)

Python語(yǔ)言的核心只包含數(shù)字,字符串,列表,元祖,字典,集合,文件等常見(jiàn)類型和函數(shù),而由Python標(biāo)準(zhǔn)庫(kù)提供了系統(tǒng)管理,網(wǎng)絡(luò)通信,文本處理,數(shù)據(jù)庫(kù)接口,圖形系統(tǒng),XML處理等額外的功能。

⑤社區(qū)提供了大量第三方庫(kù)

Python 社區(qū)提供了大量的第三方模塊,使用方式與標(biāo)準(zhǔn)庫(kù)類似。它們的功能覆蓋 科學(xué)計(jì)算、人工智能、機(jī)器學(xué)習(xí)、Web 開(kāi)發(fā)、數(shù)據(jù)庫(kù)接口、圖形系統(tǒng) 多個(gè)領(lǐng)域。

2、應(yīng)用

Python

①網(wǎng)絡(luò)編程

web應(yīng)用,網(wǎng)絡(luò)爬蟲(chóng)

②數(shù)據(jù)分析和機(jī)器學(xué)習(xí)

③自動(dòng)化測(cè)試

④自動(dòng)化運(yùn)維

Golang

①服務(wù)器編程

處理日志、數(shù)據(jù)打包、虛擬機(jī)處理、文件系統(tǒng)等。

②分布式系統(tǒng),數(shù)據(jù)庫(kù)代理器等

③網(wǎng)絡(luò)編程

這一塊目前應(yīng)用最廣,包括Web應(yīng)用、API應(yīng)用、下載應(yīng)用。

④內(nèi)存數(shù)據(jù)庫(kù)

如google開(kāi)發(fā)的groupcache,couchbase的部分組件。

⑥云平臺(tái)

Go語(yǔ)言和Python學(xué)哪個(gè)好?

Python 可以很好地集成到企業(yè)級(jí)應(yīng)用中,可用于機(jī)器語(yǔ)言和 AI 應(yīng)用。Go 語(yǔ)言的特點(diǎn)表明它具備輕量級(jí)線程實(shí)現(xiàn)(Goroutine)、智能標(biāo)準(zhǔn)庫(kù)、強(qiáng)大的內(nèi)置安全性,且可使用最簡(jiǎn)語(yǔ)法進(jìn)行編程。Go 在大部分案例中領(lǐng)先,被認(rèn)為是 Python 的有效替代方案。開(kāi)發(fā)者在選擇編程語(yǔ)言時(shí),應(yīng)考慮開(kāi)發(fā)項(xiàng)目的性質(zhì)和規(guī)模,以及所需的技能組合。

放下個(gè)人偏見(jiàn)和喜好,從優(yōu)點(diǎn)和功能的角度來(lái)評(píng)價(jià)兩種語(yǔ)言。不管選擇了哪種語(yǔ)言,Go 和 Python 都在持續(xù)演進(jìn)。盡管在大多數(shù)情況下 Golang 可能是更好的選擇,但Python語(yǔ)言也是不斷更新迭代的。以上就是本次分享的全部?jī)?nèi)容,如果你也想學(xué)習(xí)一門(mén)編程語(yǔ)言,可以考慮下 六星教育 ,這里的課程體系,師資團(tuán)隊(duì)以及售后服務(wù),一定不會(huì)讓你失望!

如何看待go語(yǔ)言泛型的最新設(shè)計(jì)?

Go 由于不支持泛型而臭名昭著,但最近,泛型已接近成為現(xiàn)實(shí)。Go 團(tuán)隊(duì)實(shí)施了一個(gè)看起來(lái)比較穩(wěn)定的設(shè)計(jì)草案,并且正以源到源翻譯器原型的形式獲得關(guān)注。本文講述的是泛型的最新設(shè)計(jì),以及如何自己嘗試泛型。

例子

FIFO Stack

假設(shè)你要?jiǎng)?chuàng)建一個(gè)先進(jìn)先出堆棧。沒(méi)有泛型,你可能會(huì)這樣實(shí)現(xiàn):

type?Stack?[]interface{}func?(s?Stack)?Peek()?interface{}?{

return?s[len(s)-1]

}

func?(s?*Stack)?Pop()?{

*s?=?(*s)[:

len(*s)-1]

}

func?(s?*Stack)?Push(value?interface{})?{

*s?=?

append(*s,?value)

}

但是,這里存在一個(gè)問(wèn)題:每當(dāng)你 Peek 項(xiàng)時(shí),都必須使用類型斷言將其從 interface{} 轉(zhuǎn)換為你需要的類型。如果你的堆棧是 *MyObject 的堆棧,則意味著很多 s.Peek().(*MyObject)這樣的代碼。這不僅讓人眼花繚亂,而且還可能引發(fā)錯(cuò)誤。比如忘記 * 怎么辦?或者如果您輸入錯(cuò)誤的類型怎么辦?s.Push(MyObject{})` 可以順利編譯,而且你可能不會(huì)發(fā)現(xiàn)到自己的錯(cuò)誤,直到它影響到你的整個(gè)服務(wù)為止。

通常,使用 interface{} 是相對(duì)危險(xiǎn)的。使用更多受限制的類型總是更安全,因?yàn)榭梢栽诰幾g時(shí)而不是運(yùn)行時(shí)發(fā)現(xiàn)問(wèn)題。

泛型通過(guò)允許類型具有類型參數(shù)來(lái)解決此問(wèn)題:

type?Stack(type?T)?[]Tfunc?(s?Stack(T))?Peek()?T?{

return?s[len(s)-1]

}

func?(s?*Stack(T))?Pop()?{

*s?=?(*s)[:

len(*s)-1]

}

func?(s?*Stack(T))?Push(value?T)?{

*s?=?

append(*s,?value)

}

這會(huì)向 Stack 添加一個(gè)類型參數(shù),從而完全不需要 interface{}?,F(xiàn)在,當(dāng)你使用 Peek() 時(shí),返回的值已經(jīng)是原始類型,并且沒(méi)有機(jī)會(huì)返回錯(cuò)誤的值類型。這種方式更安全,更容易使用。(譯注:就是看起來(lái)更丑陋,^-^)

此外,泛型代碼通常更易于編譯器優(yōu)化,從而獲得更好的性能(以二進(jìn)制大小為代價(jià))。如果我們對(duì)上面的非泛型代碼和泛型代碼進(jìn)行基準(zhǔn)測(cè)試,我們可以看到區(qū)別:

type?MyObject?struct?{

X?

int

}

var?sink?MyObjectfunc?BenchmarkGo1(b?*testing.B)?{

for?i?:=?0;?i??b.N;?i++?{

var?s?Stack

s.Push(MyObject{})

s.Push(MyObject{})

s.Pop()

sink?=?s.Peek().(MyObject)

}

}

func?BenchmarkGo2(b?*testing.B)?{

for?i?:=?0;?i??b.N;?i++?{

var?s?Stack(MyObject)

s.Push(MyObject{})

s.Push(MyObject{})

s.Pop()

sink?=?s.Peek()

}

}

結(jié)果:

BenchmarkGo1BenchmarkGo1-16?????12837528?????????87.0?ns/op???????48?B/op????????2?allocs/opBenchmarkGo2BenchmarkGo2-16?????28406479?????????41.9?ns/op???????24?B/op????????2?allocs/op

在這種情況下,我們分配更少的內(nèi)存,同時(shí)泛型的速度是非泛型的兩倍。

合約(Contracts)

上面的堆棧示例適用于任何類型。但是,在許多情況下,你需要編寫(xiě)僅適用于具有某些特征的類型的代碼。例如,你可能希望堆棧要求類型實(shí)現(xiàn) String() 函數(shù)

GO語(yǔ)言商業(yè)案例(十八):stream

切換到新語(yǔ)言始終是一大步,尤其是當(dāng)您的團(tuán)隊(duì)成員只有一個(gè)時(shí)有該語(yǔ)言的先前經(jīng)驗(yàn)。現(xiàn)在,Stream 的主要編程語(yǔ)言從 Python 切換到了 Go。這篇文章將解釋stream決定放棄 Python 并轉(zhuǎn)向 Go 的一些原因。

Go 非???。性能類似于 Java 或 C++。對(duì)于用例,Go 通常比 Python 快 40 倍。

對(duì)于許多應(yīng)用程序來(lái)說(shuō),編程語(yǔ)言只是應(yīng)用程序和數(shù)據(jù)庫(kù)之間的粘合劑。語(yǔ)言本身的性能通常并不重要。然而,Stream 是一個(gè)API 提供商,為 700 家公司和超過(guò) 5 億最終用戶提供提要和聊天平臺(tái)。多年來(lái),我們一直在優(yōu)化 Cassandra、PostgreSQL、Redis 等,但最終,您會(huì)達(dá)到所使用語(yǔ)言的極限。Python 是一門(mén)很棒的語(yǔ)言,但對(duì)于序列化/反序列化、排名和聚合等用例,它的性能相當(dāng)緩慢。我們經(jīng)常遇到性能問(wèn)題,Cassandra 需要 1 毫秒來(lái)檢索數(shù)據(jù),而 Python 會(huì)花費(fèi)接下來(lái)的 10 毫秒將其轉(zhuǎn)換為對(duì)象。

看看我如何開(kāi)始 Go 教程中的一小段 Go 代碼。(這是一個(gè)很棒的教程,也是學(xué)習(xí) Go 的一個(gè)很好的起點(diǎn)。)

如果您是 Go 新手,那么在閱讀那個(gè)小代碼片段時(shí)不會(huì)有太多讓您感到驚訝的事情。它展示了多個(gè)賦值、數(shù)據(jù)結(jié)構(gòu)、指針、格式和一個(gè)內(nèi)置的 HTTP 庫(kù)。當(dāng)我第一次開(kāi)始編程時(shí),我一直喜歡使用 Python 更高級(jí)的功能。Python 允許您在編寫(xiě)代碼時(shí)獲得相當(dāng)?shù)膭?chuàng)意。例如,您可以:

這些功能玩起來(lái)很有趣,但是,正如大多數(shù)程序員會(huì)同意的那樣,在閱讀別人的作品時(shí),它們通常會(huì)使代碼更難理解。Go 迫使你堅(jiān)持基礎(chǔ)。這使得閱讀任何人的代碼并立即了解發(fā)生了什么變得非常容易。 注意:當(dāng)然,它實(shí)際上有多“容易”取決于您的用例。如果你想創(chuàng)建一個(gè)基本的 CRUD API,我仍然推薦 Django + DRF或 Rails。

作為一門(mén)語(yǔ)言,Go 試圖讓事情變得簡(jiǎn)單。它沒(méi)有引入許多新概念。重點(diǎn)是創(chuàng)建一種非??焖偾乙子谑褂玫暮?jiǎn)單語(yǔ)言。它唯一具有創(chuàng)新性的領(lǐng)域是 goroutine 和通道。(100% 正確CSP的概念始于 1977 年,所以這項(xiàng)創(chuàng)新更多是對(duì)舊思想的一種新方法。)Goroutines 是 Go 的輕量級(jí)線程方法,通道是 goroutines 之間通信的首選方式。Goroutines 的創(chuàng)建非常便宜,并且只需要幾 KB 的額外內(nèi)存。因?yàn)?Goroutine 非常輕量,所以有可能同時(shí)運(yùn)行數(shù)百甚至數(shù)千個(gè)。您可以使用通道在 goroutine 之間進(jìn)行通信。Go 運(yùn)行時(shí)處理所有復(fù)雜性。goroutines 和基于通道的并發(fā)方法使得使用所有可用的 CPU 內(nèi)核和處理并發(fā) IO 變得非常容易——所有這些都不會(huì)使開(kāi)發(fā)復(fù)雜化。與 Python/Java 相比,在 goroutine 上運(yùn)行函數(shù)需要最少的樣板代碼。您只需在函數(shù)調(diào)用前加上關(guān)鍵字“go”:

Go 的并發(fā)方法很容易使用。與 Node 相比,這是一種有趣的方法,開(kāi)發(fā)人員必須密切關(guān)注異步代碼的處理方式。Go 中并發(fā)的另一個(gè)重要方面是競(jìng)爭(zhēng)檢測(cè)器。這樣可以很容易地確定異步代碼中是否存在任何競(jìng)爭(zhēng)條件。

我們目前用 Go 編寫(xiě)的最大的微服務(wù)編譯需要 4 秒。與以編譯速度慢而聞名的 Java 和 C++ 等語(yǔ)言相比,Go 的快速編譯時(shí)間是一項(xiàng)重大的生產(chǎn)力勝利。我喜歡在程序編譯的時(shí)候摸魚(yú),但在我還記得代碼應(yīng)該做什么的同時(shí)完成事情會(huì)更好。

首先,讓我們從顯而易見(jiàn)的開(kāi)始:與 C++ 和 Java 等舊語(yǔ)言相比,Go 開(kāi)發(fā)人員的數(shù)量并不多。根據(jù)StackOverflow的數(shù)據(jù), 38% 的開(kāi)發(fā)人員知道 Java, 19.3% 的人知道 C++,只有 4.6% 的人知道 Go。GitHub 數(shù)據(jù)顯示了類似的趨勢(shì):Go 比 Erlang、Scala 和 Elixir 等語(yǔ)言使用更廣泛,但不如 Java 和 C++ 流行。幸運(yùn)的是,Go 是一種非常簡(jiǎn)單易學(xué)的語(yǔ)言。它提供了您需要的基本功能,僅此而已。它引入的新概念是“延遲”聲明和內(nèi)置的并發(fā)管理與“goroutines”和通道。(對(duì)于純粹主義者來(lái)說(shuō):Go 并不是第一種實(shí)現(xiàn)這些概念的語(yǔ)言,只是第一種使它們流行起來(lái)的語(yǔ)言。)任何加入團(tuán)隊(duì)的 Python、Elixir、C++、Scala 或 Java 開(kāi)發(fā)人員都可以在一個(gè)月內(nèi)在 Go 上發(fā)揮作用,因?yàn)樗暮?jiǎn)單性。與許多其他語(yǔ)言相比,我們發(fā)現(xiàn)組建 Go 開(kāi)發(fā)人員團(tuán)隊(duì)更容易。如果您在博爾德和阿姆斯特丹等競(jìng)爭(zhēng)激烈的生態(tài)系統(tǒng)中招聘人員,這是一項(xiàng)重要的優(yōu)勢(shì)。

對(duì)于我們這樣規(guī)模的團(tuán)隊(duì)(約 20 人)來(lái)說(shuō),生態(tài)系統(tǒng)很重要。如果您必須重新發(fā)明每一個(gè)小功能,您根本無(wú)法為您的客戶創(chuàng)造價(jià)值。Go 對(duì)我們使用的工具有很好的支持。實(shí)體庫(kù)已經(jīng)可用于 Redis、RabbitMQ、PostgreSQL、模板解析、任務(wù)調(diào)度、表達(dá)式解析和 RocksDB。與 Rust 或 Elixir 等其他較新的語(yǔ)言相比,Go 的生態(tài)系統(tǒng)是一個(gè)重大勝利。它當(dāng)然不如 Java、Python 或 Node 之類的語(yǔ)言好,但它很可靠,而且對(duì)于許多基本需求,你會(huì)發(fā)現(xiàn)已經(jīng)有高質(zhì)量的包可用。

Gofmt 是一個(gè)很棒的命令行實(shí)用程序,內(nèi)置在 Go 編譯器中,用于格式化代碼。就功能而言,它與 Python 的 autopep8 非常相似。我們大多數(shù)人并不真正喜歡爭(zhēng)論制表符與空格。格式的一致性很重要,但實(shí)際的格式標(biāo)準(zhǔn)并不那么重要。Gofmt 通過(guò)使用一種正式的方式來(lái)格式化您的代碼來(lái)避免所有這些討論。

Go 對(duì)協(xié)議緩沖區(qū)和 gRPC 具有一流的支持。這兩個(gè)工具非常適合構(gòu)建需要通過(guò) RPC 通信的微服務(wù)。您只需要編寫(xiě)一個(gè)清單,在其中定義可以進(jìn)行的 RPC 調(diào)用以及它們采用的參數(shù)。然后從這個(gè)清單中自動(dòng)生成服務(wù)器和客戶端代碼。生成的代碼既快速又具有非常小的網(wǎng)絡(luò)占用空間并且易于使用。從同一個(gè)清單中,您甚至可以為許多不同的語(yǔ)言生成客戶端代碼,例如 C++、Java、Python 和 Ruby。因此,內(nèi)部流量不再有模棱兩可的 REST 端點(diǎn),您每次都必須編寫(xiě)幾乎相同的客戶端和服務(wù)器代碼。.

Go 沒(méi)有像 Rails 用于 Ruby、Django 用于 Python 或 Laravel 用于 PHP 那樣的單一主導(dǎo)框架。這是 Go 社區(qū)內(nèi)激烈爭(zhēng)論的話題,因?yàn)樵S多人主張你不應(yīng)該一開(kāi)始就使用框架。我完全同意這對(duì)于某些用例是正確的。但是,如果有人想構(gòu)建一個(gè)簡(jiǎn)單的 CRUD API,他們將更容易使用 Django/DJRF、Rails Laravel 或Phoenix。對(duì)于 Stream 的用例,我們更喜歡不使用框架。然而,對(duì)于許多希望提供簡(jiǎn)單 CRUD API 的新項(xiàng)目來(lái)說(shuō),缺乏主導(dǎo)框架將是一個(gè)嚴(yán)重的劣勢(shì)。

Go 通過(guò)簡(jiǎn)單地從函數(shù)返回錯(cuò)誤并期望調(diào)用代碼來(lái)處理錯(cuò)誤(或?qū)⑵浞祷氐秸{(diào)用堆棧)來(lái)處理錯(cuò)誤。雖然這種方法有效,但很容易失去問(wèn)題的范圍,以確保您可以向用戶提供有意義的錯(cuò)誤。錯(cuò)誤包通過(guò)允許您向錯(cuò)誤添加上下文和堆棧跟蹤來(lái)解決此問(wèn)題。另一個(gè)問(wèn)題是很容易忘記處理錯(cuò)誤。像 errcheck 和 megacheck 這樣的靜態(tài)分析工具可以方便地避免犯這些錯(cuò)誤。雖然這些變通辦法效果很好,但感覺(jué)不太對(duì)勁。您希望該語(yǔ)言支持正確的錯(cuò)誤處理。

Go 的包管理絕不是完美的。默認(rèn)情況下,它無(wú)法指定特定版本的依賴項(xiàng),也無(wú)法創(chuàng)建可重現(xiàn)的構(gòu)建。Python、Node 和 Ruby 都有更好的包管理系統(tǒng)。但是,使用正確的工具,Go 的包管理工作得很好。您可以使用Dep來(lái)管理您的依賴項(xiàng),以允許指定和固定版本。除此之外,我們還貢獻(xiàn)了一個(gè)名為的開(kāi)源工具VirtualGo,它可以更輕松地處理用 Go 編寫(xiě)的多個(gè)項(xiàng)目。

我們進(jìn)行的一個(gè)有趣的實(shí)驗(yàn)是在 Python 中使用我們的排名提要功能并在 Go 中重寫(xiě)它??纯催@個(gè)排名方法的例子:

Python 和 Go 代碼都需要執(zhí)行以下操作來(lái)支持這種排名方法:

開(kāi)發(fā) Python 版本的排名代碼大約花了 3 天時(shí)間。這包括編寫(xiě)代碼、單元測(cè)試和文檔。接下來(lái),我們花了大約 2 周的時(shí)間優(yōu)化代碼。其中一項(xiàng)優(yōu)化是將分?jǐn)?shù)表達(dá)式 (simple_gauss(time)*popularity) 轉(zhuǎn)換為抽象語(yǔ)法樹(shù). 我們還實(shí)現(xiàn)了緩存邏輯,可以在未來(lái)的特定時(shí)間預(yù)先計(jì)算分?jǐn)?shù)。相比之下,開(kāi)發(fā)此代碼的 Go 版本大約需要 4 天時(shí)間。性能不需要任何進(jìn)一步的優(yōu)化。因此,雖然 Python 的最初開(kāi)發(fā)速度更快,但基于 Go 的版本最終需要我們團(tuán)隊(duì)的工作量大大減少。另外一個(gè)好處是,Go 代碼的執(zhí)行速度比我們高度優(yōu)化的 Python 代碼快大約 40 倍。現(xiàn)在,這只是我們通過(guò)切換到 Go 體驗(yàn)到的性能提升的一個(gè)示例。

與 Python 相比,我們系統(tǒng)的其他一些組件在 Go 中構(gòu)建所需的時(shí)間要多得多。作為一個(gè)總體趨勢(shì),我們看到 開(kāi)發(fā) Go 代碼需要更多的努力。但是,我們花更少的時(shí)間 優(yōu)化 代碼以提高性能。

我們?cè)u(píng)估的另一種語(yǔ)言是Elixir.。Elixir 建立在 Erlang 虛擬機(jī)之上。這是一種迷人的語(yǔ)言,我們之所以考慮它,是因?yàn)槲覀兊囊幻麍F(tuán)隊(duì)成員在 Erlang 方面擁有豐富的經(jīng)驗(yàn)。對(duì)于我們的用例,我們注意到 Go 的原始性能要好得多。Go 和 Elixir 都可以很好地服務(wù)數(shù)千個(gè)并發(fā)請(qǐng)求。但是,如果您查看單個(gè)請(qǐng)求的性能,Go 對(duì)于我們的用例來(lái)說(shuō)要快得多。我們選擇 Go 而不是 Elixir 的另一個(gè)原因是生態(tài)系統(tǒng)。對(duì)于我們需要的組件,Go 有更成熟的庫(kù),而在許多情況下,Elixir 庫(kù)還沒(méi)有準(zhǔn)備好用于生產(chǎn)環(huán)境。培訓(xùn)/尋找開(kāi)發(fā)人員使用 Elixir 也更加困難。這些原因使天平向 Go 傾斜。Elixir 的 Phoenix 框架看起來(lái)很棒,絕對(duì)值得一看。

Go 是一種非常高性能的語(yǔ)言,對(duì)并發(fā)有很好的支持。它幾乎與 C++ 和 Java 等語(yǔ)言一樣快。雖然與 Python 或 Ruby 相比,使用 Go 構(gòu)建東西確實(shí)需要更多時(shí)間,但您將節(jié)省大量用于優(yōu)化代碼的時(shí)間。我們?cè)赟tream有一個(gè)小型開(kāi)發(fā)團(tuán)隊(duì),為超過(guò) 5 億最終用戶提供動(dòng)力和聊天。Go 結(jié)合了 強(qiáng)大的生態(tài)系統(tǒng) 、新開(kāi)發(fā)人員的 輕松入門(mén)、快速的性能 、對(duì)并發(fā)的 可靠支持和高效的編程環(huán)境 ,使其成為一個(gè)不錯(cuò)的選擇。Stream 仍然在我們的儀表板、站點(diǎn)和機(jī)器學(xué)習(xí)中利用 Python 來(lái)提供個(gè)性化的訂閱源. 我們不會(huì)很快與 Python 說(shuō)再見(jiàn),但今后所有性能密集型代碼都將使用 Go 編寫(xiě)。我們新的聊天 API也完全用 Go 編寫(xiě)。

分享題目:go語(yǔ)言量化分析,golang量化
文章起源:http://vcdvsql.cn/article8/hsegip.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開(kāi)發(fā)、自適應(yīng)網(wǎng)站、面包屑導(dǎo)航定制開(kāi)發(fā)網(wǎng)站內(nèi)鏈、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(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í)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作