memorypool- basic memory pool outside of haskell heap/GC

Safe HaskellNone




A very basic memory pool imlemented in haskell.

The core idea is that the pool allocates large chunks of memory that are some power-of-two factor (e.g. 256) of some base size (e.g. 10k). The user of the pool allocates chunks of a power-of-two factor of the base size (i.e. 10k, 20k, 40k, ..). This scheme avoids fragmentation due to weirdly-sized holes, but keep in mind that no compaction takes place, so this kind of fragmentation must be worked around manually if necessary.

The pool internally allocates memory on the C heap, i.e. outside of any haskell/GC heap.

Uses a buddy allocation strategy internally.



data Pool Source

Stateful pool object


create Source


:: CSize

base size.

-> CSize

block exponent; each internal block holds (2**block_exp) * base_size. Must be at least 1.

-> IO Pool 

Create an empty pool. A pool internally allocates several relatively large blocks via malloc and returns chunks of these when requested via allocate.

Note that the rts does not "see" these allocations in any way. I.e. memory allocated in the pool does not count towards heap space in the rts and is not captured by heap profiling.

allocate Source


:: Pool

pool to allocate in

-> CSize

number of bytes to allocate.

-> IO (IO (), Ptr a)

the ptr to the memory allocated in the pool, plus a deallaction action.

Allocate memory inside the specified pool. The amount allocated is rounded up to the next power-of-two multiple of the base size.

The number of bytes to allocated is limited in both directions: The minimum amount is 1 (0 is an error). The maximum is the number of a bytes in a block as specified by the arguments to create.

No deallocation happens unless the provided deallocation action is executed. (See allocateForeign for a more automatic variant of this function.)

The deallocation action must not be called more than once.

allocateForeign Source


:: Pool

pool to allocate in

-> CSize

number of bytes to allocate.

-> IO (ForeignPtr a) 

Similar to allocate, but performs the deallocation automatically as a finalizer on the returned ForeignPtr. This may lead to (arbitrary) delays between dropping of the reference and actual freeing of pool memory, but is much more convenient on usage side.

low-level and debugging functions

data PoolData Source

Internal pool type

debugShowPoolFillsData :: PoolData -> String Source

Return a visual representation of allocation inside the pool. Both distribution of blocks and fragmentation inside each block is displayed.

debugTracePoolFills :: Pool -> IO () Source

Prints a visual representation of allocation inside the pool to stderr. Both distribution of blocks and fragmentation inside each block is displayed.

getPtrFragmentation :: PoolData -> Ptr a -> Maybe Float Source

if Ptr is not allocated in this pool, returns Nothing. Otherwise returns a rather rough estimate of the usage for the block that the pointer is allocated in. For example if it returns (Just 0.75), at least 25% of the block is free (the other bound should be.. 50% i think. But the error depends in a nontrivial fashion on the value. Use unsafeGetPoolDataSnapshot to obtain the first argument.

unsafeGetPoolDataSnapshot :: Pool -> IO PoolData Source

Retrieve a snapshot of the internal data of a pool. This currently exists soly as an argument to getPtrFragmentation.