【问题标题】:Is it possible to clean memory after FileReader?是否可以在 FileReader 之后清理内存?
【发布时间】:2011-10-31 13:16:24
【问题描述】:

FileReader 似乎消耗了所有内存,因为它反复用于预加载多个 blob,并且从不释放它。任何已知的方法来强制它释放消耗的内存?将 FileReader 对象及其结果属性设置为 null 似乎不起作用。

更新:

这是一个sample code(在大文件上测试它,比如电影,否则你不会注意到任务管理器中的效果):

<input id="file" type="file" onchange="sliceMe()" />

<script>
function sliceMe() {
    var file = document.getElementById('file').files[0], 
        fr,
        chunkSize = 2097152, 
        chunks = Math.ceil(file.size / chunkSize), 
        chunk = 0;

    function loadNext() {
       var start, end,
           blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice;

       start = chunk * chunkSize;
       end = start + chunkSize >= file.size ? file.size : start + chunkSize;

       fr = new FileReader;
       fr.onload = function() {      
          if (++chunk < chunks) {
             // shortcut - in production upload happens and then loadNext() is called
             loadNext(); 
          }
       };
       fr.readAsBinaryString(blobSlice.call(file, start, end));
    }

    loadNext();
}
</script>

我每次都尝试创建新的 FileReader 实例,但问题仍然存在。我怀疑这可能是由模式的循环性质引起的,但我不确定在这种情况下可以使用什么其他模式。

我在 Firefox 和 Chrome 中检查了这段代码,Chrome 似乎可以更优雅地处理它 - 它在每个周期后都会清除内存并且速度非常快。但具有讽刺意味的是,Chrome 根本不需要使用这段代码。这只是一个克服 Gecko 6- FormData + Blob bug (Bug 649150 - Blobs do not have a filename if sent via FormData) 的实验。

【问题讨论】:

  • 您是否尝试过不重复使用文件阅读器,而是在每次需要时创建一个新实例?
  • 你有明确的例子吗?什么浏览器?你能不能做一个小提琴?
  • 感谢四你的榜样。将其设置为null似乎在几秒钟后清除内存(在选择另一个标签时)。 span>
  • 有趣的观察...嗯。实际上,有时即使没有将其设置为 null,它也会清除内存,但使用 null 时情况会更加明显。我现在想知道我们是否可以以某种方式使用它...
  • 提交了一个错误:bugzilla.mozilla.org/show_bug.cgi?id=680847,欢迎大家投票。

标签: javascript dom memory-leaks memory-management filereader


【解决方案1】:

试试这样吧:

function sliceMe() {
        var file = document.getElementById('file').files[0],
        fr = new FileReader,
        chunkSize = 2097152,
        chunks = Math.ceil(file.size / chunkSize),
        chunk = 0;

    function loadNext() {
       var start, end,
           blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice;

       start = chunk * chunkSize;
       end = start + chunkSize >= file.size ? file.size : start + chunkSize;

       fr.onload = function() {      
          if (++chunk < chunks) {
             //console.info(chunk);
          }
       };
       fr.onloadend = function(e) {      
          loadNext(); // shortcut here
       };
       fr.readAsBinaryString(blobSlice.call(file, start, end));
    }

    loadNext();
}

onloadend 将防止您与其他读取重叠...(显然,您可以更好地修复增量,但您明白了...)

【讨论】:

    【解决方案2】:

    错误已被标记为无效,因为事实证明我实际上并没有正确地重用 FileReader 对象。

    这是一个不占用内存和cpu的模式:

    function sliceMe() {
        var file = document.getElementById('file').files[0],
            fr = new FileReader,
            chunkSize = 2097152,
            chunks = Math.ceil(file.size / chunkSize),
            chunk = 0;
    
        function loadNext() {
           var start, end,
               blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice;
    
           start = chunk * chunkSize;
           end = start + chunkSize >= file.size ? file.size : start + chunkSize;
    
           fr.onload = function() {      
              if (++chunk < chunks) {
                 //console.info(chunk);
                 loadNext(); // shortcut here
              }
           };
           fr.readAsBinaryString(blobSlice.call(file, start, end));
        }
    
        loadNext();
    }
    

    另一个错误报告已提交:https://bugzilla.mozilla.org/show_bug.cgi?id=681479,这是相关的,但在这种情况下不是邪恶的。

    感谢 Kyle Huey 让我注意到这一点 :)

    【讨论】:

    • 嘿,这个解决方案真的对你有用吗?我有一个类似的问题,在切片中加载大文件时也有类似的尝试。但是当加载大于 gig 的文件时,chrome 仍然会崩溃或变得无响应。我正在重用 FileReader 对象,而不是每次都构造一个。
    • 您是否将整个文件加载到内存中?
    • 不,我正在尝试分片读取文件。事实上,我什至尝试复制上面列出的代码。
    • 我很确定您想要的是后增量而不是前增量。这个 (chunk++
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    相关资源
    最近更新 更多