C# 可以为LINQ使用自定义内存分配器吗?

C# 可以为LINQ使用自定义内存分配器吗?,c#,.net,linq,memory-management,C#,.net,Linq,Memory Management,有没有办法为LINQ使用自定义内存分配器 例如,当我打电话时: someCollection.Where(x).SelectMany(y).ToList(); 像ToList()或OrderBy()这样的方法总是会创建一个新数组,因此会发生大量GC。 使用自定义分配器,我可以始终使用相同的列表,每次都会清除并重新填充该列表。Iam意识到重用缓冲区可能会导致重入问题 背景是,我的应用程序是一个游戏,GC意味着口吃。 请不要告诉我“用C++代替”或“不使用LINQ”,我知道:< P>(尽管你不建议

有没有办法为LINQ使用自定义内存分配器

例如,当我打电话时:

someCollection.Where(x).SelectMany(y).ToList();
ToList()
OrderBy()
这样的方法总是会创建一个新数组,因此会发生大量GC。 使用自定义分配器,我可以始终使用相同的列表,每次都会清除并重新填充该列表。Iam意识到重用缓冲区可能会导致重入问题

背景是,我的应用程序是一个游戏,GC意味着口吃。 请不要告诉我“用C++代替”或“不使用LINQ”,我知道:

< P>(尽管你不建议反对它,我瘦这个答案可以帮助社区)< /P> LINQ是构建在CLR之上的工具,因此它使用CLR分配器,并且不能更改。 您可以稍微调整一下,例如,配置是否应该将GC循环卸载到后台线程,但不能再进一步了

LINQ的目的是简单地为某类问题编写代码,牺牲选择每个构建块实现的自由(这就是我们通常选择LINQ的原因)

然而,根据场景的不同,LINQ不能成为您最好的朋友,因为它的设计选择可能会与您的设计选择产生冲突。 如果在评测代码之后,发现存在严重的性能问题,则应首先尝试确定是否可以隔离某些LINQ方法中的瓶颈,并查看是否可以通过扩展方法滚动自己的实现。 当然,当you是主要调用方时,此选项是可行的,除非您成功地推出了
IEnumerable
complaint的内容。您需要非常幸运,因为您的实现应该遵守LINQ规则。特别是,由于无法控制对象的操作方式,因此无法在自己的代码中执行优化。 关闭和延迟执行对您不利

否则,评论中建议的是唯一可行的选择:避免将LINQ用于特定任务

离开LINQ的原因是,它不是解决您需要的性能约束问题的正确工具。 此外,如注释中所述,(ab)使用lambda表达式显著增加了内存压力,因为创建了支持对象来实现闭包


我们的性能问题与您的类似,我们必须重写某些慢路径。在其他(极少数)情况下,通过
AddRange
预分配列表和加载结果会有所帮助。

但答案是“不要使用LINQ”,除非您找到一种肮脏的方法来交换LINQ方法的实现与其他方法。您也许可以创建自己的扩展方法
topoleArray()
,该方法模仿Linq方法
Enumerable.ToArray()
(假设
。ToArray()
对您来说确实是个问题)。(注意:是的,有一些肮脏的方法可以用另一种方法的实现来代替一种方法的实现,但是这样做会导致更可怕的问题,而不是从这些肮脏的恶作剧中获得的任何潜在好处)扩展方法
.FillList(preallocatedList)怎么样?或者干脆
myList.AddRange()运行内存配置文件是否表明收集压力的主要原因是查询?这是有道理的;在Roslyn的早期尝试中,我们的分析表明我在过载解析中使用LINQ是造成压力的一个重要因素,因此我们重写了它以避免使用LINQ并使用池策略。但我们是在制定了一套性能测试方案之后这样做的,该方案让我们确定问题的规模和干预措施的效果。如果您试图消除压力,但您尚未首先创建一套性能套件,以明确衡量压力并将其归因于特定的分配模式,试图解决这个问题还为时过早。您将浪费大量宝贵的时间来寻找不相关的分配。此外,请记住,LINQ对内存问题的一个重要贡献是,LINQ鼓励lambdas,后者创建闭包,从而以令人惊讶的方式延长对象生命周期。很容易在某个地方意外地关闭
,并在序列存在时保持对象网络的活动状态。在这些场景中,
ToList
可以使事情变得更好,而不是更糟,因为查询被实现为一个不包含闭包的对象。优化内存使用需要一种整体的实证分析方法。