[英]Out Of Memory Exception when downloading a video file
我們目前從 Twilio 下載視頻,下載視頻后,我們將視頻保存在AWS S3
中。 但是,在部署到生產環境時,我目前得到:
引發了“System.OutOfMemoryException”類型的異常。
嘗試下載視頻時,
我檢查了 Twilio 中的視頻大小,它們相對較小,172,912kb
我已將 S3 上的實例升級到大型實例,因為我認為這將是一個問題,因為在它們很小之前。
但是問題仍然存在,它失敗的代碼塊如下:
var request = (HttpWebRequest)WebRequest.Create($"{resource.Url}/Media");
request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(_twilioOptions.ApiKey + ":" + _twilioOptions.ApiSecret)));
request.AllowAutoRedirect = true;
var responseBody = (request.GetResponseAsync().Result).GetResponseStream();
byte[] tempBuffer = new byte[8192];
MemoryStream ms = new MemoryStream();
int read;
while ((read = responseBody.Read(tempBuffer, 0, tempBuffer.Length)) > 0)
{
ms.Write(tempBuffer, 0, read);
}
var result = ms;
var fileName = $"Conversations/{conversationId}/Video-{DateTime.UtcNow:yyyyMMdd-hhmmss}-{compositionSid}.{resource.Format}";
var uploadedFile = await _fileUploader.UploadFile(result, fileName, _s3Options.SecureBucket, "video/mp4");
任何人都可以為此推薦解決方案/修復程序嗎?
從理論上講,在S3 ( 7GB RAM
計划)上一次將 ~170MB 文件下載到 memory 應該沒有問題。 但是,您不會處置或關閉任何資源。 根據周圍的代碼,這很可能是未釋放非托管資源的問題,並可能導致 memory 在一段時間內用完。
現在我們可以對Close()
或Dispose()
進行顯式調用,但更容易將相關代碼封裝在using()
塊中,如下所示:
byte[] tempBuffer = new byte[8192];
using (var responseBody = (request.GetResponseAsync().Result).GetResponseStream())
using (var ms = new MemoryStream()) // <------- using block, will call Dispose()
{
int read;
while ((read = responseBody.Read(tempBuffer, 0, tempBuffer.Length)) > 0)
{
ms.Write(tempBuffer, 0, read);
}
var result = ms;
var fileName = $"Conversations/{conversationId}/Video-{DateTime.UtcNow:yyyyMMdd-hhmmss}-{compositionSid}.{resource.Format}";
var uploadedFile = await _fileUploader.UploadFile(result, fileName,
_s3Options.SecureBucket, "video/mp4");
}
您的代碼類似於此MSDN 示例,但是您會注意到Close()
的使用。
感謝 mjwills 發現responseBody
也可以放入using()
塊中,從而節省顯式Close
。
即使有了這些修復,您也可能希望利用流式資源的最佳實踐,而不是一次全部加載,尤其是在不需要一次將其全部加載到 memory 的情況下。 只需為源創建一個讀取 stream 並為目標創建一個寫入 stream。 然后它只是一次讀取和寫入塊的問題。
正如您可能已經猜到的那樣,將整個視頻保存在 memory 中是一個壞主意,如果它很大的話。
盡管 180mb 看起來並不多,但它仍然需要一個連貫的 memory 區域用於 LOH 中。 使用某些將塊寫入磁盤的方法可能會更好。 為了提高性能和避免 LOH 中的 memory 碎片,您也可以順便使用RecyclableMemoryStream
,但這對您當前的系統沒有任何作用。
通常你應該避免這種設計。 要么保存到磁盤(使用 memory 緩沖)並信任小文件的文件系統緩存,要么嘗試直接將下游饋送到上游。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.