4

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>
Roey Zada
  • 663
  • 10
  • 30
  • _"to check, please upload more then 200 pictures"_ Creating 200 instances of `FileReader` ? _"up to 30MG. "_ What is "MG" ? – guest271314 Aug 19 '15 at 18:02
  • Is it creating 200 instances? MG is mega bytes, the idea is to upload many images to client and see the effect on memory. If you upload 10 pictures you won't see the different – Roey Zada Aug 19 '15 at 18:07
  • Try opening Task Manager , selecting current tab , viewing Memory at http://jsfiddle.net/uynvenL9/ – guest271314 Aug 19 '15 at 18:16
  • 2
    I have a strong feeling that it's your `reader.onloadend` function... really I don't understand what you are trying to do there? – MinusFour Aug 19 '15 at 18:20
  • onloadend - i get the stream of the file i need to fetch data and to show thumbnails. here I've shown that even if i don't do nothing but loading one file and then the next, it is still messing up the memory @MinusFour – Roey Zada Aug 19 '15 at 18:24
  • I didn't understand what are you showing me there.. @guest271314 – Roey Zada Aug 19 '15 at 18:27
  • @RoeyZada Try creating `` element at jsfiddle , uploading 200 files while simultaneously viewing Task Manager -> Memory – guest271314 Aug 19 '15 at 18:29
  • @RoeyZada, aren't you creating a loop by having `fu.load` call `fu.load`? – MinusFour Aug 19 '15 at 18:29
  • I do. But it's only a loop until all the files are loaded @MinusFour – Roey Zada Aug 19 '15 at 18:41
  • I already know my memory goes high by viewing task manager on my computer @guest271314 – Roey Zada Aug 19 '15 at 18:41
  • @RoeyZada _"I already know my memory goes high by viewing task manager on my computer"_ Not certain interpret correctly ? What is Question ? – guest271314 Aug 19 '15 at 18:55
  • I didn't understand why I need jsfiddle for it.. @guest271314 – Roey Zada Aug 19 '15 at 19:03

2 Answers2

4

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>
Roey Zada
  • 663
  • 10
  • 30
0

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.

MinusFour
  • 13,913
  • 3
  • 30
  • 39
  • Please try using chrome. Are you uploading large files? – Roey Zada Aug 19 '15 at 19:34
  • @RoeyZada, I've updated the answer with Chromium and added a possible fix. – MinusFour Aug 19 '15 at 22:43
  • thank you! .. unfortunately this still not freeing the memory in my case on chrome. in Firefox it works like a charm. – Roey Zada Aug 20 '15 at 01:08
  • I noticed it doesn't free the resources inmediately... I don't know why. It takes like a min or so, but it does free most of it on Chrome and works perfectly on Firefox. – MinusFour Aug 20 '15 at 02:01
  • I've finally found the fix. take a look at my answer, the reason was to have reader only have one - new FileReader() - now it doesnt go up at all for both firefox and chrome! .. thank you alot for your help :) @MinusFour – Roey Zada Aug 20 '15 at 02:08