Skip to content

Commit 254efa3

Browse files
committed
Make pollEvent not allocate unnecessarily (#178)
Just to summarize the numbers below for future reference: > let timeToPoll = 11 * 1e-6 -- from criterion > let bytesPerPoll = 36802144/100000 -- from weigh > let pollsPerSec = 1/timeToPoll > let bytesPerSecond = bytesPerPoll * pollsPerSec > pollsPerSec 90909.09090909091 > printf "%f" (pollsPerSec * bytesPerPoll) 33456494.545454547 So that's 90,909 polls and 33.5MB per second of allocations. That's consistent with the below findings. The GC count for 100,000 polls (36.8MB) is 35 GCs, so that's roughly 1 GC per 1MB which corresponds to GHC's default GC settings. Before: Case Allocated GCs pollEvents 10 4,632 0 pollEvents 100 38,416 0 pollEvents 1000 369,112 0 pollEvents 10000 3,680,088 3 pollEvents 100000 36,802,144 35 benchmarking pollEvents/orig time 11.43 μs (11.37 μs .. 11.49 μs) 1.000 R² (1.000 R² .. 1.000 R²) mean 11.41 μs (11.37 μs .. 11.48 μs) std dev 167.3 ns (122.4 ns .. 274.7 ns) variance introduced by outliers: 11% (moderately inflated) After Case Allocated GCs pollEvents 10 1,400 0 pollEvents 100 1,400 0 pollEvents 1000 1,400 0 pollEvents 10000 1,400 0 pollEvents 100000 1,400 0 benchmarking pollEvents/check time 11.05 μs (11.00 μs .. 11.11 μs) 1.000 R² (0.999 R² .. 1.000 R²) mean 11.04 μs (10.99 μs .. 11.13 μs) std dev 216.5 ns (154.8 ns .. 296.8 ns) variance introduced by outliers: 19% (moderately inflated)
1 parent b61f9b1 commit 254efa3

File tree

1 file changed

+12
-5
lines changed

1 file changed

+12
-5
lines changed

src/SDL/Event.hs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -746,11 +746,18 @@ convertRaw (Raw.UnknownEvent t ts) =
746746

747747
-- | Poll for currently pending events. You can only call this function in the thread that set the video mode.
748748
pollEvent :: MonadIO m => m (Maybe Event)
749-
pollEvent = liftIO $ alloca $ \e -> do
750-
n <- Raw.pollEvent e
751-
if n == 0
752-
then return Nothing
753-
else fmap Just (peek e >>= convertRaw)
749+
pollEvent =
750+
liftIO $ do
751+
n <- Raw.pollEvent nullPtr
752+
-- We use NULL first to check if there's an event.
753+
if n == 0
754+
then return Nothing
755+
else alloca $ \e -> do
756+
n <- Raw.pollEvent e
757+
-- Checking 0 again doesn't hurt and it's good to be safe.
758+
if n == 0
759+
then return Nothing
760+
else fmap Just (peek e >>= convertRaw)
754761

755762
-- | Clear the event queue by polling for all pending events.
756763
pollEvents :: (Functor m, MonadIO m) => m [Event]

0 commit comments

Comments
 (0)