【发布时间】:2023-03-13 20:00:01
【问题描述】:
我正在开发一个 C# 库,它将创建大量小对象作为正常操作的一部分(想想编译器中的 AST 节点)。我想以不会影响性能的方式为每个实例分配一个唯一标识符(在程序中是唯一的,而不是全局唯一的)。对象是不可变的,并且可以跨线程共享,因此 id 需要跨线程唯一。
以下是我正在考虑的一些选项:
- 使用静态 int 或 long,并通过调用
Interlocked.Increment()获取每个新 id - 使用
Guid.NewGuid()生成id - 使用带有
[ThreadStatic]属性的静态int 或long 字段,然后从当前线程的ManagedThreadId属性和线程本地计数器的下一个值生成字符串id。
其中一个会比其他的性能更好吗?有没有更好的方法来做到这一点?
谢谢!
编辑:
我运行了一个快速基准测试并得到以下结果:
- 0.19 秒(int 与 long 基本相同)
- 1.1 秒
- 3.5 秒
这似乎强烈指向使用Interlocked。但是,Interlocked 在多线程场景中是否有变慢的风险?
【问题讨论】:
-
在我看来,您的 (1) 是迄今为止解决您提出的问题的最佳方法。 Interlocked.Increment() 是超快的。只要您生成的数量不超过 2^31 个。 ;)
-
我一直使用 CombGuids - 它们基于当前日期/时间,因此除非您的代码每秒产生数千个 id - 几乎不可能发生冲突。有关代码,请参阅此帖子。 stackoverflow.com/questions/665417/…
-
@Jay:嗯,对于只需要在一个程序上的特定运行时唯一的东西来说,这是一个很大的开销。
-
选项1. 既然不需要全局,guid就是浪费资源
-
@MatthewWatson - 看起来很慢,但还不错。在我的机器上,生成一百万个 guid 需要 0.1 秒,生成 100 万个 CombGuid 需要 1 秒。所以它比生成 Guid 慢了大约 10 倍,但它很有用,因为它们几乎肯定是独一无二的。只是把它作为一种选择扔出去!
标签: c# guid thread-local unique-id interlocked-increment