【问题标题】:Why does 'file.size' take a lot of time, and how to reduce the time?为什么'file.size'需要很多时间,以及如何减少时间?
【发布时间】:2011-09-06 20:33:14
【问题描述】:

我正在制作一个处理被拖到应用程序的歌曲的应用程序。当我使用file.size 来获取文件的大小时,大约需要 1500 毫秒(平均)来获取这个值。有没有更快的方法?我理解为什么这需要时间(和内存),但由于我是处理 HTML5 文件的新手,也许有一些我不知道的东西可以加快处理速度。

文件系统 API 也是如此。如果我通过它调用文件并调用file.size,则需要类似的时间。

PS 我通过在我的代码中添加 console.time() 得出了这个结论。

这里是代码(大量精简)

fileSystem.root.getFile(id, {}, function(fileEntry) {
    fileEntry.file(function(audioTemp) {
        console.time(1);
        console.log(audioTemp.size);
        console.timeEnd(1)
    });
});

这是文件系统 API 示例。这(显然)需要名为id 的文件才能工作。下面是D&D文件输入代码

function onChangeAddSongsInput() {
    var files = document.getElementById('addSongsInput').files;
    for(var i=0; i<files.length; i++) {
        console.time(1);
        console.log(files[i].size);
        console.timeEnd(1)
    }
}

编辑

我使用的是 AMD 等效的核心二双核、2.7 GHz、2 gigs 内存、win7 x64。我相信的规格实际上是足够体面的。因此,如果某些东西在我的机器上确实需要足够长的时间,我会认为它是不行的。

这是我的应用程序中主要错误修复的阻止程序。我真的很想在很长一段时间内提供修复程序。我(还)无法设置赏金,也许在设置赏金之前有最短时间。

编辑

我做了一些测试,结果证明,这需要很长时间,因为 chrome 计算 大小,而不是仅仅从一些元数据中读取它。 Here是测试结果。

文件越大,花费的时间越长,如果第二次调用它会使用一些缓存并且不会加载文件。所以现在..我怎样才能减少这个时间?大小是我的应用程序中的一个重要信息,但可能不足以使每个文件的用户上传速度降低约 1.5 秒!我正计划导入库,当添加 100 首左右的歌曲时,它确实有助于减少这个时间。那么这一次将是应用响应时间的一个重大突破。

【问题讨论】:

  • 代码你发布代码示例或在 JSFiddle.net 上做一个小提琴好吗?
  • 当然 :) 我认为这很容易,但没关系。
  • 我只是想看看你的代码在我的硬件上是如何工作的 :)
  • 没有问题 :D 添加了代码 :)
  • 您正在使用什么浏览器/操作系统/文件大小?平均大小的 mp3 在这里速度非常快。

标签: javascript google-chrome file-upload html5-filesystem


【解决方案1】:

这是一个有根据的猜测:

查看the definition of the HTML5 File interface 会发现FileBlob,而size 属性实际上是Blob interface 的一部分。

由于Blob 是对原始数据块的抽象,访问size 属性实际上可能会导致实现将整个文件加载到内存中。您可以编写一个实验来查看延迟是否随文件大小而变化,或者延迟是否仅在第一次读取 size 属性时发生。

编辑

我真的觉得这种低效率是浏览器实现File接口的问题,但这里有两个关于如何在将大文件加载到内存时避免延迟的解决方法:

Web workers(MDN reference, WHATWG Webapps Standard) 将允许您将文件的缓慢加载本质上放到另一个线程中。我认为这是你最好的选择。

另一种方法是使用Blob 接口的slice method 来加载File 的一小部分。如果slice 的实现只加载文件的所需部分,它应该会更快。您必须为每个文件加载多个切片,并且需要通过注意slice 返回的Blob 的大小来检测何时到达文件末尾。您将通过取回一个小于您预期的 blob 来检测文件的结尾——来自规范:

如果索引算术超出大小范围,切片方法必须钳制大小值。特别是,这意味着对于给定的切片调用:

如果 start + length > size 则用户代理必须返回一个 Blob 对象,就像调用了 slice(start, size-start) 一样。

如果 start > size 则用户代理必须返回大小为 0 的 Blob 对象

不幸的是,规范还提到了当您请求一个超出Blob 缓冲区大小的切片时可能引发异常——在任何这样做的实现中,您必须捕获异常以检测结束文件。

【讨论】:

  • hmm 是的,我几乎可以肯定整个文件首先加载到内存中,然后计算大小。原因(我认为)是文件的大小不仅仅是任何元数据可以阅读,它必须*计算*。无论如何,我都会写这两个测试来确认这一点。现在的问题是,是否有任何元数据可以比将文件加载到内存然后计算大小更快地读取
  • 好的,这里的测试结果是twitpic.com/6iyb39我用doffrent文件尝试了多次,每次都是一样的结果。文件越大,花费的时间越长,如果第二次调用它会使用一些缓存并且不加载文件。所以现在..我怎样才能减少这个时间?大小是我的应用程序中的一个重要信息,但可能不足以使 每个 文件的用户上传速度降低约 1.5 秒!我正计划导入库,当添加 100 首左右的歌曲时,它确实有助于减少这个时间。
  • 我在我的答案中添加了两种可能的解决方法——我认为它们是你最好的选择。 File.size 的这种不良行为可能也应该作为一个错误提交,如果你有时间把它写好的话。
  • 切片的实现似乎有点 hack 真的,我想我会走网络工作者的路。但是必须运行一些测试来确定编写一个工人是否真的值得所有额外的代码。我理论上熟悉工人和 AFAIK 工人将繁重的工作卸载到 CPU 上。对吗?如果是,那么它可以有足够好的减少。但我会在做一些测试后发回。非常感谢您指点我! :D 我应该在哪里提交错误? webkit 还是铬?
  • 好吧,我赢了,但我想我会把它添加到铬中,如果他们觉得有必要,他们会在上游添加它。 :)
【解决方案2】:

如果你增加在 Console.Time() 下设置的时间,它会给你更多的性能。您需要确保在加载和显示文件之前,此时间不会超时。

【讨论】:

  • increase the time set under Console.Time() 你能详细说明一下吗?我不认为延迟是因为文件没有加载到浏览器中,因为当有多个文件被拖动并且.size 循环发生时,它需要相似的时间。
  • 我说要在文件加载的各个地方多保留等待时间和睡眠时间
猜你喜欢
  • 2012-01-14
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
  • 2020-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多