やったことだけ書く備忘録

Server Timing APIを使ってサーバーサイドのベンチマークを手軽にやる

手軽にServer Sideのベンチマークを可視化していく


Chrome65からServer Timing APIのサポートが入ったので手軽にサーバサイドのベンチマークをDevToolから可視化できるようになった。

Server Timingの仕様は下記:
Server Timing

で、nodeのHTTP(HTTPS)モジュール、またはexpressから手軽に使えるnpmを作って公開している。

ysugimoto/server-timing-benchmark

詳しい使い方はREADMEに書いたけど、リクエスト単位で手軽にベンチマークを行える。下記はexpressのサンプル:




const express = require('express');
const 
serverTimingBenchmark = require('server-timing-benchmark');

const 
app express();
app.use(serverTimingBenchmark());

// Handler
app.use((reqres) => {
  
// Create benchmarker
  
const benchmark req.benchmark();

  
// Async function
  
const promiseFunction = () => {
    return new 
Promise(resolve => {
    
setTimeout(() => resolve('response'), 1000);
    });
  };

  
promiseFunction()
    .
then(benchmark('promiseFunction'))
    .
then(data => res.send(data))
  ;
});
app.listen(8888);
 


これでサーバを起動してhttp://localhost:8888にアクセスすると、responseという文字と共にServer-Timingヘッダが付加される。

この状態でDevtoolを開き、Network -> localhost を選択、右ペインのTimingタブを選択すると、promiseFunctionという名前のグラフが確認できる。



req.benchmark()


req.benchmark()で得られるベンチマーク用の関数をコールする度に経過時間が更新され、その差分を溜めていき、最後にヘッダとして送出するため、
必要なタイミングでコールするだけで、その間のベンチマークが得られるようになっている。

また、この関数は




benchmark
(name [,function])
 


のフォーマットとなっていて、引数が一つだけだった場合は引数を一つ受け取ってベンチマークを取り、与えられた引数をそのまま戻す関数を戻す。
…説明がややこしいけど、これはPromiseをChainする時に便利になっていて、上記の例で言えば、




const benchmark req.benchmark();
promiseFunction()
  .
then(benchmark('promiseFunction'))
  .
then(data => res.send(data))
;
 


という感じで、promiseFunction()の実行結果に対してベンチマークを取って、Resolveされたデータはそのまま流すのでChainの途中、または非同期な関数にベンチマークを挟むのに便利になっている。もちろん第二引数をつければそのまま実行結果をベンチマークする:




const benchmark req.benchmark();
benchmark('SyncFunction'someSyncFunction())
 


この2つのパターンでだいたいの計測はできると思う。また、Server-Timingのヘッダは主にデバッグ用途で通常Production環境では送出しなくても良いので、送出を抑制するメソッドも用意している。具体的には、




if (process.env.NODE_ENV === 'production') {
  
req.disableBenchmark();
}
 


という感じにすれば開発環境でだけベンチマーク結果が得られる。



まとめ



サーバーサイドのベンチマークって結構面倒で、ログに吐いたりFluentを挟んで…みたいな手間が必要だったけど、Server Timingを使えばレスポンスのヘッダにそのまま結果を載せて、かつChromeのDevToolで可視化できてとても便利だと思う。

また、実装に当たっては既存のserver-timingのnpmモジュールを参考にさせていただいた。最初はそのまま使ってたけど、Total Timeのヘッダ送出が抑制できなかったりしたのとベンチマーク用途ではなかったので一から書いた次第。

今回はnode用に書いたけど、基本的にHTTPなので他のHTTPサーバを持ってる言語ならどれでも同じようにできる。
この仕様提案したIlyaには感謝ですね。

現場からは以上です。

« 前の記事 次の記事 »

0件のコメント