Goのtime packageによるwall clockとmonotonic clockについて
wall clock
とmonotoric clock
とは
現代のコンピューターには少なくとも2つの時間が存在します。1つは時刻の時間
(wall clock)で、もう1つが短調増加の時間
(monotonic clock)です。
wall clock
とはカレンダーに基づいた現在の日付、時刻を指します。一方で、monotonic clock
は常に進み続ける時間を指します(ストップウォッチなどイメージしやすいです)。
wall clock
は通常NTPサーバーと同期されています。これはすなわち、あるマシン上のタイムスタンプは、他のマシン上のタイムスタンプと同じ時刻を指すということです。
monotonic clock
はある時間を起点として時間を短調増加させたものです。(ストップウォッチなら0秒を起点として時間が増えていく)
wall clock
は現在日時がいつなのか調べることに向いており、monotonic clock
は期間を調べることに向いています。
Goでも1.9からこのmonotonic clock
がサポートされるようになりました。
wall clock
とmonotonic clock
time packageのGoのtime packageはTime
構造体を返しますが、この構造体にwall clock
とmonotonic clock
が含まれています。
現在時刻を取得するために以下を実行することが多いかと思います。
time.Now()
こちらはTime
構造体を返します。
Time
構造体にDuration
をAdd()してみましょう。
t0 := time.Now() // 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
t1 := t0.Add(10 * time.minute) // 2009-11-10 23:10:00 +0000 UTC m=+600.000000001
そうすると、現在時刻よりも 10分進んだ別のTime
構造体を得ることができます。
ここで、t0やt1で表示された時間を見てください。横にm = +hogehoge
と表示されています。
これがGoでのmonotonic clock
です。また、それ以前の時刻を表しているのがwall clock
です。
time packageのドキュメントにも以下のように書かれています。
If the time has a monotonic clock reading, the returned string includes a final field “m=±<value>”, where value is the monotonic clock reading formatted as a decimal number of seconds.
ここで、m=+0.000000001
が気になった方もいるかもしれません。これは、プログラムが実行するのにかかった時間なのであまり気にしないでください。
ここで2つの時間の差分を見てみます。
t2 := t1.Sub(t0) // 10m0s
追加した時間だけの差分が表示されました。この差分はmonotonic clock
に基づいて計算されています。
しかし、monotonic clock
はいつでも利用できるわけではありません。monotonic clock
が消えてしまうメソッド(AddDate, Round, Truncateなど)がいくつか存在します。
t3 := t0.Round(0) // 2009-11-10 23:00:00 +0000 UTC
このようにmonotonic clock
が消えた状態でSubメソッドを実行するとmonotonick clock
の代わりにwall clock
で処理が実行されるので気をつけましょう。公式ドキュメントにも以下のように書かれています。
If Times t and u both contain monotonic clock readings, the operations t.After(u), t.Before(u), t.Equal(u), t.Compare(u), and t.Sub(u) are carried out using the monotonic clock readings alone, ignoring the wall clock readings. If either t or u contains no monotonic clock reading, these operations fall back to using the wall clock readings.
まとめ
Goのwall clock
とmonotonic clock
について解説しました。時刻を調べる時にはwall clock
を使い、期間を調べる時にはmonotonic clock
が使用されています。Time
構造体に実装されているメソッドにはmonotonic clock
を消してしまうメソッドも存在するので気を付けましょう。
Discussion