[Haskell-cafe] IORef vs TVar performance: 6 seconds versus 4
minutes
Bertram Felgenhauer
bertram.felgenhauer at googlemail.com
Mon Dec 29 06:28:06 EST 2008
Evan Laforge wrote:
> On Mon, Dec 29, 2008 at 1:15 PM, Ryan Ingram <ryani.spam at gmail.com> wrote:
> > Both readTVar and writeTVar are worse than O(1); they have to look up
> > the TVar in the transaction log to see if you have made local changes
> > to it.
> >
> > Right now it looks like that operation is O(n) where n is the number
> > of TVars accessed by a transaction, so your big transaction which is
> > just accessing a ton of TVars is likely O(n^2).
>
> So this actually brings up a tangential question I've wondered about
> for a while.
>
> The lock-free datastructure paper at
> http://research.microsoft.com/users/Cambridge/simonpj/papers/stm/lock-free-flops06.pdf
> shows lock vs. STM with very similar performance for single processor
> with STM quickly winning on multi-processors.
I have not verified this, but a possible cause is that
Control.Concurrent.QSem isn't efficient if there are many waiters.
It should use two lists for managing the waiters (ala Okasaki).
But why does it manually manage the waiters at all? MVars are fair, in
ghc at least. So this should work:
newtype Sem = Sem (MVar Int) (MVar Int)
newSem :: Int -> IO Sem
newSem initial = liftM2 Sem (newMVar initial) newEmptyMVar
-- | Wait for a unit to become available
waitSem :: Sem -> IO ()
waitSem (Sem sem wakeup) = do
avail' <- modifyMVar sem (\avail -> return (avail-1, avail-1))
when (avail' < 0) $ takeMVar wakeup >>= putMVar sem
-- | Signal that a unit of the 'Sem' is available
signalSem :: Sem -> IO ()
signalSem (Sem sem wakeup) = do
avail <- takeMVar sem
if avail < 0 then putMVar wakeup (avail+1)
else putMVar sem (avail+1)
(I should turn this into a library proposal.)
Bertram
More information about the Haskell-Cafe
mailing list