C# 用于快速筛选的.net集合(已排序集合)
在分析一个非常慢的方法时,我发现搜索和筛选集合的过程存在滞后 该方法(按顺序)执行以下操作。根据profiler,80%的时间花在步骤1-3上C# 用于快速筛选的.net集合(已排序集合),c#,sorting,collections,c5,C#,Sorting,Collections,C5,在分析一个非常慢的方法时,我发现搜索和筛选集合的过程存在滞后 该方法(按顺序)执行以下操作。根据profiler,80%的时间花在步骤1-3上 从文件中读取已排序的集合并使用Protobuf net(v2)反序列化 从已排序的集合中,根据开始和结束整数(name.RangeFromTo())进行筛选 从同一个已排序的集合中,获取集合的下一个元素(name.Right()) 执行一些任务 .RangeFromTo()为给定范围筛选,例如: [3,7,9,12].RangeFromTo(2,9) -
.RangeFromTo()
)进行筛选Right()
).RangeFromTo()
为给定范围筛选,例如:
[3,7,9,12].RangeFromTo(2,9) -> [3,7,9]
[3,7,9,12].RangeFromTo(2,8) -> [3,7]
[3,7,9,12].RangeFromTo(7,13) -> [7,9,12]
[3,7,9,12].RangeFromTo(13,14) -> [ ]
[3,7,9,12].Right(0) -> 3
[3,7,9,12].Right(3) -> 7
[3,7,9,12].Right(4) -> 7
[3,7,9,12].Right(12) -> null
indexer: [0,0,0,0,1,1,1,1,2,2]
list: [3,7,9]
.Right()
在集合中查找一个元素,并为您提供列表中的下一个元素。如果该元素不存在,它将为您提供最接近右侧的元素。例如:
[3,7,9,12].RangeFromTo(2,9) -> [3,7,9]
[3,7,9,12].RangeFromTo(2,8) -> [3,7]
[3,7,9,12].RangeFromTo(7,13) -> [7,9,12]
[3,7,9,12].RangeFromTo(13,14) -> [ ]
[3,7,9,12].Right(0) -> 3
[3,7,9,12].Right(3) -> 7
[3,7,9,12].Right(4) -> 7
[3,7,9,12].Right(12) -> null
indexer: [0,0,0,0,1,1,1,1,2,2]
list: [3,7,9]
目前该集合正在使用C5()中的SortedArray
。有更适合我使用的收藏吗
注:
第一步。大约占总时间的30%。如果我改用列表,protobuf反序列化的时间实际上减少了40%!我猜当插入SorterDarray时,集合不知道数据已经被排序,并且正在做大量的工作。理想的集合(如果存在)也应该能够绕过它
编辑:
要澄清的是,该列表大约有1000-5000个,有90k个不同的集合!该方法需要加载内存中的所有集合以执行某些业务任务
编辑2:
我在这里添加了一些示例基准:
它将C5中的SortedArray
与.Net中的SortedSet
进行比较。到目前为止,结果如下:
C5 sorted array deserialize took 904
Sorted set deserialize took 1040
C5 sorted array .Right() took 5
Sorted set .Right() took 798 <--- Not sure what happened here...
C5 sorted array .RangeFromTo() took 217
Sorted set .RangeFromTo() took 140
因此,.Right(3)
将是list[indexer[3]+]
代码可以找到
很难相信这种类型的列表在互联网上还没有实现。如果可能的话,我想使用一个库,这样我就不必管理自己的列表
互联网上有这样的实现吗?如果你的数组足够小(可能在10-20个元素以下),那么简单的线性搜索很有可能足够好(这在某种程度上可以通过
列表
在你的测量中速度更快来体现),你可以用Where
/TakeWhile
:
(new[]{3,7,9,12}).Where(i => i>= 2).TakeWhile(i => i <= 9)
(new[]{3,7,9,12}).Where(i=>i>=2).TakeWhile(i=>我可以使用吗?我怀疑这会有同样的“它已经排序”问题,但是如果您先反序列化到列表,然后创建SortedSet
(或SortedArray
)在一个步骤中,这可能会更有效。谢谢,我将首先尝试一下,并将结果发布在这里。@JonSkeet,我已经更新了问题,还添加了SortedSet的测试。SortedSet的性能不如C5实现。不幸的是:(.谢谢,我想使用3,7,9,12不是一个很好的例子。该列表大约有1000-5000个集合,有90k个不同的集合!该方法需要加载内存中的所有集合以执行一些业务任务。@ChiChan-(请使用数组和范围的此项计数更新您的问题)考虑手工编码二进制搜索的第一个元素(<代码>右< /代码>),看看你是否得到更好的结果…还取决于范围是多大,如果你花所有的时间复制大范围作为数组/列表,它可能没有帮助。我更新了这个问题,并添加了一些分支标记代码。(Log(N))因此,要改进这一点,我需要比这更快。我现在确实制作了一个自定义列表,但不知道互联网上是否存在这样的列表。