scrive / pool

A high-performance striped resource pooling implementation for Haskell
Other
18 stars 11 forks source link

Rework resource allocation strategy #36

Open goosedb opened 2 months ago

goosedb commented 2 months ago

I believe we should change the strategy for how resources are allocated across stripes.

The next code allocates 16 resources, while the maximum number specified in the config is nine.

main :: IO ()
main = do
  getNumCapabilities >>= print
  ref <- newIORef @Int 0
  pool <- newPool PoolConfig
    { createResource   = atomicModifyIORef ref (\a -> (a + 1, a)) >>= print
    , freeResource     = const $ atomicModifyIORef ref ((,()) . pred)
    , poolCacheTTL     = 0.5
    , poolMaxResources = 9
    , poolNumStripes   = Just 8
    } 
  hSetBuffering stdout LineBuffering
  forM_ @[] [1..200] \(_ :: Int) -> do
    forkIO $ withResource pool \() -> threadDelay 1000000
  threadDelay 2000000

This can play very badly when you for some reason reduce the number of available resources (for example, your database cannot accept so many connections), as in the example above from 16 to 9, but do not get the expected result.

I suggest adding an interface for manually distributing the number of resources across stripes and accepting not numStripes + maxResources, but something like [Int], where each element of the list is a stripe and the number is the amount of resources on this stripe

arybczak commented 2 months ago

In hindsight looks like the decision of changing "resources per stripe" in the config to "resources across all stripes" was a mistake. I'm not sure how to back off of this now though :confused: