Investigate use of floating-point arithmetic in I/O Event-handler
I was asked/made aware of some questionable use of floating-point arithmetic in GHC.Event.TimerManager
;
Specifically, I can't explain why getMonotonicTime
first gets a timestamp as Word64
, only to perform a not-necessarily cheap floating-point division, and returns a Double
...
-- | Return monotonic time in seconds, since some unspecified starting point
getMonotonicTime :: IO Double
getMonotonicTime = do w <- getMonotonicNSec
return (fromIntegral w / 1000000000)
foreign import ccall unsafe "getMonotonicNSec"
getMonotonicNSec :: IO Word64
which then gets used e.g. by
updateTimeout :: TimerManager -> TimeoutKey -> Int -> IO ()
updateTimeout mgr (TK key) us = do
now <- getMonotonicTime
let expTime = fromIntegral us / 1000000.0 + now
editTimeouts mgr (Q.adjust (const expTime) key)
wakeManager mgr
Whereas, the priority queue (GHC.Event.PSQ
) then uses Double
s for its priorities...
For correctness and performance reasons, I'd expect the use of fixed-width integers (i.e. Word64
or Int64
) for such codepaths...
Trac metadata
Trac field | Value |
---|---|
Version | 8.0.1 |
Type | Task |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | libraries/base |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | davean |
Operating system | |
Architecture |