C++
Windows
Linux
C++11
timer

ソフトウェアタイマ性能評価(C++)

概要

ソフトウェアタイマとは,プログラム上で時間を測定するための機能である.主にプログラム内部の処理時間を測定するときに使用される.
C++では11種類以上のソフトウェアタイマが提供されている.さらに,それぞれのタイマは性能が異なっている.
そのため,ソフトウェアタイマを使用するときは性能と照らし合わせながら,適切なソフトウェアタイマを選択しなればならない.

ソフトウェアタイマは主に高速化対応で使用されることが多い.そのため,高速化を行う上ではソフトウェアタイマの知識は必須になる.
高速化対応ではホットスポットを特定することが重要となる.このとき,ホットスポット特定にはソフトウェアタイマとプロファイラツールが使われる.
ここで不適切なソフトウェアタイマを使用するとホットスポットが特定できないこともある.
そのため,ホットスポットでない箇所に対して高速化実装を行うこともあり得るので高速化の効果が少ないという問題が発生することもある.

そこで,C++に対して適切なソフトウェアタイマの選択が行えるようにソフトウェアタイマの性能評価を行った.
性能評価ではソフトウェアタイマの評価指標である分解能とレイテンシーを測定した.
つまり,分解能とレイテンシーを測定することでソフトウェアタイマの性能が明らかになる.

  • 分解能
    • ソフトウェアタイマが測定可能な時間粒度を指す.
  • レイテンシー
    • ソフトウェアタイマの測定遅延時間を指す.

基本的には,分解能とレイテンシーが低いほどソフトウェアタイマの性能が良いことになる.
ソフトウェアタイマの性能を明らかにすることで適切なソフトウェアタイマでの時間測定が行えるようになる.

測定

C++で提供されている代表的なソフトウェアタイマに対して分解能とレイテンシーを測定した.

Windows

WindowsのVisual Studio 2017 communityを用いて11種類のソフトウェアタイマに対して性能評価を行った.

タイマ タイマ対応単位 分解能 レイテンシー 備考
QueryPerformanceCounter ナノ秒 306.431ナノ秒 8.215ナノ秒
chrono::system_clock ナノ秒 307.000ナノ秒 23.434ナノ秒 GetSystemTimePreciseAsFileTimeで実装
timespec_get ナノ秒 307.650ナノ秒 28.503ナノ秒
chrono::steady_clock ナノ秒 307.816ナノ秒 11.405ナノ秒 QueryPerformanceCounterで実装
GetSystemTimePreciseAsFileTime 100ナノ秒 309.200ナノ秒 16.373ナノ秒
clock ミリ秒 1.000ミリ秒 35.940ナノ秒
timeGetTime ミリ秒 1.000ミリ秒 21.120ナノ秒 timeBeginPeriod(1)を使用
GetSystemTimeAsFileTime 100ナノ秒 7.792ミリ秒 2.881ナノ秒
timeGetTime ミリ秒 15.525ミリ秒 15.620ナノ秒 timeBeginPeriod未使用
GetTickCount64 ミリ秒 15.617ミリ秒 2.200ナノ秒
GetTickCount ミリ秒 15.624ミリ秒 2.200ナノ秒
time 1.000秒 20.000ナノ秒
  • 開発環境:Visual Studio 2017 community

スペック

  • OS : Windows 10 pro(64bit)
  • CPU : Intel(R) Core(TM) i7 CPU X 980 @ 3.33GHz
  • メインメモリ : 24.0GB

WIndowsでは,chrono::high_resolution_clockはchrono::steady_clockと同一のタイマとなる.
そのため,chrono::high_resolution_clockの測定結果はchrono::steady_clockの測定結果となる.

分解能評価

ソフトウェアタイマの最小分解能は約306ナノ秒であった.そのため,マイクロ秒単位での測定は可能である.しかし,ナノ秒以下の単位での測定は不可能である.

レイテンシー評価

ソフトウェアタイマの最大レイテンシーは約36ナノ秒であった.
したがって,マイクロ秒単位での測定誤差率は約3.6%になる.つまり,レイテンシーに関してはマイクロ秒単位での測定には影響を与えることはない.
よって,マイクロ秒単位での測定は可能である.

推奨タイマ

性能評価の結果に基づき,Windowsでの推奨ソフトタイマを記載する.

単位 タイマ
ナノ秒 なし
マイクロ秒 QueryPerformanceCounter, timespec_get, chrono
ミリ秒 clock, chrono
time, chrono

C++11以降の場合はchronoを使用すればよい.

Linux(CentOS)

