枚举比手动检查不同的变化更便宜时,是否在比较期间将 1,000 多个字符串转换为小写?
Is converting 1,000+ strings to lower-case during comparisons when enumerating cheaper than checking for different variations manually?
我有一个名为 SelectedSections 的 属性,它是从部分集合中分配的。每个部分都包含一个 BidItem 集合,其中包含 1,000 多个项目。当我 select 一个部分时,我需要使用经过过滤的项目集刷新我的视图数据绑定到的项目集合。
public Section SelectedSection
{
get
{
return selectedSection;
}
set
{
this.SetPropertyByReference(ref this.selectedSection, value);
if (value != null)
{
this.BidItems = value.BidItems
.Where(item =>
!item.Description.ToLower().Contains("flagger") ||
!item.Description.ToLower().Contains("civilian flagger") ||
!item.Description.ToLower().Contains("law enforcement"))
.ToList();
}
this.MptPayment.EditedItem.DiaryPayItem.Section = value;
}
}
我必须过滤掉大约十几种不同类型的项目(为了清楚起见,我只显示了 3 种)。在我的 Where
子句中,在检查集合是否包含我要过滤掉的内容之前,我将所有内容都转换为小写。
我意识到这会产生大量垃圾,因为集合中的 1,000 多个项目中的每一个都会为小写 Description
内容创建一个新字符串。我的问题是,对集合中的每个项目都执行此操作十几次是否比我只检查所有已知变体更昂贵?忽略我可能会错过一个变化的事实,因为我对更快的理论更感兴趣。
- 举报者
- 举报者
- 旗手
以上列表是所有已知的变体。我想知道走哪条路会更贵。遍历集合以检查每个已知条件将足够快,而不会产生如此多的垃圾。要么,每个 item/description 枚举不止一次以便找到它们,或者每个 item/description 枚举一次,同时在将被 GC 的堆上创建垃圾字符串。
请注意,此 属性 可能会在用户执行工作时重新设置几十次。所以会进行很多(几万次)字符串比较。
我意识到相对于应用程序的其余部分,这是一个成本低廉的操作;我想了解更多信息以自学而不是担心实际应用程序中的性能下降。
ToLower()
对大型集合会产生不必要的 GC 压力。相反,使用 IndexOf >= 0
和 StringConparison.OrdinalIgnoreCase
:
this.BidItems = value.BidItems
.Where(item =>
!(item.Description.IndexOf("flagger", StringComparison.OrdinalIgnoreCase) >= 0) ||
!(item.Description.IndexOf("civilian flagger", StringComparison.OrdinalIgnoreCase) >= 0) ||
!(item.Description.IndexOf("law enforcement", StringComparison.OrdinalIgnoreCase) >= 0))
.ToList();
一个个人故事 - 我在分析我们的应用程序时看到一个负责 XML 反序列化的方法正在发出大量字符串,导致我们的应用程序每个 运行 发出大约 1.5GB 的数据。这种方法在我们的热门路径上。这最终成为在每次解析迭代中执行 ToLower
的程序员之一。通过删除该调用,我最终为每个 运行 节省了超过 1GB 的分配。
随着您的集合越来越大,您会发现这会导致越来越大的 GC 压力。如果你能避免它,就这样做。
我有一个名为 SelectedSections 的 属性,它是从部分集合中分配的。每个部分都包含一个 BidItem 集合,其中包含 1,000 多个项目。当我 select 一个部分时,我需要使用经过过滤的项目集刷新我的视图数据绑定到的项目集合。
public Section SelectedSection
{
get
{
return selectedSection;
}
set
{
this.SetPropertyByReference(ref this.selectedSection, value);
if (value != null)
{
this.BidItems = value.BidItems
.Where(item =>
!item.Description.ToLower().Contains("flagger") ||
!item.Description.ToLower().Contains("civilian flagger") ||
!item.Description.ToLower().Contains("law enforcement"))
.ToList();
}
this.MptPayment.EditedItem.DiaryPayItem.Section = value;
}
}
我必须过滤掉大约十几种不同类型的项目(为了清楚起见,我只显示了 3 种)。在我的 Where
子句中,在检查集合是否包含我要过滤掉的内容之前,我将所有内容都转换为小写。
我意识到这会产生大量垃圾,因为集合中的 1,000 多个项目中的每一个都会为小写 Description
内容创建一个新字符串。我的问题是,对集合中的每个项目都执行此操作十几次是否比我只检查所有已知变体更昂贵?忽略我可能会错过一个变化的事实,因为我对更快的理论更感兴趣。
- 举报者
- 举报者
- 旗手
以上列表是所有已知的变体。我想知道走哪条路会更贵。遍历集合以检查每个已知条件将足够快,而不会产生如此多的垃圾。要么,每个 item/description 枚举不止一次以便找到它们,或者每个 item/description 枚举一次,同时在将被 GC 的堆上创建垃圾字符串。
请注意,此 属性 可能会在用户执行工作时重新设置几十次。所以会进行很多(几万次)字符串比较。
我意识到相对于应用程序的其余部分,这是一个成本低廉的操作;我想了解更多信息以自学而不是担心实际应用程序中的性能下降。
ToLower()
对大型集合会产生不必要的 GC 压力。相反,使用 IndexOf >= 0
和 StringConparison.OrdinalIgnoreCase
:
this.BidItems = value.BidItems
.Where(item =>
!(item.Description.IndexOf("flagger", StringComparison.OrdinalIgnoreCase) >= 0) ||
!(item.Description.IndexOf("civilian flagger", StringComparison.OrdinalIgnoreCase) >= 0) ||
!(item.Description.IndexOf("law enforcement", StringComparison.OrdinalIgnoreCase) >= 0))
.ToList();
一个个人故事 - 我在分析我们的应用程序时看到一个负责 XML 反序列化的方法正在发出大量字符串,导致我们的应用程序每个 运行 发出大约 1.5GB 的数据。这种方法在我们的热门路径上。这最终成为在每次解析迭代中执行 ToLower
的程序员之一。通过删除该调用,我最终为每个 运行 节省了超过 1GB 的分配。
随着您的集合越来越大,您会发现这会导致越来越大的 GC 压力。如果你能避免它,就这样做。