我正在嘗試提高我在 Go 中實(shí)現(xiàn)的下載器的性能。我認(rèn)為我遇到了內(nèi)存使用問(wèn)題,因?yàn)楫?dāng)我嘗試下載大文件(如 1gb 或更大)時(shí)程序卡住了。我用它下載了 100mgb 和 300mgb 左右的文件,一切正常。下載器在提供標(biāo)頭 Accept-Ranges 的服務(wù)器上使用。下面我將向您展示實(shí)現(xiàn)和主要部分,但首先讓我解釋一下。接受范圍:字節(jié)在這個(gè)實(shí)現(xiàn)中,我創(chuàng)建了一個(gè) http.Client 來(lái)使用我請(qǐng)求的文件部分設(shè)置標(biāo)題范圍,之后我提出了請(qǐng)求。為了存儲(chǔ)這個(gè)請(qǐng)求的響應(yīng),我創(chuàng)建了一個(gè)臨時(shí)文件,并將響應(yīng)直接復(fù)制到這個(gè)文件中。這樣做的想法是避免將整個(gè)響應(yīng)復(fù)制到內(nèi)存中。這是實(shí)現(xiàn):func DownloadPart(wg *sync.WaitGroup, tempName string, url string, part string) { //setting up the client to make the request client := http.Client{} request, err := http.NewRequest("GET", url, nil) //setting up the requests request.Header.Set("Range", part) response, err := client.Do(request) checkError(err, "fatal") defer response.Body.Close() //creating the temporary file and copying // the response to it file, err := os.Create(tempName) checkError(err, "panic") defer file.Close() _, err = io.Copy(file, response.Body) checkError(err, "fatal") defer wg.Done()}這個(gè)函數(shù)在各種 goroutine 中被調(diào)用,所以當(dāng) gorputine 結(jié)束下載部分文件時(shí),我使用了 WaitGroup 來(lái)減少計(jì)數(shù)器。在所有這些 goroutine 結(jié)束后,我將不同的臨時(shí)文件加入到一個(gè)文件中。這是join函數(shù)的實(shí)現(xiàn)func joinFiles(name string) { finalFile, err := os.OpenFile(name, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) if err != nil { log.Panicln(err.Error()) } defer finalFile.Close() files, err := ioutil.ReadDir(".") for _, f := range files { tempData, err := ioutil.ReadFile(f.Name()) if err != nil { log.Panicln(err.Error()) } if f.Name() != finalFile.Name() { finalFile.Write(tempData) os.Remove(f.Name()) } }}現(xiàn)在我將向您展示使用這些功能的主要功能部分//start, end and rest are used to set the Range header in the requests //threads are the number of goroutines to used in the downloadvar wg sync.WaitGroupwg.Add(threads)//initializing the goroutinesfor i := 0; i < threads; i++ { part := fmt.Sprintf("bytes=%d-%d", start, end) start = end + 1 if i == threads-1 { end = end + step + rest } else { end = end + step }如果有辦法改進(jìn)這個(gè)實(shí)現(xiàn)?
1 回答

守候你守候我
TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超10個(gè)贊
我認(rèn)為這里最大的問(wèn)題是您如何將文件拼接在一起。調(diào)用ioutil.ReadAll
會(huì)將整個(gè)文件的內(nèi)容讀入內(nèi)存,并且由于您對(duì)所有部分都執(zhí)行此操作,因此您可能會(huì)在內(nèi)存中結(jié)束整個(gè)文件的內(nèi)容(GC 可能會(huì)在中間運(yùn)行并釋放其中的一些內(nèi)容。)要做的是io.Copy
在文件上使用(在用打開(kāi)它之后os.Open
)將其復(fù)制到最終文件中。這樣您就不必將內(nèi)容存儲(chǔ)在內(nèi)存中。
- 1 回答
- 0 關(guān)注
- 99 瀏覽
添加回答
舉報(bào)
0/150
提交
取消