<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          也許你從來(lái)沒用過(guò)的利器:GODEBUG

          共 5434字,需瀏覽 11分鐘

           ·

          2021-05-20 22:38

          點(diǎn)擊上方“Go編程時(shí)光”,選擇“加為星標(biāo)

          第一時(shí)間關(guān)注Go技術(shù)干貨!



          作者:Vincent Blanchon 譯者:lxbwolf 校對(duì):polaris1119
          本文由 GCTT[9] 原創(chuàng)編譯,轉(zhuǎn)載自:Go語(yǔ)言中文
          網(wǎng) 公眾號(hào),轉(zhuǎn)載請(qǐng)務(wù)必聯(lián)系其授權(quán)。

          Go 協(xié)程是輕量的,在很多場(chǎng)景能提升你的程序性能。不幸的是,如果使用不當(dāng),也可能降低你程序的性能,因?yàn)?Go 協(xié)程的上線文切換也需要消耗一定的資源。

          項(xiàng)目上下文和測(cè)試基準(zhǔn)

          在我的公司—PropertyFinder[1]—一個(gè)阿聯(lián)酋的實(shí)業(yè)地產(chǎn)門戶網(wǎng)站—我的團(tuán)隊(duì)維護(hù)一個(gè)微服務(wù),用于為我們的客戶和地產(chǎn)經(jīng)紀(jì)人尋找潛在的機(jī)會(huì)。我們來(lái)通過(guò)一個(gè)算法 demo 概覽下這個(gè) Go 微服務(wù):

          Variables:
          lead struct
          Start:
          // a profile of this lead is made based on its interest
          MakeProfile(lead)
          // we get all listing that are around of this kind of profile
          listings <- GetListings()
          For each chunk of 1000 in listings
              Start goroutine
                  For each listing in chunk
                      score <- CalculateMatching(listing, lead)
                      Add the score to the bulk object
                  Bulk insert the 100 scores of the chunk
          Stop

          因?yàn)檫@里的 listings 可能達(dá)到 10k 以上,所以我們決定每 1000 個(gè)作為一個(gè)塊,創(chuàng)建一個(gè)協(xié)程。下面是我們對(duì)計(jì)算過(guò)程跑的基準(zhǔn)測(cè)試以及 10k 個(gè)匹配結(jié)果的記錄:

          name                                     time/op
          LeadMatchingGenerationFor10000Matches-4  626ms ± 6%

          我們?cè)谟?jì)算部分再增加更多的協(xié)程。我們對(duì)代碼作如下更改:

          // we get all listing that are around of this kind of profile
          listings <- GetListings()
          For each chunk of 1000 in listings
              Start goroutine
                  For each listing in chunk
                      Start goroutine
                          score <- CalculateMatching(listing, lead)
                          Add the score to the bulk object
                  Bulk insert the 1000 scores

          我們?cè)龠\(yùn)行一次:

          name                                     time/op
          LeadMatchingGenerationFor10000Matches-4  698ms ± 4%

          比上次慢了 11%,但在預(yù)期內(nèi)。實(shí)際上,分?jǐn)?shù)計(jì)算部分是純粹的數(shù)學(xué)計(jì)算,因此 Go 調(diào)度器在新的協(xié)程里并不能利用任何的停頓時(shí)間(如系統(tǒng)調(diào)用)。

          如果你想了解更多關(guān)于 Go 調(diào)度器和協(xié)程上下文切換的知識(shí),我強(qiáng)烈推薦你閱讀 William Kennedy 寫的 Go 調(diào)度之上下文切換[2]。

          上下文切換導(dǎo)致的協(xié)程等待

          我們現(xiàn)在來(lái)分析 Go 調(diào)度器是怎么運(yùn)行協(xié)程的。我們先來(lái)看我們的第一個(gè)算法,每 1000 個(gè)作為一個(gè)塊,啟動(dòng)一個(gè)協(xié)程。打開 Go 調(diào)度器的 schedtrace 來(lái)運(yùn)行基準(zhǔn):

          GODEBUG=schedtrace=1 Go test ./... -run=^$ -bench=LeadMatchingGenerationFor10000Matches -benchtime=1ns

          參數(shù) schedtrace=1 會(huì)按毫秒打印 Go 調(diào)度器的調(diào)度事件[3]。下面是之前處理器空閑時(shí)新起的協(xié)程的相關(guān)信息的一部分追蹤信息:

          gomaxprocs=2 idleprocs=1 runqueue=0 [0 0]
          gomaxprocs=2 idleprocs=1 runqueue=0 [0 0]
          gomaxprocs=2 idleprocs=1 runqueue=0 [0 0]
          gomaxprocs=2 idleprocs=0 runqueue=1 [0 0]
          gomaxprocs=2 idleprocs=2 runqueue=0 [0 0]
          gomaxprocs=2 idleprocs=2 runqueue=0 [0 0]

          gomaxprocs 表示可用的處理器的最大數(shù),空閑線程數(shù)是 idleprocs,runqueue 表示等待被分配的協(xié)程數(shù),中括號(hào)中的數(shù)表示每個(gè)處理器中等待執(zhí)行的協(xié)程([0 0])。在 關(guān)于性能的 wiki[4] 中你可以找到更多相關(guān)信息。

          我們可以清晰地看到并沒有充分利用協(xié)程。我們也可以看到我們的處理器不是一直在工作,進(jìn)而可能會(huì)想我們是否應(yīng)該增加更多的協(xié)程來(lái)充分利用那些空閑的資源。我們以同樣的步驟來(lái)運(yùn)行第二個(gè)算法,每個(gè)分?jǐn)?shù)計(jì)算起一個(gè)協(xié)程。(Go語(yǔ)言中文網(wǎng):建議一定自己動(dòng)手試試)

          gomaxprocs=2 idleprocs=0 runqueue=645 [116 186]
          gomaxprocs=2 idleprocs=0 runqueue=514 [77 104]
          gomaxprocs=2 idleprocs=0 runqueue=382 [57 64]
          gomaxprocs=2 idleprocs=0 runqueue=124 [57 88]
          gomaxprocs=2 idleprocs=0 runqueue=0 [28 17]
          gomaxprocs=2 idleprocs=1 runqueue=0 [0 0]

          現(xiàn)在我們看到全局和本地隊(duì)列的協(xié)程棧,它使我們的處理器一直處于工作狀態(tài)。然而,我們的處理器很快又空閑了。使用追蹤器的額外功能能解釋這個(gè)現(xiàn)象:

          我們可以看到,大部分協(xié)程在數(shù)據(jù)記錄時(shí)都在等待服務(wù)返回的 response。我們的優(yōu)化應(yīng)該關(guān)注這個(gè)地方,充分利用這個(gè)等待時(shí)間。這就是我們以 1000 份文件為一束來(lái)創(chuàng)建協(xié)程進(jìn)行記錄的原因。

          我們也理解了,在計(jì)算過(guò)程中增加協(xié)程數(shù)只能增加對(duì)程序的壓力而沒有其他的收益。因?yàn)橛?jì)算過(guò)程中在當(dāng)前協(xié)程等待時(shí),系統(tǒng)并沒有足夠的時(shí)間來(lái)運(yùn)行另一個(gè)協(xié)程,所以切換到另一個(gè)協(xié)程所耗的時(shí)間僅僅是浪費(fèi)而已。

          更多關(guān)于協(xié)程

          如果你想提升創(chuàng)建協(xié)程的方式,那么 Go 的調(diào)度器和并發(fā)是很重要的內(nèi)容。Wiliam Kennedy 的 Go 的調(diào)度機(jī)制[5] 可能是最好的在線資源之一,我強(qiáng)烈推薦。


          via: https://medium.com/a-journey-with-go/go-improve-the-usage-of-your-goroutines-with-godebug-4d1f33970c33

          參考資料

          [1]

          PropertyFinder: https://www.propertyfinder.ae/

          [2]

          Go 調(diào)度之上下文切換: https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part2.html#context-switching

          [3]

          按毫秒打印 Go 調(diào)度器的調(diào)度事件: https://golang.org/doc/diagnostics.html#godebug

          [4]

          0 0]`)。在 [關(guān)于性能的 wiki: https://github.com/golang/go/wiki/Performance#scheduler-trace

          [5]

          Go 的調(diào)度機(jī)制: https://studygolang.com/articles/14264

          [6]

          Vincent Blanchon: https://medium.com/@blanchon.vincent

          [7]

          lxbwolf: https://github.com/lxbwolf

          [8]

          polaris1119: https://github.com/polaris1119

          [9]

          GCTT: https://github.com/studygolang/GCTT

          [10]

          Go 中文網(wǎng): https://studygolang.com/


             


          喜歡明哥文章的同學(xué)
          歡迎長(zhǎng)按下圖訂閱!

          ???


          瀏覽 85
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品久久午夜夜伦鲁鲁 | 午夜色色色 | 亚洲天堂在线观看网站 | 九九九成人视频 | 天天做天天干天天爱 |