Xamarin - 多个HTTP请求减慢应用程序的速度
问题描述:
我使用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请求时提高性能?
答
有两种许多问题与当前的代码:
- 这是低效的读取数据方面
- 它同步写入的数据,如果你是在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!
虽然你叫'ToList()'?这是一开始就引入不必要的复制。为什么你要在'while'循环的每次迭代中创建一个新的缓冲区?只需在循环之前创建一次*,以便您可以继续使用相同的缓冲区。事实上,为什么你有'缓冲'呢?你已经有了一个有效的缓冲区 - “数据”。直接读入:'int read = stream.ReadAsync(data,receivedBytes,totalBytes - receivedBytes,_cancelSource.Token).Result;' –
你是对的!我删除了缓冲区,似乎工作得更好。它减少了大约20%的CPU使用率!在物品列表上滚动时仍然不顺畅,因此欢迎提供任何提示。谢谢! – nhenrique
是否有任何理由使用* WriteFile的* synchronous *调用?这可能会使它也生涩...... –