VMWare上でのCentOSに対してg++・Clnagを用いて11種類のソフトウェアタイマに対して性能評価を行った.

g++

タイマ タイマ対応単位 分解能 レイテンシー 備考
clock_gettime(CLOCK_REALTIME) ナノ秒 21.611ナノ秒 23.202ナノ秒
clock_gettime(CLOCK_MONOTONIC) ナノ秒 22.164ナノ秒 22.622ナノ秒
chrono::system_clock ナノ秒 106.594ナノ秒 100.675ナノ秒
chrono::steady_clock ナノ秒 99.778ナノ秒 101.353ナノ秒
clock_gettime(CLOCK_BOOTTIME) ナノ秒 108.257ナノ秒 111.839ナノ秒
clock_gettime(CLOCK_MONOTONIC_RAW) ナノ秒 103.251ナノ秒 112.871ナノ秒
gettimeofday マイクロ秒 1.031マイクロ秒 24.187ナノ秒
clock_gettime(CLOCK_REALTIME_COARSE) ナノ秒 1.884ミリ秒 6.520ナノ秒
clock_gettime(CLOCK_MONOTONIC_COARSE) ナノ秒 1.930ミリ秒 6.240ナノ秒
clock マイクロ秒 10.000ミリ秒 203.000マイクロ秒
time 1.000秒 0.000ナノ秒
  • 開発環境:g++4.8.5

Clang

タイマ タイマ対応単位 分解能 レイテンシー 備考
clock_gettime(CLOCK_REALTIME) ナノ秒 21.644ナノ秒 22.432ナノ秒
clock_gettime(CLOCK_MONOTONIC) ナノ秒 21,635ナノ秒 22.402ナノ秒
chrono::system_clock ナノ秒 98.648ナノ秒 101.116ナノ秒
chrono::steady_clock ナノ秒 101.435ナノ秒 101.699ナノ秒
clock_gettime(CLOCK_BOOTTIME) ナノ秒 105.378ナノ秒 107.169ナノ秒
clock_gettime(CLOCK_MONOTONIC_RAW) ナノ秒 107.175ナノ秒 103.760ナノ秒
gettimeofday マイクロ秒 1.023マイクロ秒 24.678ナノ秒
clock_gettime(CLOCK_REALTIME_COARSE) ナノ秒 1.336ミリ秒 6.340ナノ秒
clock_gettime(CLOCK_MONOTONIC_COARSE) ナノ秒 1.379ミリ秒 6.240ナノ秒
clock マイクロ秒 10.000ミリ秒 198.400マイクロ秒
time 1.000秒 0.000ナノ秒
  • 開発環境:clang3.4.2

スペック

  • OS : CentOS7(VMWare)
  • CPU : Intel(R) Core(TM) i7 CPU X 980 @ 3.33GHz
  • メインメモリ : 24.0GB

Linuxでは,chrono::high_resolution_clockはchrono::system_clockと同一のタイマとなる.
そのため,chrono::high_resolution_clockの測定結果はchrono::steady_clockの測定結果となる.

分解能評価

CentOSのソフトウェアタイマの最小分解能は約21ナノ秒であった.そのため,100ナノ秒での測定は可能である.

レイテンシー評価

clock_gettime(CLOCK_REALTIME), clock_gettime(CLOCK_MONOTONIC)に関しては最大レイテンシーは約23ナノ秒であった.
したがって,100ナノ秒単位での測定誤差率は約22%になる.つまり,レイテンシーに関してはマイクロ秒単位での測定には影響を与えることになる.
しかし,100ナノ単位での測定は可能である.

一方,clock_gettime(CLOCK_REALTIME), clock_gettime(CLOCK_MONOTONIC), clock以外のソフトウェアタイマの最大レイテンシーは約112ナノ秒であった.
したがって,マイクロ秒単位での測定誤差率は約11.2%になる.つまり,レイテンシーに関してはマイクロ秒単位での測定でも影響を与えることになる.
しかし,マイクロ秒単位での測定は可能である.

推奨タイマ

性能評価の結果に基づき,CentOSでの推奨ソフトタイマを記載する.

単位 タイマ
ナノ秒 なし
100ナノ秒 clock_gettime(CLOCK_REALTIME), clock_gettime(CLOCK_MONOTONIC)
マイクロ秒 chrono
ミリ秒 chrono
time, chrono

※clock_gettimeがあるため,gettimeofdayは非推奨

Linux(Ubuntu)

VMWare上でのUbuntuに対してg++・Clnagを用いて11種類のソフトウェアタイマに対して性能評価を行った.

g++

