FileReader memory leak

2019-08-08 17:05发布

I'm using FileReader to upload image files to a client for data fetching and thumbnails display.

what I've noticed is, that on the page process, in task manager, the memory just keeps going higher and higher. and when the process stops, and memory stay high and never goes down.

can you please tell me what I am doing wrong here?

to check, please upload more then 200 pictures, up to 30MG. and see that the memory keeps on leaking

thank you in advanced.

-- here is a link to a code example on the web

and here is my code:

<input class="fu" type="file" multiple="multiple" />
<div class="fin"></div>
<div class="list"></div>

<script type="text/javascript">
    $(document).ready(function () {
        var input = $("body input.fu");

        input[0].addEventListener('change', fu.select, false);
    });

    var fu = {
        list: [],
        index: 0,

        select: function (evt) {
            evt.stopPropagation();
            evt.preventDefault();

            var files = evt.target.files ? evt.target.files : evt.dataTransfer ? evt.dataTransfer.files : []; // FileList object

            fu.list = files;
            fu.index = 0;

            fu.load();
        },

        load: function () {
            var index = fu.index;
            var file = fu.list[index];

            if (file) {
                var reader = new FileReader(); // File API object

                reader.onloadend = (function (theFile) {
                    return function (evt) {
                        if (evt.target.readyState == FileReader.DONE) {
                            setTimeout(fu.load, 20);
                        }
                    };
                })(file);


                reader.onprogress = null;
                reader.onloadstart = null;
                reader.onerror = null;
                reader.onabort = null;

                if (reader.readAsBinaryString) {
                    reader.readAsBinaryString(file);
                } else {
                    reader.readAsDataURL(file);
                }

                fu.index++;
                $('.fin').html("#" + fu.index);
            } else {
                $('.fin').html("finish");
            }

        }
    }
</script>

2条回答
Animai°情兽
2楼-- · 2019-08-08 17:31

ok, I have fixed this.

the reason was that I set reader to - new FileReader() - each time.

so I only made it global.

here is the working code:

<script type="text/javascript">
    $(document).ready(function () {
        var input = $("body input.fu");

        input[0].addEventListener('change', fu.select, false);
    });

    var fu = {
        list: [],
        index: 0,
        reader: null,

        select: function (evt) {
            evt.stopPropagation();
            evt.preventDefault();

            var files = evt.target.files ? evt.target.files : evt.dataTransfer ? evt.dataTransfer.files : []; // FileList object

            fu.list = files;
            fu.index = 0;

            fu.reader = new FileReader(); // <- made this only once

            fu.load();
        },

        load: function () {
            var index = fu.index;
            var file = fu.list[index];

            if (file) {
                fu.reader.onloadend = (function (theFile) {
                    return function (evt) {
                        if (evt.target.readyState == FileReader.DONE) {
                            fu.reader.abort();

                            setTimeout(fu.load, 5);
                        }
                    };
                })(file);


                fu.reader.onprogress = null;
                fu.reader.onloadstart = null;
                fu.reader.onerror = null;
                fu.reader.onabort = null;

                if (fu.reader.readAsBinaryString) {
                    fu.reader.readAsBinaryString(file);
                } else {
                    fu.reader.readAsDataURL(file);
                }

                fu.index++;
                $('.fin').html("#" + fu.index);
            } else {
                $('.fin').html("finish");
            }

        }
    }
</script>
查看更多
疯言疯语
3楼-- · 2019-08-08 17:33

I just tested it with 289 files and there's no memory leak. Here's the jsfiddle I use:

http://jsfiddle.net/2pyqjeke/

Before reading:

              total        used        free      shared  buff/cache   available
Mem:           3945        1400         749          23        1796        2253

After reading:

              total        used        free      shared  buff/cache   available
Mem:           3945        1963         292          23        1690        1690

Sometime after:

              total        used        free      shared  buff/cache   available
Mem:           3945        1398         856          23        1690        2255

I'm using Firefox and Manjaro.

Edit

With Chromium these are my results.

Before:

              total        used        free      shared  buff/cache   available
Mem:           3945        1140         633          52        2171        2476

After loading pictures:

              total        used        free      shared  buff/cache   available
Mem:           3945        1573         296          43        2075        2050

And after that it wouldn't go down... so I'm guessing the GC is not releasing the file readers. So I did a very small change to the code:

http://jsfiddle.net/2pyqjeke/1/

And here are the results again in Chromium...

Before:

              total        used        free      shared  buff/cache   available
Mem:           3945        1197         672          44        2075        2426

After loading pictures:

              total        used        free      shared  buff/cache   available
Mem:           3945        1588         322          44        2034        2035

And after a while it went down to:

              total        used        free      shared  buff/cache   available
Mem:           3945        1227         684          44        2034        2397

Quite frankly I don't why Chromium is not releasing the FileReader and Firefox is.

查看更多
登录 后发表回答