go pipeline的流水線示意圖

這是對 go中關於chan應用的程序分析
文章中代碼的流水流水線示意圖。

  • 我們假設gen,sq和print操作需要的時間單位都是1:
time gen sq Print
1 out:1
2 out:2 out: 1
3 out:3 out: 4 1
4 out:4 out: 9 4
5 out:5 Out: 16 9
6 out:6 Out: 25 16
7 out:7 Out: 36 25
8 out:8 Out: 49 36
9 close(out) close(out) done<-

我們假設gen,sq和print沒一個處理步驟是相同的,那我們就可以明顯的看到一個流水線的形式,而最後我們給done這個通道推入數據,gen,sq同時關閉並退出。

  • 但是在程序的主體運行部分,sq函數通常需要更多的時間進行數據運算或其他相關的操作。我們假設sq的需要2個時間單位。
time gen sq Print
1 1
2 2 1
3 blocked going
4 3 4 1
5 blocked going waiting
6 4 9 4
7 blocked going waiting
8 5 16 9
9 close(out) close(out) done<-

由於sq需要2個時間單位來進行運算,這就導致了上游方法gen輸出通道阻塞,和下游方法print讀取通道等待。增加了時間的消耗。

  • 由於sq需要消耗2個時間單位所以我們開啓2個sq函數,同時用一個merge函數處理兩個sq函數的通道輸出。如下:
time gen Sq1 Sq2 Merge Print
1 1
2 2 1
3 3 Going 4
4 4 9 Going 1
5 5 Going 16 4 1
6 6 25 Going 9 4
7 7 Going 36 16 9
8 8 49 Going 25 16
9 close(out) close(out) close(out) close(out) done<-

在這個流水線中,用了兩個sq和一個merge作爲中間函數來進行數據處理。這樣同樣在9個時間單位內我們可以輸出4個值,同時也不會造成阻塞等行爲。

  • 既然這樣我們開3個通道會如何呢?
time gen Sq1 Sq2 Sq3 Merge Print
1 1
2 2 1
3 3 Going 4
4 4 Going 9 1
5 5 16 Going 4 1
6 6 25 Going 9 4
7 7 Going 36 16 9
8 8 Going 49 25 16
9 close(out) close(out) close(out) close(out) done<-

這時可以看出,如果通道開的多了之後總會有一部分通道沒有處於滿負荷運轉,這樣會增加我們的空間消耗。

  • 而如果sq需要華爲3個時間單位呢?
time gen Sq1 Sq2 Sq3 Merge Print
1 1
2 2 1
3 3 Going 4
4 4 Going Going 9
5 5 16 Going Going 1
6 6 Going 25 Going 4 1
7 7 Going Going 36 9 4
8 8 49 Going going 16 9
9 close(out) close(out) close(out) close(out) done<-

在這個流水線中,開三個通道,同時sq的處理時間是3個時間單位,正好每個協程都在運轉且不會造成阻塞或等待的現象。

由此可知,我們在一個pipeline中,其中的一個部分是否並行主要根據各子程序運行一次的時間來判斷,運行時間越長,越應該用多個協程處理。

我們可以用拓撲圖進行表示,在拓撲圖中,每個圓代表的是一個方法(function或goroutine)圖中的數字指每個方法在單位時間內能夠處理的數據量:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章