<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                我們先看下go1.0源碼當時是c實現的go的調度: ~~~go static void schedule(G *gp) { ... schedlock(); if(gp != nil) { ... switch(gp->status){ case Grunnable: case Gdead: // Shouldn't have been running! runtime·throw("bad gp->status in sched"); case Grunning: gp->status = Grunnable; gput(gp); break; } gp = nextgandunlock(); gp->readyonstop = 0; gp->status = Grunning; m->curg = gp; gp->m = m; ... runtime·gogo(&gp->sched, 0); } ~~~ 這里調度的作用: * 調用`schedlock`方法來獲取全局鎖。 * 獲取全局鎖成功后,將當前 Goroutine 狀態從 Running(正在被調度) 狀態修改為 Runnable(可以被調度)狀態。 * 調用`gput`方法來保存當前 Goroutine 的運行狀態等信息,以便于后續的使用。 * 調用`nextgandunlock`方法來尋找下一個可運行 Goroutine,并且釋放全局鎖給其他調度使用。 * 獲取到下一個待運行的 Goroutine 后,將其運行狀態修改為 Running。 * 調用`runtime·gogo`方法,將剛剛所獲取到的下一個待執行的 Goroutine 運行起來,進入下一輪調度。 GM 模型的缺點: Go1.0 的 GM 模型的 Goroutine 調度器限制了用 Go 編寫的并發程序的可擴展性,尤其是高吞吐量服務器和并行計算程序。 GM調度存在的問題: * 存在單一的全局 mutex(Sched.Lock)和集中狀態管理: mutex 需要保護所有與 goroutine 相關的操作(創建、完成、重排等),導致鎖競爭嚴重。 * Goroutine 傳遞的問題: goroutine(G)交接(G.nextg):工作者線程(M's)之間會經常交接可運行的 goroutine。 而且可能會導致延遲增加和額外的開銷。每個 M 必須能夠執行任何可運行的 G,特別是剛剛創建 G 的 M。 * 每個 M 都需要做內存緩存(M.mcache): 這樣會導致資源消耗過大(每個 mcache 可以吸納到 2M 的內存緩存和其他緩存),數據局部性差。 * 頻繁的線程阻塞/解阻塞: 在存在 syscalls 的情況下,線程經常被阻塞和解阻塞。這增加了很多額外的性能開銷。 為了解決 GM 模型的以上諸多問題,在`Go1.1`時,`Dmitry Vyukov`在 GM 模型的基礎上,新增了一個 P(Processor)組件。并且實現了 Work Stealing 算法來解決一些新產生的問題。 加了 P 之后會帶來什么改變呢? * 每個 P 有自己的本地隊列,大幅度的減輕了對全局隊列的直接依賴,所帶來的效果就是鎖競爭的減少。而 GM 模型的性能開銷大頭就是鎖競爭。 * 每個 P 相對的平衡上,在 GMP 模型中也實現了`Work Stealing`算法,如果 P 的本地隊列為空,則會從全局隊列或其他 P 的本地隊列中竊取可運行的 G 來運行,減少空轉,提高了資源利用率。 為什么要有P呢? 一般來講,M 的數量都會多于 P。像在 Go 中,M 的數量默認是10000,P 的默認數量的 CPU 核數。另外由于 M 的屬性,也就是如果存在系統阻塞調用,阻塞了 M,又不夠用的情況下,M 會不斷增加。 M 不斷增加的話,如果本地隊列掛載在 M 上,那就意味著本地隊列也會隨之增加。這顯然是不合理的,因為本地隊列的管理會變得復雜,且 Work Stealing 性能會大幅度下降。 M 被系統調用阻塞后,我們是期望把他既有未執行的任務分配給其他繼續運行的,而不是一阻塞就導致全部停止。 因此使用 M 是不合理的,那么引入新的組件 P,把本地隊列關聯到 P 上,就能很好的解決這個問題。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看