【发布时间】:2016-05-04 11:04:50
【问题描述】:
Universal Windows 8.1 Store 项目在这里。
我正在使用 512mb 内存的模拟器上进行一些内存分析。我在这里谈论的测试并不完全实用,我只是想了解一下机制。
测试项目非常简单:它打开一个大文件(超过 700mb)用于在线程上顺序读取,并通过 15mb 缓冲区读取它,在每次迭代后执行await Task.Delay();,以保持线程运行更长时间。我用Task.Run() 多次启动相同的代码并观察内存消耗。
当我强制 GC 时,内存量接近我的预期:
some initial 6-7 mb +
number_of_tasks * buffer_size +
some little memory per task for the objects created by the reading method
但让我感到困惑的是当我开始执行任务时的初始内存开销。在触发 GC 之前,应用程序消耗了两倍的内存,因此我只有 6 个同时读取线程出现内存不足异常。
例如,当我有 5 个阅读线程时:
- 应用以
~6.5mb的内存开头, - 然后在创建任务时增加到
~175mb(为什么?) - 拍摄快照时(触发 GC),消耗量降至
~85mb - 当所有线程完成读取时,内存下降到
~10mb
那里会发生什么?我是不是做错了什么?
这是我用于测试的代码的简短版本:
// the code is placed in the only page of the default Universal App -> Blank App template
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Test();
}
async Task Test()
{
Debug.WriteLine("BEGIN");
var task1 = Task.Run(()=>ReadFile("1"));
var task2 = Task.Run(()=>ReadFile("2"));
var task3 = Task.Run(()=>ReadFile("3"));
var task4 = Task.Run(()=>ReadFile("4"));
var task5 = Task.Run(()=>ReadFile("5"));
Debug.WriteLine("END");
await Task.WhenAll(task1, task2, task3, task4, task5, task6);
Debug.WriteLine("ALL TASKS COMPLETE");
}
async Task ReadFile(string tag)
{
Debug.WriteLine("FILE {0}: begin", tag);
var file = await StorageFile.GetFileFromApplicationUriAsync(
new Uri("ms-appx:///Assets/test.rar")
);
using(var seqStream = await file.OpenSequentialReadAsync()) {
var buf = CryptographicBuffer.CreateFromByteArray(new byte[15*1024*1024]);
IBuffer result = null;
uint total = 0;
do {
Debug.WriteLine("FILE {0}: read {1} bytes", tag, buf.Length);
var operation = seqStream.ReadAsync(buf, buf.Capacity, InputStreamOptions.None);
await operation;
if (operation.Status == AsyncStatus.Completed) {
result = operation.GetResults();
total += result.Length;
Debug.WriteLine("FILE {0}: got {1} bytes", tag, total);
} else {
result = null;
}
await Task.Delay(234);
} while (result != null && result.Length == buf.Capacity);
}
Debug.WriteLine("FILE {0}: end", tag);
}
更新:我发现,当我不使用线程池而只使用var task1 = ReadFile("1"); 时,内存开销会降低 5 倍(尽管它仍然存在)。为什么? (在实际项目中,我对文件内容进行了一些 cpu-bound 工作,而不仅仅是异步 IO,所以我想无论如何我都需要单独的线程。)
【问题讨论】:
标签: c# memory-management windows-runtime windows-phone-8.1 win-universal-app