Canvasのメモリーリーク疑いについて

このQ&Aのポイント
  • Canvasを使用したペイントソフトにおいて、大量のレイヤーを使用するとメモリーリークが発生している可能性がある。
  • 特にFirefoxでは、1レイヤーにつき1MB程度のメモリを消費している。
  • メモリーリークが起きた場合の対処方法やCanvasの代替案について教えてほしい。
回答を見る
  • ベストアンサー

Canvasのメモリーリーク疑いについて

現在、Canvasを使ってペイントソフトにあるような「レイヤー」的な ことが出来ないか実験をしています。 (レイヤー数に関しては、最大で24程度を考えています。) 環境等は、以下の通りです。 OS:Windows XP Pro(SP3) 32bit メモリ:2GB ブラウザ:各ブラウザの最新版(FireFox,Chrome,Opera,safariも実施予定です。) 実験の結果、大量のレイヤーを使用した場合に ついてメモリーリーク的な問題が発生しているような感じがしています。 もちろん、レイヤーなのである程度のメモリ消費は承知の上だったのですが タブを閉じた際や描画してから時間が経過してもメモリ使用量が減少しないのは 使用上問題がありますので質問させて頂くことになった次第です。 (なお、レイヤー数を削減すると、比例してメモリ使用量も削減されていました。 メモリ使用量に関しては、タスクマネージャのプロセスタブのメモリ使用量 で見ています。) で、この問題が特に顕著なのが、Firefoxです。 私見では、1レイヤーにつき1MB程度消費してしまう感じです。 他のブラウザ(クローム、オペラ)では一時的にメモリ使用量は 増加しますが、時間が経過するとだいたい元にもどります。 なお、実験は以下のようなサンプルを作成して行っています。 (途中省略しています。) ご教授して頂きたい点は、以下になります。 ■メモリーリークが起きている場合の対処方法 (特にFirefoxにおける対処方法) ■Canvasを使用しない場合の代替案 宜しくお願い致します。 <html> <head> <script> function draw() { canvas = document.getElementById("g0"); if(!canvas || !canvas.getContext) return false; ctx = canvas.getContext('2d'); ctx.font = "15px 'MS Pゴシック'"; ctx.fillStyle = "black"; ctx.fillText("aaa", 100, 100); canvas = document.getElementById("g1"); if(!canvas || !canvas.getContext) return false; ctx = canvas.getContext('2d'); ctx.font = "15px 'MS Pゴシック'"; ctx.fillStyle = "black"; ctx.fillText("bbb", 150, 150); canvas = document.getElementById("g23"); if(!canvas || !canvas.getContext) return false; ctx = canvas.getContext('2d'); ctx.font = "15px 'MS Pゴシック'"; ctx.fillStyle = "black"; ctx.fillText("eee", 300, 300); } function start() { draw(); } </script> </head> <body onload="start()"> <body onload="start()"> <canvas height="500" width="500" class="g" id="g0"></canvas> <canvas height="500" width="500" class="g" id="g23"></canvas> </body> </html>

質問者が選んだベストアンサー

  • ベストアンサー
  • think49
  • ベストアンサー率59% (285/482)
回答No.3

「Windows XP Pro SP3 + Firefox4 + タスクマネージャ」で確認しましたが、リークしているようには見えません。 ページ描画時に一時的にメモリ消費量が増加し、やがて消費量が減ります。タブを閉じればメモリは解放されました。 (<body onload="start()"> を削る、DOCTYPE宣言を加える等、やや変更を加えていますが基本的には掲示されたコードと同じです) http://fiddle.jshell.net/mQpwL/ Firefox の拡張やPluginを全てオフにしても再現しますか? Firefox のバージョンは 4 でしょうか?

armada-compaq
質問者

お礼

ご連絡が遅くなりまして大変申し訳ありませんでした。 質問させて頂いた後で4がリリースされたのを知りまして 4にしてみました。 で、プラグインをオフにするとかなり改善されることがわかりました。ご助言して頂きましてありがとうございました。

