Haskell中多个线程的高性能唯一时间戳ID

时间:2012-01-29 07:08:36

标签: multithreading performance haskell uniqueidentifier

我有多个线程处理事件。我想为每个事件分配一个纳秒时间戳。但它必须是一个独特的id。因此,在奇怪的情况下,两个事件到达使得它们将被分配相同的时间戳,我希望其中一个增加一纳秒。鉴于实际精度不是纳秒级,就系统的时间戳性质而言,这是可以的。

在一个帖子中,这是一个微不足道的问题。但是跨越多个线程,它变得更具挑战性。性能是绝对关键的,所以天真地同步典型的id生成器类型的东西的想法似乎会阻止太多。

是否有一些方法可以解决这个问题,只需要很少的锁定或没有锁定?

5 个答案:

答案 0 :(得分:2)

为什么不将时间戳和唯一ID生成的问题分开?例如,标准模块Data.Unique可以在IO中提供全局唯一值,并且对于大多数用途而言应该足够快。或者,如果您需要更高级的东西,concurrent-supply包提供了一个高性能的并发唯一ID供应和纯接口。

也就是说,您可以使用POSIX monotonic clock来实现此目的,例如, clock包裹:

import Control.Monad
import qualified System.Posix.Clock as Clock

main :: IO ()
main = replicateM_ 100 $ do
  time <- Clock.getTime Clock.Monotonic
  print (Clock.sec time, Clock.nsec time)

答案 1 :(得分:2)

您可以使用两条信息作为唯一ID吗?如果是,请为每个线程分配一个唯一的id,并为每个事件记录纳秒时间戳和分配时间戳的线程的id。然后问题就减少到你在单线程情况下所做的任何事情,以保证时间戳的唯一性。初始化后根本没有同步。

答案 2 :(得分:1)

您可以使用atomicModifyIORef来实现原子计数器。使用GHC,它是使用原子操作实现的,而不是锁。

import Data.IORef
import System.IO.Unsafe

counter :: IO Int
counter = unsafePerformIO $ newIORef 0

getUnique :: IO Int
getUnique = atomicModifyIORef counter $ \x -> let y = x + 1 in (y, y)

答案 3 :(得分:0)

在基于C语言中,我们通常使用原子计数器来完成此操作 - 不需要锁定。如果您还想要时间戳,那么这将是一个单独的值。我不确定Haskell,因为我不用它写(听起来很有趣)。

答案 4 :(得分:0)