這是對 go中關於chan應用的程序分析
文章中代碼的流水流水線示意圖。
- 我們假設gen,sq和print操作需要的時間單位都是1:
time | gen | sq | |
---|---|---|---|
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 | |
---|---|---|---|
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 | |
---|---|---|---|---|---|
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 | |
---|---|---|---|---|---|---|
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 | |
---|---|---|---|---|---|---|
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)圖中的數字指每個方法在單位時間內能夠處理的數據量: