【问题标题】:WinRT: Reading and deserializaing large amount of files takes too much timeWinRT:读取和反序列化大量文件需要太多时间
【发布时间】:2012-12-16 15:26:38
【问题描述】:

我有一个 Windows Store 应用程序,它管理对象集合并将它们存储在应用程序本地文件夹中。这些对象使用 JSON 在文件系统上进行序列化。由于我需要能够单独编辑和保留这些项目,因此我为每个对象选择了单独的文件,而不是一个大文件。对象按照这种模式存储:

Local Folder
|
--- db
    |
    --- AB283376-7057-46B4-8B91-C32E663EC964
    |   |
    |   --- AB283376-7057-46B4-8B91-C32E663EC964.json
    |   --- AB283376-7057-46B4-8B91-C32E663EC964.jpg
    |
    --- B506EFC5-E853-45E6-BA32-64193BB49ACD
    |   |
    |   --- B506EFC5-E853-45E6-BA32-64193BB49ACD.json
    |   --- B506EFC5-E853-45E6-BA32-64193BB49ACD.jpg
    |
    ...

每个对象都有其文件夹节点,其中包含 JSON 序列化对象和其他最终资源。

当我进行一些写作、阅读、删除测试时,一切都很好。当我试图在应用程序启动时加载大量对象时,它变得复杂了。我估计item的最大数量会存储到10000,所以我写了10000个条目然后尝试加载它......超过3分钟到应用程序完成操作,这当然是不可接受的。

所以我的问题是,在我为读取和反序列化对象(下面的代码)编写的代码中可以优化什么?有没有办法实现分页系统,以便在我的 WinRT 应用程序中动态加载?就 IO/CPU 而言,我的存储方法(上述模式)是否过于繁重?我在 WinRT 中遗漏了什么吗?

public async Task<IEnumerable<Release>> GetReleases()
{
    List<Release> items = new List<Release>();

    var dbFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(dbName, CreationCollisionOption.OpenIfExists);

    foreach (var releaseFolder in await dbFolder.GetFoldersAsync())
    {
        var releaseFile = await releaseFolder.GetFileAsync(releaseFolder.DisplayName + ".json");
        var stream = await releaseFile.OpenAsync(FileAccessMode.Read);

        using (var inStream = stream.GetInputStreamAt(0))
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Release));
            Release release = (Release)serializer.ReadObject(inStream.AsStreamForRead());
            items.Add(release);
        }

        stream.Dispose();
    }

    return items;
}

感谢您的帮助。

注意:我已经看过 SQLite,我不需要这么复杂的系统。

【问题讨论】:

    标签: json optimization io windows-runtime


    【解决方案1】:

    据说 JSON.NET 比内置的东西更好。如果您不通过网络发送数据,那么最快的方法是进行二进制序列化而不是 JSON 或 XML。最后 - 考虑一下您是否真的需要在应用程序启动时加载所有数据。将您的数据序列化为二进制记录列表并创建一个索引,以便您快速跳转到实际需要使用的记录范围。

    【讨论】:

    • WinRT 中似乎没有开箱即用的二进制序列化。我会尝试找到一个支持它的库。我测试了 Json.Net,我注意到加载时性能提高了 20%,这非常令人鼓舞!我有点喜欢我的对象的原子性,因为它们可以单独编写(就像在数据库中一样)。序列化到列表肯定会减少一些文件系统 IO 开销,但序列化不会更快。
    【解决方案2】:

    正如 Filip 已经提到的,您可能不需要在启动时加载所有数据。即使您真的想在第一页显示所有项目(一次向用户显示 10,000 个项目对我来说听起来不是一个好主意),您也不需要让它们的所有属性都可用:通常只有一个其中几个显示在列表中,当用户导航到单个项目详细信息时,您需要其余的。您可以有一个单独的“索引”文件,其中仅包含列表所需的数据。这确实意味着重复,但它会帮助您提高性能。

    尽管您已经提到过,但您不需要 SQLite,因为它对您的需求来说太复杂了,您真的应该仔细研究一下。它旨在有效地处理结构化数据,例如您的数据。我很确定如果你切换到它,性能会更好,你的代码最终可能会更简单。试试看。

    【讨论】:

    • 确实,我不需要在启动时加载所有内容,这就是为什么我还建议有一种分页。听说WinRT提供了虚拟化列表加载,这要归功于某些Web服务的分页功能,但由于我提供自己的数据源,我不知道如何实现它。关于 SQLite,我的对象模型非常简单,并且包含列表引用枚举。如果我使用 SQLite,对象模型会变得更加复杂,我什至不必担心使用序列化,但我不能说拥有可查询的数据源会很好,所以我会尝试一下。
    猜你喜欢
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-29
    相关资源
    最近更新 更多