ベンチマークの結果をd3.jsで可視化してみた

投稿日:

もういくつ寝るとお正月。今年もあっという間に年末になりました。
年末になると今年も色々あったなぁなんて思い出にふけるわけですが、色々という言葉にほとんどの出来事は濃縮されてしまって、過ぎたことは本当にどうでもよくなりますね。
こうして人は年をとっていくんだなと思います。

というわけで、以前書いた

を使ってベンチマークの結果をd3.jsで可視化してみました。
サンプルは こちら です。

仕組みとしては、

  • shimabox/SMBBenchmark でベンチマークの結果を配列で出力
  • shimabox/SMBArrayto で受け取った配列を json※ で出力
  • d3.jsで受け取った json※ をつかってグラフを描画

※ csvでもtsvでもよいです

という流れになります。

ソース

例として、isset(), in_array(), ランダムな計測(10個) の計測結果をグラフ化してみます。

php

こんな感じで計測結果を保存しておきます(sample.json)。

<?php
// vendor/autoload.php
require_once 'your/path/to/vendor/autoload.php';

// a 〜 z までの文字
$range = range('a', 'z');

// isset()用
// ['a' => 1, 'b' => 1, ..., 'z' => 1]
$list1 = array();
foreach ($range as $c){
    $list1[$c] = 1;
}

// in_array()用
// ['a', 'b', ..., 'z']
$list2 = array();
foreach ($range as $c){
    $list2[] = $c;
}

// 計測開始
$bm = SMB\Benchmark::getInstance();

$bm->measure(
    function () use ($list1) {
        for($i=0;$i<5000;$i++) {
            isset($list1['z']);
        }
    },
    [],
    'isset()', // ラベル名
    100 // 100回繰り返す
)->measure(
    function () use ($list2) {
        for($i=0;$i<5000;$i++) {
            in_array('z', $list2);
        }
    },
    [],
    'in_array()',
    100
);

// これは適当
for($i=1;$i<=10;$i++){
    $s = rand(1000, 20000);
    $bm->measure(
        function () use ($s) {
            usleep($s);
        },
        [],
        'bench'.$i
    );
}

// json
$jsonWriter = SMB\Arrayto\Json::Factory()->getWriter();
$bm->write($jsonWriter, 'sample.json');

// csvの場合
// $csvWriter = SMB\Arrayto\Csv::Factory()
//                 ->getWriter()
//                 ->setToConvert(false) // UTF-8, LF
//                 ->setHeader(['label', 'benchmark'])
//                 ;
// $bm->write($csvWriter, 'sample.csv');

// tsvの場合
// $tsvWriter = SMB\Arrayto\Tsv::Factory()
//                 ->getWriter()
//                 ->setToConvert(false) // UTF-8, LF
//                 ->setHeader(['label', 'benchmark'])
//                 ;
// $bm->write($tsvWriter, 'sample.tsv');

XHR

こんな感じでoutputterを使えばajaxでも利用できます。

// json
$jsonOutputter = SMB\Arrayto\Json::Factory()->getOutputter();
$bm->output($jsonOutputter);
exit;

// csvの場合
$csvOutputter = SMB\Arrayto\Csv::Factory()
                   ->getOutputter()
                   ->setToConvert(false) // UTF-8, LF
                   ->setHeader(['label', 'benchmark']);
$bm->output($csvOutputter);
exit;

d3.js

こんな感じで、上記で保存したsample.jsonを読み込んでグラフを描画します。

ポイント

// x軸ラベルのラッパー
var xAxisWrapperObj = parent.append('foreignObject')
                            .attr("width", x.rangeBand())
                            .attr("height", "100%")
                            .attr("x", function () { // 左揃えにする
                              return -(x.rangeBand() / 2);
                            })
                            .attr("y", "10")
                            ;

ラベル(X軸の部分)が長くなっても自動で折り返されるように、ラベル部分はforeignObjectを使ってHTMLを描画しています。

ただし、このforeignObjectはIEだと未対応?の様なので表示されません。
(Chrome, Safari, FireFox で見てみてください)

最後に

というわけで、ベンチマークの結果をd3.jsを使って描画してみました。
今時こんなアナログな手法を使う場面があるか分かりませんが、もし良かったら試してみてください。

それではよいお年を。

参考にさせて頂きました

作成者: shimabox

Web系のプログラマをやっています。 なるべく楽しく生きていきたい。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください