Skip to content

Rethink the empty array optimization #102

@treeowl

Description

@treeowl

Currently,

createArray 0 _ _ = emptyArray
createArray n x f = runST $ do
  ma <- newArray n x
  f ma
  unsafeFreezeArray ma

This is very straightforward, but it doesn't play particularly well with worker-wrapper. In particular, whenever the array is non-empty, it will allocate both an array and an Array constructor to hold it. Since the empty array is the unusual case, I think we might be better off optimizing the non-empty case more aggressively at its expense:

createArray
  :: Int
  -> a
  -> (forall s. MutableArray s a -> ST s ())
  -> Array a
createArray n x f = Array (createArray# n x f)

createArray#
  :: Int
  -> a
  -> (forall s. MutableArray s a -> ST s ())
  -> Array# a
createArray# 0 _ _ = emptyArray# (# #)
createArray# (I# n) x f = case runRW# $ \s ->
   case newArray# n x s of { (# s', mary# #) ->
   case unST (f (MutableArray mary#)) s' of { (# s'', _ #) ->
   unsafeFreezeArray# mary# s'' }} of (# _, ary# #) -> ary#

unST :: ST s a -> State# s -> (# State# s, a #)
unST (ST f) = f

emptyArray# :: (# #) -> Array# a
emptyArray# _ = case emptyArray of Array ar -> ar
{-# NOINLINE emptyArray# #-}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions