System.Array.IndexOf 分配内存
Posted
技术标签:
【中文标题】System.Array.IndexOf 分配内存【英文标题】:System.Array.IndexOf allocates memory 【发布时间】:2019-02-13 11:31:47 【问题描述】:我一直在分析我的代码,发现System.Array.IndexOf
分配了相当多的内存。我一直在试图找出这是怎么发生的。
public struct LRItem
public ProductionRule Rule get; // ProductionRule is a class
public int Position get;
// ...
public List<LRItem> Items get; = new List<LRItem>();
// ...
public bool Add(LRItem item)
if (Items.Contains(item)) return false;
Items.Add(item);
return true;
我假设IndexOf
由Items.Contains
调用,因为我认为Items.Add
没有任何业务检查索引。我试过查看reference source 和.NET Core source 但无济于事。这是 VS 分析器中的错误吗?这个函数实际上是在分配内存吗?我能以某种方式优化我的代码吗?
【问题讨论】:
在您看到 IndexOf 中的内存分配发生之前,您是否可能将列表的容量设置为某个较高的值? 检查LRItem
是如何实际实现Equals
的。罪魁祸首很可能就在那里。
另外,如果您需要一个强制唯一性的集合,请使用已经提供该功能的类型。
@elgonzo 不,我不会在任何地方设置或更改容量
@InBetween 我没有 LRItem 的自定义 Equals
【参考方案1】:
您的对象不是像 text 或 number 这样的简单数据类型,所以 检查复杂对象的每个项目可能是内存杀手。
例如,如果您的对象包含图像、文本、数字和...每个数据都应该进行相似性处理。
我建议您不要使用 IndexOf 或 Contains 函数,因为它们 可能比较对象中的每一个数据。
只需手动执行,使用单个 foreach 循环并只需比较您的密钥 数据(用户 ID、对象 ID、姓名、家庭、日期、时间或 ...)。
【讨论】:
好吧,再读一遍问题,然后看看你的答案。这是一些关于避免使用 IndexOf 以提高性能但与内存无关的有问题的建议。 是的,你是对的,在问题的最后,他要求优化!所以现在阅读我的答案,包含对复杂对象的调用导致过多的数据比较,从而导致时间、内存和性能问题。谢谢。 “你的对象不是文本或数字这样的简单数据类型”我认为你指的是值类型,而结构是值类型【参考方案2】:我知道这可能有点晚了,但万一其他人有同样的问题......
当List<T>.Contains(...)
被调用时,它使用EqualityComparer<T>.Default
来比较各个项目以查找您传入的内容[1]。 docs 这么说EqualityComparer<T>.Default
:
Default 属性检查类型 T 是否实现了 System.IEquatable 接口,如果是,则返回使用该实现的 EqualityComparer。否则,它返回一个使用 T 提供的 Object.Equals 和 Object.GetHashCode 覆盖的 EqualityComparer。
由于您的LRItem
没有 实现IEquatable<T>
,因此它回退到使用Object.Equals(object, object)
。而且因为LRItem
是一个结构,所以它最终会被装箱为object
,因此它可以传递给Object.Equals(...)
,这是分配的来源。
解决此问题的简单方法是从文档中获取提示并实现 IEquatable<T>
接口:
public struct LRItem : IEquatable<LRItem>
// ...
public bool Equals(LRItem other)
// Implement this
return true;
现在这将导致 EqualityComparer<T>.Default
返回一个专门的比较器,该比较器不需要对您的 LRItem
结构进行装箱,从而避免分配。
[1] 我不确定自从提出这个问题后是否发生了变化(或者可能是 .net 框架与核心差异之类的),但 List<T>.Contains()
现在不打电话给 Array.IndexOf()
。无论哪种方式,他们都做遵从EqualityComparer<T>.Default
,这意味着这在任何一种情况下都应该是相关的。
【讨论】:
以上是关于System.Array.IndexOf 分配内存的主要内容,如果未能解决你的问题,请参考以下文章