その他の回答 (2)

  • yyr446
  • ベストアンサー率65% (870/1330)
回答No.2

OS:Windows XP Pro(SP3) 32bit メモリ:2GB Firefox:3.6.15 で、あえて <body onload="start()"> <body onload="start()"> のまま試したけど、別にリークしてませんね? (Windowタスクマネージャのメモリ使用量とメモリデルタで確認した) 他にも別パターン(ローカル変数化とか)いろいろやったけど、 ご提示のような単純パターンだとリークはしてませんね。

armada-compaq
質問者

お礼

ご連絡が遅くなりまして大変申し訳ありませんでした。 確かにそのようです。 もう少し試行錯誤してみます。 ありがとうございました。

回答No.1

RAMディスク化用のAPPとか常駐Software・Serviceとかによる邪魔の不在証明は可能でしょうか?

armada-compaq
質問者

お礼

ご連絡が遅くなりまして大変申し訳ありませんでした。 完全な証明は出来ないですが、その状態でのみ再現性を確認したのでほぼ間違いないと思います。

関連するQ&A

  • html5canvasの文字枠のずれ

    html5のcanvasで、枠付きの文字列を描画しようとしたら、表示がおかしくなったのですが、理由がわかりません。ブラウザはchromeです。 一部のフォントとサイズのときだけ起きるのですが、それ以外で作れば問題ないのでしょうか。 <canvas id="canvas" width="500" height="500"></canvas> <script type="text/javascript"> var canvas = document.getElementById("canvas"); var ctx = canvas.getContext('2d'); ctx.lineWidth=2; ctx.font = "bold 22px 'MS P明朝'" ctx.strokeStyle = 'rgba(255, 0, 0, 1)'; ctx.fillStyle = 'rgba(0, 0, 0, 1)'; ctx.strokeText("aa0.3", 10, 25); ctx.fillText("aa0.3", 10, 25); </script>

  • javascriptKeydownのcanvas

    こんにちは。 javascriptのkeydownについての質問です。 <script type="text/javascript"> document.onkeydown = draw; function draw() { var hiddenI = document.getElementById("i"); var hiddenJ = document.getElementById("j"); i = hiddenI.value; j = hiddenJ.value; var canvas = document.getElementById('rolate'); if ( ! canvas || ! canvas.getContext ) { return false; } var ctx = canvas.getContext('2d'); ctx.beginPath(); //下ボタン if(event.keyCode == 40){ i = i; j += 1; ctx.lineTo(i, j); ctx.closePath(); ctx.stroke(); } //右ボタン else if(event.keyCode == 39){ i += 1 ; j = j; ctx.lineTo(i, j); ctx.closePath(); ctx.stroke(); } hiddenI.value = i; hiddenJ.value = j; } </script> <body> <h1>Canvas</h1> <canvas id="rolate" width="600" height="600" style="background:#ffffff;"></canvas> <input type="hidden" value="5" id="i"> <input type="hidden" value="5" id="j"> </body> </html> このコードで下ボタンと右ボタンが押されたとき、 決まった5ピクセルずつdrawしようと書きましたが、 キーを押すたびに、値が倍増されます。 どうすれば、5ピクセルずつ値を増やせるのでしょうか。 間違いがある箇所があれば、ご教授お願いします。 よろしくお願いします。

  • Chromeで文字コード(UTF-8)の設定

    ●質問の主旨 文字コードを常時、"utf-8"に設定したいと考えています。 どのように設定すればよいでしょうか? ご存知の方ご教示願います ●質問の補足 下記コードにて、ファイルを実行し、 "Canvasの練習"という文字列と、 青色の正方形をはさんだ黄色の正方形2つが、 表示させるつもりです。 しかし、実際に実行すると、 図形は意図通り描画されますが、文字列が文字化けします。 HTML5のコードにおいて、 <meta charset="utf-8">を <meta charset="s-jis"> に変更すると、文字化けもなくなります。 "utf-8"のコードがすでに大量に用意されているので、 PCの方の認識を"s-jis"から"utf-8"に替えるためにはどうすればよいでしょうか? PCはWindowsVistaで、ブラウザはGoogleChromeです。 ●コード ・HTML5 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Canvasの練習</title> </head> <body> <h1>Canvasの練習</h1> <canvas id="mycanvas" width="400" height="200"> Canvasに対応したブラウザを使ってください。 </canvas> <script src="mycss.js"></script> </body> </html> ・JavaScript // myscript.js window.onload = function() { draw(); } function draw() { var canvas = document.getElementById('mycanvas'); if (!canvas || !canvas.getContext) return false; var ctx = canvas.getContext('2d'); ctx.fillStyle = "yellow"; ctx.save(); ctx.fillRect(0,0,50,50); ctx.fillStyle = "blue"; ctx.fillRect(100,0,50,50); ctx.restore(); ctx.fillRect(200,0,50,50); }

    • ベストアンサー
    • HTML
  • HTML5のcanvasで描画がされない

    HTML5のcanvas要素を使って描画をしようとしたのですが、図形が表示されません。 コードは以下の通りです。 ・index.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>canvasで図形を描く</title> <script type="text/javascript" src="paint.js"></script> </head> <body onLoad="draw()"> <canvas id="mycanvas"width="800" height"800"> </canvas> </body> </html> ・paint.js function draw() { //描画コンテキストの取得 var canvas = document.getElementById('mycanvas'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); ctx.arc(180,150,20,Math.PI*1,Math.PI*2,true); } } このコードでは(180,150)の位置に半径20の円が描画されるはずなのですが、何も表示されませんでした。 どこかコードに誤りがあるのでしょうか? よろしくお願いします。

  • javascriptのcanvasについて

    先日こちらで質問させて頂き、頂いた回答をもとに javascriptのcanvasについて勉強を続けていて、 canvasを2つ重ねたカラーシミュレーションのようなものを作りたいと考えています。 先日教えて頂いた内容をもとに 下記のような記述で2枚目のcanvasの画像を入れ替えることや、 色を変更することは出来ました。 ただ、「進む」ボタンや「戻る」ボタンを押したときに 色がもとの色に戻ってしまうので、色は固定されたまま(この記述でいうと茶色や赤)で 画像を入れ替える方法がわからずにいます。 なにか良い方法はないでしょうか。 <style type="text/css"> .canvas001 { position: absolute; top:100px; left:0px; } .canvas002{ position: absolute; top:100px; left:0px; } </style> <script> onload = function() { image1(); image2(); image3();}; function image1() { var cnvs = document.getElementById('canvas1'); var ctx = cnvs.getContext('2d'); var img = new Image(); img.onload = function() { ctx.drawImage(img, 0, 0); }; img.src = "face.png"; }; function image2() { var cnvs = document.getElementById('canvas2'); var ctx = cnvs.getContext('2d'); var img = new Image(); img.onload = function() { ctx.drawImage(img, 0, 0); }; img.src = "hair1.png"; }; var src = [  'hair1.png',  'hair2.png',  'hair3.png' ]; var currentIndex = 0; var currentImage; function hair(){ var img = currentImage = new Image(); img.onload = function() { if(currentImage === img){ var cnvs = document.getElementById('canvas2'); var ctx = cnvs.getContext('2d'); ctx.clearRect(0, 0, cnvs.offsetWidth, cnvs.offsetHeight); ctx.drawImage(img, 0, 0); } }; img.src = src[currentIndex]; } window.back = function(){ currentIndex = (currentIndex - 1 + src.length) % src.length; hair(); } window.foward = function(){ currentIndex = (currentIndex + 1) % src.length; hair(); } function black(){ var ctx = document.getElementById("canvas2").getContext("2d"); var imagedata = ctx.getImageData(0,0,300,300); var idata = imagedata.data; var num = idata.length; var pix = num / 4; for ( var i = 0 ; i < pix ; i++ ){ var r = idata[ i*4 ]; var g = idata[ i*4 + 1 ]; var b = idata[ i*4 + 2 ]; idata[ i*4 ] = 35; idata[ i*4 + 1 ] = 24; idata[ i*4 + 2 ] = 21; } ctx.putImageData(imagedata,0,0); } function brown(){ var ctx = document.getElementById("canvas2").getContext("2d"); var imagedata = ctx.getImageData(0,0,300,300); var idata = imagedata.data; var num = idata.length; var pix = num / 4; for ( var i = 0 ; i < pix ; i++ ){ var r = idata[ i*4 ]; var g = idata[ i*4 + 1 ]; var b = idata[ i*4 + 2 ]; idata[ i*4 ] = 140; idata[ i*4 + 1 ] = 96; idata[ i*4 + 2 ] = 37; } ctx.putImageData(imagedata,0,0); } function red(){ var ctx = document.getElementById("canvas2").getContext("2d"); var imagedata = ctx.getImageData(0,0,300,300); var idata = imagedata.data; var num = idata.length; var pix = num / 4; for ( var i = 0 ; i < pix ; i++ ){ var r = idata[ i*4 ]; var g = idata[ i*4 + 1 ]; var b = idata[ i*4 + 2 ]; idata[ i*4 ] = 182 ; idata[ i*4 + 1 ] = 0; idata[ i*4 + 2 ] = 5; } ctx.putImageData(imagedata,0,0); } </script> <body> <div> <div class="canvas001"><canvas id="canvas1" height="300"></canvas></div> <div class="canvas002"><canvas id="canvas2" height="300"></canvas></div> </div> <div> <form><div> <INPUT TYPE=button NAME="submit" VALUE="戻る" onClick="back()"> <INPUT TYPE=button NAME="submit" VALUE="進む" onClick="foward()"> </div></form> </div> <img src="btn_black.png" onclick="black()" > <img src="btn_brown.png" onclick="brown()" > <img src="btn_red.png" onclick="red()" > </body>

  • 2つの図を重ねて表示したい

    HTMLもJavaScriptも初心者です。 *.png の図と canvas に書いた図を重ねて表示したいのですが、canvas に書いた図が *.png に隠れて表示されません。 コーディングは次のとおりです。 <html> <title>figures</title> <!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]--> </head> <body> <div id=lyrwall style="position:absolute; left:20px; top:20px;"> <img src=figure.png> </div> <canvas id="canvassample" width="500" height="500"> <script type="text/javascript"> onload = function() { draw(); }; function draw() { var canvas = document.getElementById('canvassample'); if ( ! canvas || ! canvas.getContext ) { return false; } /* 2Dコンテキスト */ var ctx = canvas.getContext('2d'); /* 線を引く */ ctx.beginPath(); ctx.moveTo(20, 20); ctx.lineTo(480, 480); ctx.stroke(); } </script> </canvas> </body> </html> 直線のうち、figure.png と重なる部分が表示されません。表示されるようにするにはどうすればいいのでしょうか。よろしくお願いいたします。

    • ベストアンサー
    • HTML
  • this.ctx is undefined

    皆様のお知恵を拝借いたしたく。 JavaScriptのCANVASでアニメーションを表示したく、 setIntervalで1秒にして、絵を描こうとしたところです。 ところが、以下のプログラムを実施しても、 1秒ごとに、 "ReferenceError: this.ctx is not defined" というエラーが表示されます。エラーの行は下から3行目です。 ですが、一応「テストです」という文字は表示されます。 なぜこのエラーがでるかがわからず・・・・ アドバイスいただけないでしょうか。よろしくおねがいします。 ---------------------------- onload = function() { var layer1 = document.getElementById('layer1'); if ( ! layer1 || ! layer1.getContext ) { return false; } var lay1ctx = layer1.getContext('2d'); setInterval(drawAnime, 1000); drawAnime(layer1, lay1ctx); }; function drawAnime(layer1, lay1ctx){ var SSESocArc = new SocArc(lay1ctx); SSESocArc.drawArc(50); } var SocArc = function (ctx){ this.ctx = ctx; } SocArc.prototype.drawArc = function(){ this.ctx.font = "20px 'Ariel bold'"; ← エラーはココ this.ctx.fillText("テストです", 100, 100); }

  • マウスの座標を表示しようとしたのですが、できません

    //マウス座標の表示・・・ができない? ctx.fillStyle="rgb(0, 0, 0)"; ctx.font = "18px Arial"; //Hello Worldは表示できる ctx.fillText("Hello World!", 20, 250); //この書き方が、おかしい? ctx.fillText("mouseX =" + mouseX, 50, 50); ctx.fillText("mouseY =" + mouseY, 50, 75); Hello World!のようにcanvas上に座標を表示するには、どうすればいいのでしょうか? ちなみに、マウス座標そのものは alert("mouseX = "+mouseX+"\n"+"mouseY = "+mouseY); で確認できたので取得できてます。(添付画像有)

  • 【html5】canvasでの文字の形の透明くりぬ

    html5でcanvasを使用した場合に赤い背景に文字の形に透明くり抜きを行いたいです。 ctx.fillStyle = "rgb(200, 0, 0)"; ctx.fillRect(0, 0, 100, 100); ctx.clearRect(20, 30, 60, 40);  ★ここがRectでなく文字の切り抜きにしたい。 イメージ的にはclearText()というのがあればいいのになぁ、という感じです。 パスをmoveToで文字の形にうごかして、clipしなさーい という回答はご勘弁を(^^;)

    • ベストアンサー
    • HTML
  • IEの「explorercanvas」で作ったCANVASがスクロール

    IEの「explorercanvas」で作ったCANVASがスクロール出来ない HTML5の<canvas>要素を、擬似的に使えるようにした「explorercanvas」↓ http://code.google.com/p/explorercanvas/ ですが、これを使って<canvas>要素を<div>要素の中に配置したんですが、 親の<div>ボックスをスクロールしても、canvasがスクロールされません。 本物の<canvas>要素はちゃんと出来ます。(FirefoxとChromeで確認) 何か代替策ないでしょうか?(canvas内に再描画しろってか..) (実験したコード) <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Canvas Test</title> <style type="text/css"> </style> <!--[if IE]><script src="/jslib/excanvas.js"></script><![endif]--> </head> <body> <p>CANVAS</p> <h2 style="text-align:center">Canvas TEST By HTML5 or IE(excanvas.js)</h2> <div id="hoge" style="width;500px;overflow:scroll;border:solid 1px gray"></div> <p>イメージ</p> <div id="fuga" style="width;500px;overflow:scroll;border:solid 1px gray"></div> <script type="text/javascript"> //CANVASの場合  var container1 = document.getElementById("hoge");  var canvas = document.createElement("canvas");  canvas.width = 2000;  canvas.height = 500;  container1.appendChild(canvas);  if (typeof(G_vmlCanvasManager) != 'undefined')   canvas = G_vmlCanvasManager.initElement(this.canvas);  var ctx = canvas.getContext('2d');  var img = new Image();  img.src = "/image/mio.jpg" + "?" + new Date().getTime();   img.onload = function() {    ctx.drawImage(img,0,0,2000,500);   }  container1.scrollLeft = 500; //imgの場合  var container2 = document.getElementById("fuga");  var img2 = new Image();  img2.src = "/image/yui.jpg" + "?" + new Date().getTime();  img2.style.width="2000px";  img2.style.height="500px";  container2.appendChild(img2);  container2.scrollLeft = 500; </script> </body> </html>

専門家に質問してみよう