1 回答

TA貢獻1757條經驗 獲得超7個贊
你在評論中提到
每個 goroutine 都在讀取要編碼的文件
但當然,文件——任何文件——已經以某種方式編碼:也許是純文本,或者是 UTF-8(字節流),也許是組裝成“行”單元。或者它可能是一個圖像流,例如一個 mpeg 文件,由一些幀組成。或者它可能是一個由記錄組成的數據庫。無論其輸入形式是什么,它都包含某種基本單元,您可以將其提供給您的(重新)編碼器。
那個單位,不管它是什么,都是一個合理的分工場所。(多么明智,取決于它是什么。請參閱下面的分塊的想法。)
假設文件由獨立的行組成:然后使用scanner.Scan來讀取它們,并將每一行傳遞給一個接收行的通道。分拆 N,對于一些 N,閱讀頻道的讀者,一次一行:
ch := make(chan string)
for i := 0; i < n; i++ {
go readAndEncode(ch)
}
// later, or immediately:
for s := bufio.NewScanner(os.Stdin); s.Scan(); {
ch <- s.Text()
}
close(ch)
如果有 100 行和 4 個閱讀器,前四個ch <- s.Text()操作會快速進行,第五個操作會暫停,直到其中一個閱讀器完成編碼并返回讀取通道。
如果單個行太小,也許您應該一次讀取一個“塊”(例如,1 MB)。如果塊的末尾有部分行,請備份或閱讀更多內容,直到您有整行。然后發送整個數據塊。
因為通道復制數據,您可能希望發送對塊的引用。1 這適用于任何更大的數據單元。(行往往很短,與首先使用通道的開銷相比,復制它們的開銷通常不是很大。如果你的行有 type string,那么,請參閱腳注。)
如果行或行塊在這里不是正確的工作單元,請弄清楚什么是. 將 goroutine 想象為每個人都有一份工作要做的人(或忙碌的小地鼠) 。他們可以依靠其他人——另一個人或地鼠——來做一份較小的工作,不管那是什么;并且有十個人,或稱地鼠,處理子任務允許主管管理它們。如果你需要做 N 次相同的工作,并且 N 不是無界的,你可以分拆 N 個 goroutine。如果 N可能是無界的,則分拆一個固定的數字(可能基于#cpus)并通過通道為它們提供工作。
1正如 Burak Serdar 所指出的,一些副本可以自動刪除:例如,字符串實際上是只讀切片。切片類型包含三個部分:指向底層數據的指針(引用)、長度和容量。復制切片會復制這三個部分,但不會復制底層數據。字符串也是如此:字符串標題省略了容量,因此通過通道發送字符串僅復制兩個標題詞。因此,許多明顯且易于編碼的數據分塊方式已經非常有效。
- 1 回答
- 0 關注
- 135 瀏覽
添加回答
舉報