我正在尝试优化一个并发集合,以尽量减少读取的锁争用。第一遍是使用链表,它允许我只锁定写入,而许多同时读取可以继续畅通无阻。这使用了一个自定义IEnumerator
来产生下一个链接值。一旦我开始将集合上的迭代与普通进行比较,List<T>
我注意到我的实现速度大约是原来的一半(对于from x in c select x
1*m* 项目的集合,我的集合分别为24 毫秒List<T>
和49 毫秒)。
所以我想我会使用 aReaderWriteLockSlim
并在读取上牺牲一点争用,这样我就可以使用 aList<T>
作为我的内部存储。由于我必须在迭代开始时捕获读锁并在完成时释放它,所以我首先为 my IEnumerable
, foreach做了一个yield模式List<T>
。现在我只有66ms。
我查看了 List 实际做了什么,它使用了一个内部存储T[]
和一个自定义IEnumerator
来向前移动索引并返回当前索引值。现在,手动T[]
用作存储意味着更多的维护工作,但是,我正在追逐微秒。
然而,即使模仿IEnumerator
移动数组上的索引,我能做的最好的事情也是大约~38ms。那么是什么提供了List<T>
它的秘诀,或者说什么是迭代器的更快实现呢?
更新:原来我的主要速度罪魁祸首是运行调试编译,而List<T>
显然是发布编译。在发布时,我的实现仍然比 . 慢一点List<T>
,尽管在单声道上它现在更快。
我从朋友那里得到的另一个建议是 BCL 更快,因为它在 GAC 中,因此可以由系统预编译。将不得不在 GAC 中进行测试以测试该理论。