Don't use floating-point for time
Opened this issue · 0 comments
The timer API in swanstation correctly stores time as an integer:
swanstation/src/common/timer.h
Line 9 in 7a27436
But then provides APIs to convert it to and from floating-point:
swanstation/src/common/timer.h
Lines 14 to 17 in 7a27436
The floating-point API is used in the code, here's one example:
swanstation/src/core/gpu_backend.cpp
Lines 213 to 214 in 7a27436
This article has a mostly good writeup on why storing time in floating-point is bad:
https://randomascii.wordpress.com/2012/02/13/dont-store-that-in-a-float/
Keep in mind that most of the examples in the article use the float
type in the context of game dev, which is typically single-precision floating-point IEEE754 (32-bit float). Swanstation uses double
which is typically double-precision IEEE754 (64-bit float), so things are not as extreme as in the examples there.
The article also suggests using double
as a possible fix, however, that isn't good enough for swanstation. For instance, it appears CLOCK_MONOTONIC is implemented as the time since boot at least on NetBSD and OpenBSD. I can't seem to find the relevant code on FreeBSD or Linux, but they should be similar. Considering every integer between -(2^53)
and 2^53
can be stored without rounding in a 64-bit IEEE754 float, the time is acquired via CLOCK_MONOTONIC on Unix, and the unit is nanoseconds:
swanstation/src/common/timer.cpp
Lines 59 to 60 in 7a27436
It takes
2^53 / 1000000000
seconds or 104 days of uptime for any conversion of Common::Timer
to double
to lose precision to rounding.
The separate Windows and Unix code can be mostly unified too, only GetValue()
needs to be different.