我试图优化试图进行读取,以尽量减少锁争用并发收集。第一遍是用一个链表,这让我只在写锁定,而许多并发的读写可以继续畅通。此使用自定义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来测试这一理论。

有帮助吗?

解决方案

获取和释放锁在每次迭代听起来像一个坏主意 - 因为如果你执行AddRemove当你遍历列表中,将无效的迭代器。 List<T>肯定不会那样的,例如

请问你的使用情况允许呼叫者拿出ReaderWriterLockSlim围绕他们的整个迭代过程,而不是在每个项目的基础是什么?这将是更有效的更稳健。如果没有,你是如何打算处理的并发性问题?如果一个作家比,我已经到了地方早些时候元素添加,简单的执行两次返回相同的元素。相反将与去除发生 - 迭代器将跳过的元素

最后,是.NET 4.0的选项?我知道有一些高度优化的并发集合有...

编辑:我不太清楚你目前的情况是建立手工迭代器而言是什么,但有一点,你可能要调查是使用结构为IEnumerator<T>,并让您的收藏明确声明它返回 - 这是List<T>做什么。它的的意思是使用一个可变的结构,这让小猫哭了世界各地,但如果这是绝对关键的性能,你认为你可以用恐怖生活,它至少值得一试。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top