2010/04/06

[javascript]canvas、drawImageの機能の違いによる速度の影響を調べる

このエントリーをはてなブックマークに追加
drawImageは、canvasで画像を使用するためのメソッドです。
パラメータがいろいろあるので、機能の違いから、速度にどのくらい影響するのかを調べてみました。

●drawImageの使い方


使い方は、下記を参照してください。
解りやすい解説があります。

Mozilla Developer Center > Canvas チュートリアル > 画像を使う
https://developer.mozilla.org/ja/Canvas_tutorial/Using_images


一度画像をImageオブジェクトに読み込ませないといけないところは他のグラフィック要素と違って面倒ではありますよね。

●処理時間の計測方法


ベースとなるサイズを320px×480pxとし、50%、100%(原寸)、150%、200%にした画像を用意する。
用意した画像について、下記の4パターンをテストしてみます。
  • ①same:画像を伸縮させて320px×480pxに収まるように配置する

  • ②half:画像を伸縮させて160px×240pxに収まるように配置する

  • ③pick:画像を50%切り出したものを伸縮させて、320px×480pxに収まるように配置する

  • ④fixed:画像を320px×480px切り出したものを、320px×480pxに収まるように配置する


上記それぞれの処理を100回繰り返し使用した時間を計測しました。なお、画像の読み込み時間は処理時間には含みません。
パラメータ次第でいろいろな結果がでそうではあるし、ローカル環境のスペックに依存するので数値に信頼性はありません。ざっくり傾向が分析できればよいぐらいの気持ちでお願いします。

●結果


Y軸の単位はmsです。
ChromeとFireFoxで行いました。


極端な結果になりました。しめたものです。
突出しているところは、処理が重いことを示しています。
なお、グラフになる前の数値データは、テストコードと一緒に後に載せます。

●考察


考察します。
結果から言えること。
  • Chromeは画像の一部を抜粋して伸縮する処理(③pickの処理)がネック。抜粋だけで、伸縮がなければ速度は十分出ている。Chromeの③の結果がなければ、全体的にFFよりも圧倒しています。

  • 小さい画像を扱うほうが処理速度は速い。まあ当然。ただし、Chromeに限っては、あまり倍率の異なる伸縮処理は重くなる。

  • FFは、伸縮処理が加わるとと途端に重くなる。処理速度は元の画像サイズに関わらず、配置後の画像サイズに比例している。

  • 共通していえるのは、伸縮処理は重いということ。元のサイズと、配置サイズを一致させるだけで、処理速度は全然違う。

  • 一番速度がでていたのは、Chromeにて実寸を50%のサイズにして配置する処理(100%の②halfの処理)。100回繰り返しで3ms。


ぐりぐりと触れて、再描画を繰り返さないといけない処理は、伸縮機能を使用しないように工夫するべきだという結果に。

●テストコード


function onLoad()
{
var container = document.getElementById("container");
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var srcList = ["img_050.png", "img_100.png", "img_150.png", "img_200.png"];
var funcList = [ function (img)
{
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, 320, 480);
},
function (img)
{
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, 160, 240);
},
function (img)
{
ctx.drawImage(img, 0, 0, img.width * 0.5, img.height * 0.5, 0, 0, 320, 480);
},
function (img)
{
if (img.width >= 320 && img.height >= 480) {
ctx.drawImage(img, 0, 0, 320, 480, 0, 0, 320, 480);
}
} ];
// 画像を全部読み込む
var imageList = [];
var loadImage = function (src)
{
var img = document.createElement("img");
img.onload = function ()
{
imageList.push(img);
// next
if (srcList.length > 0) {
loadImage(srcList.shift());
}
else {
loadedImage();
}
};
img.src = src;
img.alt = src;
};
loadImage(srcList.shift());
// 画像が全て読み込まれた後に呼び出される
var loadedImage = function ()
{
for (var i = 0; i < funcList.length; i++)
{
var func = funcList[i];
document.write("<p>");
document.write("<b>" + func + "</b><br>");
for (var j = 0; j < imageList.length; j++) {
var img = imageList[j];
test(img, func);
}
document.write("</p>");
}
};
var test = function (img, func)
{
var now = new Date();
for (var i = 0; i < 100; i++) {
func(img);
}
var stamp = new Date() - now;
document.write(img.alt + "=" + stamp + "<br>");
};
}


処理結果。
・Google Chrome4.1
function (img){ ctx.drawImage(img,0,0,img.width,img.height,0,0,320,480); }
img_050.png=25
img_100.png=18
img_150.png=38
img_200.png=50

function (img){ ctx.drawImage(img,0,0,img.width,img.height,0,0,160,240); }
img_050.png=5
img_100.png=3
img_150.png=21
img_200.png=32

function (img){ ctx.drawImage(img,0,0,img.width * 0.5,img.height * 0.5,0,0,320,480); }
img_050.png=271
img_100.png=1067
img_150.png=1491
img_200.png=18

function (img){ if(img.width >= 320 && img.height >=480){ ctx.drawImage(img,0,0,320,480,0,0,320,480); } }
img_050.png=0
img_100.png=19
img_150.png=18
img_200.png=18

・FireFox3.6
function (img) { ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, 320, 480); }
img_050.png=633
img_100.png=20
img_150.png=639
img_200.png=650

function (img) { ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, 160, 240); }
img_050.png=13
img_100.png=192
img_150.png=191
img_200.png=191

function (img) { ctx.drawImage(img, 0, 0, img.width * 0.5, img.height * 0.5, 0, 0, 320, 480); }
img_050.png=632
img_100.png=642
img_150.png=643
img_200.png=20

function (img) { if (img.width >= 320 && img.height >= 480) { ctx.drawImage(img, 0, 0, 320, 480, 0, 0, 320, 480); } }
img_050.png=0
img_100.png=20
img_150.png=20
img_200.png=20

0 件のコメント :

コメントを投稿