Windows Phone上的内存消耗开销

时间:2016-05-04 11:04:51

标签: c# memory-management windows-runtime windows-phone-8.1 win-universal-app

通用Windows 8.1存储项目。

我正在使用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

enter image description here

那里发生了什么?我只是做错了吗?

以下是我用于测试的代码的简要版本:

// 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);
}

UPDATE :我发现,当我不使用线程池而只执行var task1 = ReadFile("1");时,内存开销会降低约5倍(尽管它仍然存在)。为什么? (在实际项目中,我对文件内容有一些cpu绑定的工作,而不仅仅是异步IO,所以我想我还是需要单独的线程。)

1 个答案:

答案 0 :(得分:2)

问题在于CryptographicBuffer。 Windows.Storage.Streams.Buffer应该用于文件IO。

var buf = new Windows.Storage.Streams.Buffer(16*1024);