2014-05-23 82 views
0

我使用Xamarin開發iOS應用程序。其中一項功能是以hls格式下載視頻,這意味着每個視頻可以有100到1000個區塊下載。所以我需要做100到1000個http請求。這是工作,但下載時應用程序非常慢,我用「樂器」進行了性能測試,CPU處於80%,一旦完成,它會回到0%-1%。這是在iPad上測試,而不是在模擬器上。Xamarin - 多個HTTP請求減慢應用程序的速度

public async Task CreateDownloadTask (string path){ 

var response = await _httpClient.GetAsync (GetUrl(path), 
            HttpCompletionOption.ResponseHeadersRead); 

if (!response.IsSuccessStatusCode) 
{ 
    Debug.WriteLine ("Error: " + path); 
    RaiseFault(new RpcFault("Error: Unable to download video", -1)); 
} 
else 
{ 
    var totalBytes = response.Content.Headers.ContentLength.HasValue 
        ? response.Content.Headers.ContentLength.Value : -1L; 

    using (var stream = await response.Content.ReadAsStreamAsync()) 
    { 
     var isMoreToRead = true; 
     var data = new byte[totalBytes]; 

     do 
     { 
      _cancelSource.Token.ThrowIfCancellationRequested(); 
      var buffer = new byte[4096]; 
      int read = stream.ReadAsync(buffer, 
             0, 
             buffer.Length, 
             _cancelSource.Token).Result; 

      if (read == 0) 
       isMoreToRead = false; 
      else { 
       buffer.ToList().CopyTo (0, data, receivedBytes, read); 
       receivedBytes += read; 
       HlsVideo.TotalReceived += read; 
      } 
     } while(isMoreToRead); 

     var fullPath = GetFullFilePath (path); 
     _fileStore.WriteFile (fullPath, data); 
    } 
} 

如何在做多個http請求時提高性能?

+1

雖然你叫'ToList()'?這是一開始就引入不必要的複製。爲什麼你要在'while'循環的每次迭代中創建一個新的緩衝區?只需在循環之前創建一次*,以便您可以繼續使用相同的緩衝區。事實上,爲什麼你有'緩衝'呢?你已經有了一個有效的緩衝區 - 「數據」。直接讀入:'int read = stream.ReadAsync(data,receivedBytes,totalBytes - receivedBytes,_cancelSource.Token).Result;' –

+0

你是對的!我刪除了緩衝區,似乎工作得更好。它減少了大約20%的CPU使用率!在物品列表上滾動時仍然不順暢,因此歡迎提供任何提示。謝謝! – nhenrique

+1

是否有任何理由使用* WriteFile的* synchronous *調用?這可能會使它也生澀...... –

回答

2

有兩種許多問題與當前的代碼:

  • 這是低效的讀取數據方面
  • 它同步寫入的數據,如果你是在UI線程上這顯然是一個問題

的「異步寫入數據」可能是一個簡單的修復,所以讓我們看看在讀取數據的效率低下:

  • 您在每次迭代中分配buffer。我們不關心前一次迭代的數據,因此您可以在while循環之前分配一次
  • 您在buffer上調用ToList,該副本將生成副本 - 然後將其複製到data
  • 根本不需要buffer!相反,兩項撥款,並在每次迭代兩個副本的,你可以只讀取字節直接data:在你的緩衝

    var data = new byte[totalBytes]; 
    
    do { 
        _cancelSource.Token.ThrowIfCancellationRequested(); 
        int read = stream.ReadAsync(data, receivedBytes, data.Length - receivedBytes, 
               _cancelSource.Token).Result; 
    
        receivedBytes += read; 
        if (read == 0 || receivedBytes == data.Length) 
         isMoreToRead = false; 
        } 
        HlsVideo.TotalReceived += read; 
    } while(isMoreToRead); 
    // TODO: check that receivedBytes == data.Length! 
    
相關問題