FileReader利用時のメモリ増減パターンをちょっと調べてみた

FileReaderを通してローカル画像ファイルのプレビュー

jsFiddleを使ってみたかったので,デモ的に貼ってみます.

このあたりを参考に,FileReaderでローカルの画像ファイルを読み込み&ファイルプレビューをしてみました.大体動くんですが,どうもブラウザがメモリとってもおいしいです☆をしていたので,ちょっと調べてみました.

メモリリークするケース?

で,どうもFileReaderのインスタンスを作ったらしっかり使い回さないと,狭い確認範囲ですがメモリリークすることがあるみたいです.正直,ガベージコレクションに明るくなさ過ぎるので,考え方に自信ありませんが….

以下,検証がいい加減なところありますので話半分なご参考までに!(というかブラウザのメモリリークを厳密に計測する方法が分からず)

ケースA FileReaderをその都度生成してファイル(5MBのjpeg)を5回選択

document.addEventListener('DOMContentLoaded', function() {
    var input  = document.getElementById('input'),
        _image = document.createElement('image');

    input.addEventListener('change', function(e) {
        var file   = this.files[0],
            reader = new FileReader();

        if ( file.type.indexOf('image') === -1 ) {
            return;
        }

        reader.readAsDataURL(file);
    });
});

ケースB FileReaderを使い回してファイル(5MBのjpeg)を5回選択

document.addEventListener('DOMContentLoaded', function() {
    var input  = document.getElementById('input'),
        _image = document.createElement('image'),
        reader = new FileReader();

    input.addEventListener('change', function(e) {
        var file   = this.files[0];

        if ( file.type.indexOf('image') === -1 ) {
            return;
        }

        reader.readAsDataURL(file);
    });
});

ケースC ケースAと同じコードでファイル(5MBのjpeg)を1回だけ選択

じつはケースAとケースBを選択してから思いついたのですが,1回だけファイルを選択したパターンも比較用に.

結果

Mac版のChromeとFirefoxしか見ていませんが,ケースAでメモリリークらしきものが発生していることが確認できます.

Google Chrome 16 (MemoryはTaskMnagerからTab単位で確認) : ケースA before: 35MB / after: 66MB / result: +31MB : ケースB before: 32MB / after: 43MB / result: +11MB : ケースC before: 33MB / after: 45MB / result: +12MB

Firefox 8 (MacのActivity Monitorで確認) : ケースA before: 131MB / after: 178MB / result: +47MB : ケースB before: 128MB / after: 138MB / result: +10MB : ケースC before: 129MB / after: 143MB / result: +14MB

Firefox 3.6 (MacのActivity Monitorで確認) : ケースA before: 85MB / after: 93MB / result: +8MB : ケースB before: 85MB / after: 94MB / result: +9MB : ケースC before: 85MB / after: 87MB / result: +2MB

今回は5MB程度の大きい画像ファイルで検証しましたが,対象が数十KB程度の小さいファイルになるとここまでは顕在化しません.

readerがreadAsDataURL実行後のresultを抱え込んだまま処分されずに滞留しているから,リーク量がファイルサイズに左右されるんですかね.readAsDataURLを実行しない場合は,ケースAのようなコードでもメモリは膨れあがりません.

Firefox 3.6のケースA〜Cが全体的にあれれ?って感じで何度かやり直したのですが,傾向的には似たようなものでした.Firefoxの3.6当時って恒常的なメモリリークがあった気がするので,単純に操作すれするほど重くなってるだけかもしれませんし,ただの誤差かもしれません.つまりよくわかりません.X-(

ちなみに,1タブあたりのメモリ使用量がみやすいChromeで見たところ,(少なくともChromeは)タブを切り替えるとメモリが開放されるようです.

さらにreader.resultを参照すると…

reader.onload = function() {
    reader.result;
};
reader.readAsDataURL(file);

で,FileReaderがファイルを読み込み終わった後のreader.resultにアクセスすると,これまたメモリが一定量確保されます.dataURLの分ですかね.そいでこれがまた別途メモリリークしてるぽかったり…循環参照がうまく処分さてれないとかでしょうか.

今回FileAPI周りを軽く試すだけのつもりだったところ,大きい画像ファイルで試していたらクラッシュしてしまったので今回の検証に寄り道してしまった次第.

今回は解決的なオチはなしということで....より詳しい情報をご存じの方はご教授いただけたら嬉しいです.


Author

ahomuAyumu Sato

KINTOテクノロジーズ株式会社

Web 技術、組織開発、趣味など雑多なブログ。技術の話題は zenn、ご飯の話題はしずかなインターネットにも分散して投稿しています。

Bio: aho.mu
X: @ahomu
Zenn: ahomu
GitHub: ahomu
Sizu: ahomu

Related

Latest

Archives

Tags

Search