タイマ タイマ対応単位 分解能 レイテンシー 備考
clock_gettime(CLOCK_REALTIME) ナノ秒 17.841ナノ秒 18.476ナノ秒
clock_gettime(CLOCK_MONOTONIC) ナノ秒 18.418ナノ秒 18.102ナノ秒
chrono::system_clock ナノ秒 19.058ナノ秒 19.567ナノ秒
chrono::steady_clock ナノ秒 19.575ナノ秒 19.237ナノ秒
clock_gettime(CLOCK_MONOTONIC_RAW) ナノ秒 59.854ナノ秒 60.303ナノ秒
clock_gettime(CLOCK_BOOTTIME) ナノ秒 66.495ナノ秒 67.145ナノ秒
clock マイクロ秒 1.012マイクロ秒 123.649ナノ秒
gettimeofday マイクロ秒 1.017マイクロ秒 19.775ナノ秒
clock_gettime(CLOCK_REALTIME_COARSE) ナノ秒 4.000ミリ秒 6.160ナノ秒
clock_gettime(CLOCK_MONOTONIC_COARSE) ナノ秒 4.000ミリ秒 6.000ナノ秒
time 1.000秒 0.000ナノ秒
  • 開発環境:g++5.4.0

Clang

タイマ タイマ対応単位 分解能 レイテンシー 備考
clock_gettime(CLOCK_MONOTONIC) ナノ秒 18.159ナノ秒 17.855ナノ秒
chrono::steady_clock ナノ秒 19.986ナノ秒 19.866ナノ秒
chrono::system_clock ナノ秒 21.011ナノ秒 19.588ナノ秒
clock_gettime(CLOCK_REALTIME) ナノ秒 21.106ナノ秒 18.102ナノ秒
clock_gettime(CLOCK_MONOTONIC_RAW) ナノ秒 61.646ナノ秒 60.618ナノ秒
clock_gettime(CLOCK_BOOTTIME) ナノ秒 74.937ナノ秒 68.668ナノ秒
clock マイクロ秒 1.006マイクロ秒 132.856ナノ秒
gettimeofday マイクロ秒 1.018マイクロ秒 24.987ナノ秒
clock_gettime(CLOCK_REALTIME_COARSE) ナノ秒 4.000ミリ秒 6.400ナノ秒
clock_gettime(CLOCK_MONOTONIC_COARSE) ナノ秒 4.000ミリ秒 6.320ナノ秒
time 1.000秒 0.000ナノ秒
  • 開発環境:clang3.8.0

スペック

  • OS : Ubuntu11.04(VMWare)
  • CPU : Intel(R) Core(TM) i7 CPU X 980 @ 3.33GHz
  • メインメモリ : 24.0GB

Linuxでは,chrono::high_resolution_clockはchrono::system_clockと同一のタイマとなる.
そのため,chrono::high_resolution_clockの測定結果はchrono::steady_clockの測定結果となる.

分解能評価

Ubuntuのソフトウェアタイマの最小分解能は約17ナノ秒であった.そのため,100ナノ秒での測定は可能である.

レイテンシー評価

clock_gettime(CLOCK_REALTIME), clock_gettime(CLOCK_MONOTONIC), chrono::system_clock, chrono::steady_clockに関しては最大レイテンシーは約19ナノ秒であった.
したがって,100ナノ秒単位での測定誤差率は約19%になる.つまり,レイテンシーに関してはマイクロ秒単位での測定には影響を与えることになる.
しかし,100ナノ単位での測定は可能である.

一方,上記以外のソフトウェアタイマの最大レイテンシーは約132ナノ秒であった.
したがって,マイクロ秒単位での測定誤差率は約13.2%になる.つまり,レイテンシーに関してはマイクロ秒単位での測定でも影響を与えることになる.
しかし,マイクロ秒単位での測定は可能である.

推奨タイマ

性能評価の結果に基づき,Ubuntuでの推奨ソフトタイマを記載する.

単位 タイマ
ナノ秒 なし
100ナノ秒 clock_gettime(CLOCK_REALTIME), clock_gettime(CLOCK_MONOTONIC), chrono
マイクロ秒 chrono
ミリ秒 chrono
time, chrono

※clock_gettimeがあるため,gettimeofdayは非推奨

C++11以降の場合はchronoを使用すればよい.

参考文献

  1. Optimized C++ ―最適化、高速化のためのプログラミングテクニック, Kurt Guntheroth (著), 島 敏博 (監修), 黒川 利明 (翻訳), オライリージャパン, 2017年2月.
  2. 碧色工房, https://www.mm2d.net/main/
  3. 性能評価プログラム, https://github.com/lambda-classic/TimeEvaluation