Unsafe version of writeTVar

Viewed 80

I'm using a list of TVars that are accessed by multiple threads. However, there is one performance-critical section in my code that reads as follows:

 sequence [ atomically $ writeTVar tvar1 someValue | tvar1 <- listOfTVars ]

It is guaranteed that, at the time when this code is reached, no other thread will be accessing any of the TVars in listOfTVars until sequence has completed, neither by reading nor writing.

Does GHC expose any primitives that would allow me to "unsafely" perform these value updates? My goal would be to do this faster without going through the STM-overhead of committing a transaction for each of them. In other words, I don't need the atomicity that STM provides for writeTVar; Instead, I would just need a fast way to update the values stored in the TVars.

1 Answers

Looking around I do not see any exposed primitives.

The documentation says you can use unsafePerformIO with atomically, but warns that it may subvert some of the guarantees that it offers: Control.Monad.STM.atomically. Apparently unsafeDupablePerformIO has better performance than unsafePerformIO, but more caveats. If it is performance critical it is worth benchmarking to see if these offer any performance advantages.

import Control.Concurrent.STM.TVar
import Control.Monad.STM
import Control.Monad
import System.IO.Unsafe

t1 <- newTVarIO "Hello"
t2 <- newTVarIO "Goodbye"
unsafeDupablePerformIO $ sequence $ (\t -> atomically $ writeTVar t "Hola") <$>  [t1,t2] 
unsafeDupablePerformIO $ sequence $ (putStrLn <=< readTVarIO) <$> [t1,t2]
Related