【问题标题】:FileReader: reading many files with javascript without memory leaksFileReader:使用 javascript 读取许多文件而没有内存泄漏
【发布时间】:2015-06-10 21:43:47
【问题描述】:

在网页中,我必须读取文件的一小部分,这适用于许多 (1500 - 12000) 个小文件,每个文件大约 1 Mb 大。收集到所需信息后,我会将其推送回服务器。

我的问题:我使用 FileReader API,垃圾收集不起作用,内存消耗激增。

代码如下:

function extract_information_from_files(input_files) {

//some dummy implementation
for (var i = 0; i < input_files.length; ++i) {


    (function dummy_function(file) {

        var reader = new FileReader();

        reader.onload = function () {

            //convert to Uint8Array because used library expects this

            var array_buffer = new Uint8Array(reader.result);

            //do some fancy stuff with the library (very small subset of data is kept)

            //finish

            //function call ends, expect garbage collect to start cleaning.
            //even explicit dereferencing does not work
        };

        reader.readAsArrayBuffer(file);

    })(input_files[i]);

}

}

一些备注:

  • 不,乍一看,库似乎没有保留对已加载对象的任何引用。即使您运行如上所示的代码,并且根本没有使用 array_buffer,所有内容都保存在内存中。
  • 行为因浏览器而异:
  • Chrome (43) 无法清除所有内容
  • Firefox (38) 似乎使用了所有文件大小的大约 1/3 的剩余内存使用量
  • 我发现在 Internet 上讨论相同问题的主题非常非常少。我尝试过的是:
  • Is it possible to clean memory after FileReader? -> 旧的,File.prototype.mozSlice 已更改为 .slice,但问题仍然存在
  • http://www.joelandritsch.com/posts/lessons-learned-in-javascript-11 -> 建议的解决方案不起作用。
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management 对我来说不是很清楚。 -> 似乎首先您不需要取消引用(请参阅不需要对象与对象不可访问),但随后它们还声明“限制:需要使对象显式不可访问”

最后一个奇怪的细节(为完整性而发布),当使用 FileReader 和 https://gildas-lormeau.github.io/zip.js/ 时,我在将文件推送到 zip 存档之前读取了一个文件,垃圾收集就可以了。

所有这些言论,似乎指向我无法正常使用 FileReader,所以请告诉我如何。

【问题讨论】:

    标签: javascript file


    【解决方案1】:

    问题可能与执行顺序有关。在您的for 循环中,您正在读取带有reader.readAsArrayBuffer(file) 的所有文件。此代码将在为读者运行任何onload 之前运行。根据FileReader 的浏览器实现,这可能意味着浏览器会在调用任何onload 之前加载整个文件(或简单地为整个文件预分配缓冲区)。

    尝试像队列一样处理文件,看看它是否有所作为。比如:

    function extract_information_from_files(input_files) {
        var reader = new FileReader();
    
        function process_one() {
            var single_file = input_files.pop();
            if (single_file === undefined) {
                return;
            }
    
            (function dummy_function(file) {
                //var reader = new FileReader();
    
                reader.onload = function () {
                    // do your stuff
                    // process next at the end
                    process_one();
                };
    
                reader.readAsArrayBuffer(file);
            })(single_file);
        }
    
        process_one();
    }
    
    extract_information_from_files(file_array_1);
    // uncomment next line to process another file array in parallel
    // extract_information_from_files(file_array_2);
    

    编辑:似乎浏览器希望您重用FileReaders。我编辑了代码以重用单个阅读器并测试(在 chrome 中)内存使用量限制为您阅读的最大文件。

    【讨论】:

    • 感谢您的建议。我更正了我最初的帖子,因为我现在根据浏览器看到不同的行为。然而,你的建议似乎根本没有任何区别。我们有 FileReader 的替代品吗
    • 我认为没有其他替代 API。至少具有相同的标准化水平。不过,奇怪的是我的建议没有任何区别。我会调查,因为我也有兴趣知道原因。
    • 经过测试,我可以复制您描述的问题,并且似乎浏览器所做的任何内存管理都假定您使用很少的 FileReader 实例。
    猜你喜欢
    • 1970-01-01
    • 2012-11-19
    • 2017-05-02
    • 1970-01-01
    • 2013-04-30
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    相关资源
    最近更新 更多