Skip to content

Commit 66dcf1f

Browse files
committed
SPECIALISE functions in Data.Arena
They're overloaded on MonadPrim m => and are called in the hot path of lookup, where using the overloaded version was generating a lot of allocations. The alloc per key in the benchIndexSearches goes from 1369 to 88.9.
1 parent 127bd93 commit 66dcf1f

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

src/Data/Arena.hs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ module Data.Arena (
2020
import Control.DeepSeq (NFData (..))
2121
import Control.Exception (assert)
2222
import Control.Monad.Primitive
23+
import Control.Monad.ST (ST)
2324
import Data.Bits (complement, popCount, (.&.))
2425
import Data.Primitive.ByteArray
2526
import Data.Primitive.MutVar
@@ -59,19 +60,32 @@ type Alignment = Int
5960
blockSize :: Int
6061
blockSize = 0x100000
6162

63+
{-# SPECIALIZE
64+
newBlock :: ST s (Block s)
65+
#-}
66+
{-# SPECIALIZE
67+
newBlock :: IO (Block RealWorld)
68+
#-}
6269
newBlock :: PrimMonad m => m (Block (PrimState m))
6370
newBlock = do
6471
off <- newPrimVar 0
6572
mba <- newAlignedPinnedByteArray blockSize 4096
6673
return (Block off mba)
6774

75+
{-# INLINE withArena #-}
6876
withArena :: PrimMonad m => ArenaManager (PrimState m) -> (Arena (PrimState m) -> m a) -> m a
6977
withArena am f = do
7078
a <- newArena am
7179
x <- f a
7280
closeArena am a
7381
pure x
7482

83+
{-# SPECIALIZE
84+
newArena :: ArenaManager s -> ST s (Arena s)
85+
#-}
86+
{-# SPECIALIZE
87+
newArena :: ArenaManager RealWorld -> IO (Arena RealWorld)
88+
#-}
7589
newArena :: PrimMonad m => ArenaManager (PrimState m) -> m (Arena (PrimState m))
7690
newArena (ArenaManager arenas) = do
7791
marena <- atomicModifyMutVar' arenas $ \case
@@ -86,6 +100,12 @@ newArena (ArenaManager arenas) = do
86100
full <- newMutVar []
87101
return Arena {..}
88102

103+
{-# SPECIALIZE
104+
closeArena :: ArenaManager s -> Arena s -> ST s ()
105+
#-}
106+
{-# SPECIALIZE
107+
closeArena :: ArenaManager RealWorld -> Arena RealWorld -> IO ()
108+
#-}
89109
closeArena :: PrimMonad m => ArenaManager (PrimState m) -> Arena (PrimState m) -> m ()
90110
closeArena (ArenaManager arenas) arena = do
91111
scrambleArena arena
@@ -112,6 +132,12 @@ scrambleBlock (Block _ mba) = do
112132
setByteArray mba 0 size (0x77 :: Word8)
113133
#endif
114134

135+
{-# SPECIALIZE
136+
resetArena :: Arena s -> ST s ()
137+
#-}
138+
{-# SPECIALIZE
139+
resetArena :: Arena RealWorld -> IO ()
140+
#-}
115141
-- | Reset arena, i.e. return used blocks to free list.
116142
resetArena :: PrimMonad m => Arena (PrimState m) -> m ()
117143
resetArena Arena {..} = do
@@ -135,13 +161,19 @@ withUnmanagedArena k = do
135161
mgr <- newArenaManager
136162
withArena mgr k
137163

164+
{-# SPECIALIZE
165+
allocateFromArena :: Arena s -> Size -> Alignment -> ST s (Offset, MutableByteArray s)
166+
#-}
138167
-- | Allocate a slice of mutable byte array from the arena.
139168
allocateFromArena :: PrimMonad m => Arena (PrimState m)-> Size -> Alignment -> m (Offset, MutableByteArray (PrimState m))
140169
allocateFromArena !arena !size !alignment =
141170
assert (popCount alignment == 1) $ -- powers of 2
142171
assert (size <= blockSize) $ -- not too large allocations
143172
allocateFromArena' arena size alignment
144173

174+
{-# SPECIALIZE
175+
allocateFromArena' :: Arena s -> Size -> Alignment -> ST s (Offset, MutableByteArray s)
176+
#-}
145177
-- TODO!? this is not async exception safe
146178
allocateFromArena' :: PrimMonad m => Arena (PrimState m)-> Size -> Alignment -> m (Offset, MutableByteArray (PrimState m))
147179
allocateFromArena' arena@Arena { .. } !size !alignment = do
@@ -173,6 +205,7 @@ allocateFromArena' arena@Arena { .. } !size !alignment = do
173205
-- * go again
174206
allocateFromArena' arena size alignment
175207

208+
{-# SPECIALIZE newBlockWithFree :: MutVar s [Block s] -> ST s (Block s) #-}
176209
-- | Allocate new block, possibly taking it from a free list
177210
newBlockWithFree :: PrimMonad m => MutVar (PrimState m) [Block (PrimState m)] -> m (Block (PrimState m))
178211
newBlockWithFree free = do

0 commit comments

Comments
 (0)