C#中非常大的数组(内存方式)的推荐类型

时间:2010-01-15 15:22:18

标签: c# performance arrays

我有一个包含大约20k个对象的大型数组。每个对象都有一个大型复杂树结构中的子对象,其中也有数组。现在,应用程序仅使用简单的myObjectType[] myArray开发,只需13秒即可获得数组中的项目数。

是否有更好的类型或是否有更好的方法来管理阵列? 99%的阵列使用是从中读取的,但目前需要将近3分钟来填充它。

编辑::添加更多信息。

应用程序当前正在将所有这些数据加载到巨型数组中,然后使用该数组作为数据库。然后,它会根据您从某些下拉框中选择的内容过滤数据,并将子集返回到要显示的数据网格。我没有选择重写整个过程只是将过滤器传递给实际的数据库...

编辑:更多信息,抱歉延迟,被召入会议。

[Serializable]
public class PartsList : System.Collections.CollectionBase
{
  public virtual Part[] parts {get { return (Part[])List; } }
  public new virtual int Count { get{ return this.List.Count;}}

  public virtual CountryList GetCountries()
  {
    CountryList countries = new CountryList;
    //Code removed - goes through every sub item and makes a list of unique countries... 
    // Yes, could have been done better. 
    Return countries;
  }

}

/////////////////////////////////////

[Serializable]
public class Part
{
  private int id, blah, myvariable;
  private CountryList countries;  //formatted the same way as this class...
  private YearList  years; 
  private ModelList models;
  private PriceHistoryList priceHistoryList;
  // there are a couple more like these...
}

这就是加载需要3分钟的原因。 - 20k零件 - 每个部分1-2个国家 - 每个部件1 - 10年 - 每个部件1-12个型号 - 每部分1-10个价格历史

当我在此行停止调试器时:     PartsList mylist = new PartsList;     //在此处填充列表     if(list.Count!= 0)< - 调试器在按下f10后需要13秒才能离开此行。在列表上执行“快速监视”只会给计数值一个错误。

我真正想要的是,是否有更好的变量类型来替换数组,因为它们是内部嵌套的......

2010年1月29日更新 做了一些搜索,似乎由于对象设计,它一次将一个对象延迟加载到内存中,导致触发了一系列sql调用。此外,Count似乎花了这么长时间,因为使用CollectionBase和复杂对象的组合,它检索每个对象,计数然后转到下一个。现在计划是将应用程序移动到2008(.net 3.5从1.1)并重写应用程序的后端,以便它不会将350mb预加载到内存中......

感谢大家的投入。

6 个答案:

答案 0 :(得分:6)

20,000个物体(例如实际上是参考物)是花生。伯爵会立刻回归。如果遇到麻烦,那不是因为数组类。

最终要使用哪个集合取决于你想用它做什么。

在优化之前,请务必找到瓶颈。通常这不是人们首先想到的,因此你绝对应该使用一个分析器来查看实际占用这么多时间的内容。

答案 1 :(得分:5)

任何.NET托管应用程序中的数组类型T[]都将数组的长度存储为对象开头附近的变量。这需要花费很少的时间来计算,所以我们需要更多关于完整结构的信息(特别是“计数”的含义)来告诉你需要花费多长时间。

一个建议是将“节点X下的子项目总数”存储为节点的一部分。这需要O(log n)时间来维护,这与影响计数的树操作具有相同的复杂性,因此不会影响结构的算法复杂性(尽管它确实为每个节点添加了一个4字节的变量)。

答案 2 :(得分:4)

只有一个原因可能会如此缓慢。这是一个称为颠簸的老式问题。在程序运行时,请留意硬盘指示灯。它是在疯狂地闪烁吗?购买更多内存。

答案 3 :(得分:0)

您可以使用类似Dictionary<T>的内容和适当的密钥进行快速查找。但是,你是如何表现你的伯爵的?使用Count()方法可能很慢,但长度应该很快。

更新根据相关新信息:

众所周知,CollectionBase有点慢,因为所有东西都存储为一个对象,并且铸造操作随处可见,就像蚂蚁一样。如果您使用的是带有.NET 1.1的VS 2003,那么您可能会陷入困境,试图优化您的出路。如果您可以将VS 2005与.NET 2.0一起使用,那么您可以使用通用集合,这些集合可以(a)将管理新类型集合的所有管理员带走,并且(b)更快。

这些问题可能会引起关注:

答案 4 :(得分:0)

这取决于您的用法。我最近优化了一些代码,从2-3分钟加载到1.5秒。也许你可以从我的博客文章中获得一些想法:http://blog.zoolutions.se/post/2010/01/04/An-even-better-way-of-handling-a-singleton-WURFL-in-aspnet.aspx

这主要是因为摆脱了我糟糕的单例实例并使用IoC容器为我做这件事。

答案 5 :(得分:0)

这个问题我们不可能给你一个具体的答案,因为很可能你的代码中发生了更多你认为无关紧要的事情,但可能是为什么事情似乎是重要的线索慢慢地跑。

我说“看似”,因为我们没有迹象表明您尝试执行的操作可以运行得更快。

您需要做的是将探查器指向您的程序并查看大多数时间的使用位置。只有这样,您才能开始寻找加速计划的具体方法。

请注意,随机修补可能会让您获得性能提升,但如果您碰巧找到了正确的点,那可能更像是盲目的运气而不是您的任何特定技能(请注意,我并不是说您没有正确的技能,但即使是表演专家也会说他们在大部分时间都在走自己的路是错的。)

根据您的问题判断,您可能需要查看具体问题,但在查看并修复这些问题之后,您仍然需要该分析器。

  • 为什么数组上的简单“计数”需要3分钟?也许你遗漏了你真正在计算符合特定标准的物体?或者你可能正在使用.Count()扩展方法而不是.Length(注意,.Length将返回数组的大小,而不是实际放置对象的元素数量)

您可以查看的个人资料: