正在寻找的IEnumerable / IEnumerator的一个更快的实现
-
20-09-2019 - |
题
我试图优化试图进行读取,以尽量减少锁争用并发收集。第一遍是用一个链表,这让我只在写锁定,而许多并发的读写可以继续畅通。此使用自定义IEnumerator
至产量下一个链接值。一旦我开始在收集比较迭代纯List<T>
我发现我实现一半左右的速度(用于在1 * M *项目的集合from x in c select x
,我得到的 24MS 作为List<T>
和 49ms 作为我的集合)。
所以我想我会使用一个ReaderWriteLockSlim
和牺牲一点争上读取,所以我可以使用List<T>
作为我的内部存储。因为我要捕捉迭代开始读锁和释放完成后,我第一次做了产量图案为我IEnumerable
,的foreach 的荷兰国际集团通过内部List<T>
。现在我是越来越只的 66ms 强>
我在偷看什么列表实际上做了,它使用T[]
的内部存储器和向前移动索引并返回当前索引值自定义IEnumerator
。现在,手动使用T[]
作为存储装置,更大量的维护工作,但第w ,我在追求微秒。
然而,即使模仿IEnumerator
阵列上移动所述索引,I能做的最好的为约的〜38MS 即可。那么是什么原因List<T>
它的秘密武器或可替代什么是一个迭代器更快的实现?
更新:原来我的主要罪魁祸首速度正在运行调试编译,而List<T>
显然是一个版本的编译。在释放我的实现仍是一个头发比List<T>
慢,altough单声道它现在更快。
另外一个建议,我从一个朋友得到的是,BCL更快,因为它在GAC,因此可以得到由系统预编译。将不得不把我的测试在GAC来测试这一理论。
解决方案
获取和释放锁在每次迭代听起来像一个坏主意 - 因为如果你执行Add
或Remove
当你遍历列表中,将无效的迭代器。 List<T>
肯定不会那样的,例如
请问你的使用情况允许呼叫者拿出ReaderWriterLockSlim
围绕他们的整个迭代过程,而不是在每个项目的基础是什么?这将是更有效的和更稳健。如果没有,你是如何打算处理的并发性问题?如果一个作家比,我已经到了地方早些时候元素添加,简单的执行两次返回相同的元素。相反将与去除发生 - 迭代器将跳过的元素
最后,是.NET 4.0的选项?我知道有一些高度优化的并发集合有...
编辑:我不太清楚你目前的情况是建立手工迭代器而言是什么,但有一点,你可能要调查是使用结构为IEnumerator<T>
,并让您的收藏明确声明它返回 - 这是List<T>
做什么。它的不的意思是使用一个可变的结构,这让小猫哭了世界各地,但如果这是绝对关键的性能,你认为你可以用恐怖生活,它至少值得一试。