Skip to content

Commit 6be948a

Browse files
authored
Merge pull request #330 from IntersectMBO/dcoutts/arena-specialise
Two micro-optimisations
2 parents 320473e + 74ba6c7 commit 6be948a

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
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

src/Database/LSMTree/Internal/IndexCompact.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,19 +360,19 @@ import Database.LSMTree.Internal.Vector
360360
data IndexCompact = IndexCompact {
361361
-- | \(P\): Maps a page @i@ to the 64-bit slice of primary bits of its
362362
-- minimum key.
363-
icPrimary :: !(VU.Vector Word64)
363+
icPrimary :: {-# UNPACK #-} !(VU.Vector Word64)
364364
-- | \(C\): A clash on page @i@ means that the primary bits of the minimum
365365
-- key on that page aren't sufficient to decide whether a search for a key
366366
-- should continue left or right of the page.
367-
, icClashes :: !(VU.Vector Bit)
367+
, icClashes :: {-# UNPACK #-} !(VU.Vector Bit)
368368
-- | \(TB\): Maps a full minimum key to the page @i@ that contains it, but
369369
-- only if there is a clash on page @i@.
370370
, icTieBreaker :: !(Map (Unsliced SerialisedKey) PageNo)
371371
-- | \(LTP\): Record of larger-than-page values. Given a span of pages for
372372
-- the larger-than-page value, the first page will map to 'False', and the
373373
-- remainder of the pages will be set to 'True'. Regular pages default to
374374
-- 'False'.
375-
, icLargerThanPage :: !(VU.Vector Bit)
375+
, icLargerThanPage :: {-# UNPACK #-} !(VU.Vector Bit)
376376
}
377377
deriving stock (Show, Eq)
378378

0 commit comments

Comments
 (0)