katokenです。
本記事はACCESS Advent Calendar 2016の1日目の記事です。
あらまし
株式会社ACCESSでは、PC以外の環境に主にPC向けのOSS Browser製品(WebKit, Chromium)をポートするソリューションを提供しています。
これらの製品をポートする際、よくパフォーマンスが問題になるのですが、プロファイラやデバッガ等は使えない場合が多いです。
その場合、泥臭く根気よくfprintf()
で頑張ります。
パフォーマンス測定にはタイムスタンプが必要ですが、遅いとはいえmicro sec 程度の精度のタイムスタンプがほしいですね。
また、画面やファイルに出力する方法も必要です。
そこでタイムスタンプの取得とその表示方法を紹介します。
タイムスタンプの取得
Chromium にあったコードを参考にしました。 struct timespec
を uint64_t
に変換しています。
#include <stdint.h>
#include <time.h>
uint64_t getTimestamp()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
uint64_t absolute_micro = static_cast<uint64_t>(ts.tv_sec) * 1000000 +
static_cast<uint64_t>(ts.tv_nsec) / 1000;
return absolute_micro;
}
64ビット型、便利ですねえ。
最近は気軽に使えるようになりましたが、昔は対応していないプラットフォームがあるために、ソリューションでの使用は禁止されていました。
64ビット型が使えない時はみんなこんなことをしていました。ちょっと面倒ですね。
Quoted from: Calculate diff of two struct timespec
#include <time.h>
void timespec_diff(struct timespec *start, struct timespec *stop,
struct timespec *result)
{
if ((stop->tv_nsec - start->tv_nsec) < 0) {
result->tv_sec = stop->tv_sec - start->tv_sec - 1;
result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
} else {
result->tv_sec = stop->tv_sec - start->tv_sec;
result->tv_nsec = stop->tv_nsec - start->tv_nsec;
}
return;
}
タイムスタンプの表示
fprintf()
系関数で値を表示するには、%d
などのフォーマット文字列が必要ですね。
しかし、uint64_t
に対応するフォーマット文字列はman fprintf
には出てきてくれません。
じゃあどうするかというと、stdtypes.h
で定義されるマクロを使います。
※ このへんは一本記事がかけるのですが、諸事情でまだ書けずにいます。
uint64_t
に対応するフォーマット文字列はPRIu64
で定義されおり、以下のように書くことで画面にタイムスタンプを出力可能です。
fprintf(stderr, "timestamp: %" PRIu64 "\n", getTimestamp());
終わりに
プロファイラやデバッガがない状況下でタイムスタンプの取得と表示をする方法を紹介しました。
これを任意のポイントに配置することで、区間ごとのパフォーマンスを測定することができるようになります。
(ホントはGoについて書こうと思ったんだけど、時間が取れなくて今やっている業務のテクニック書いちゃいました)
明日もkatokenです。
こんどこそGoネタで行きたいと思います。
参考文献
How to print a int64_t type in C
Calculate diff of two struct timespec
Chromium logging.cc TickCount()