9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ACCESSAdvent Calendar 2016

Day 1

clock_gettime() で高精度なタイムスタンプを取得して表示する

Last updated at Posted at 2016-11-30

katokenです。
本記事はACCESS Advent Calendar 2016の1日目の記事です。

あらまし

株式会社ACCESSでは、PC以外の環境に主にPC向けのOSS Browser製品(WebKit, Chromium)をポートするソリューションを提供しています。

これらの製品をポートする際、よくパフォーマンスが問題になるのですが、プロファイラやデバッガ等は使えない場合が多いです。
その場合、泥臭く根気よくfprintf()で頑張ります。

パフォーマンス測定にはタイムスタンプが必要ですが、遅いとはいえmicro sec 程度の精度のタイムスタンプがほしいですね。
また、画面やファイルに出力する方法も必要です。

そこでタイムスタンプの取得とその表示方法を紹介します。

タイムスタンプの取得

Chromium にあったコードを参考にしました。 struct timespecuint64_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()

9
8
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?