我有一个包含大约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预加载到内存中......
感谢大家的投入。
答案 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)
这个问题我们不可能给你一个具体的答案,因为很可能你的代码中发生了更多你认为无关紧要的事情,但可能是为什么事情似乎是重要的线索慢慢地跑。
我说“看似”,因为我们没有迹象表明您尝试执行的操作可以运行得更快。
您需要做的是将探查器指向您的程序并查看大多数时间的使用位置。只有这样,您才能开始寻找加速计划的具体方法。
请注意,随机修补可能会让您获得性能提升,但如果您碰巧找到了正确的点,那可能更像是盲目的运气而不是您的任何特定技能(请注意,我并不是说您没有正确的技能,但即使是表演专家也会说他们在大部分时间都在走自己的路是错的。)
根据您的问题判断,您可能需要查看具体问题,但在查看并修复这些问题之后,您仍然需要该分析器。
您可以查看的个人资料: