C# 在哪里我该如何加速?
假设我有一门课是这样的:C# 在哪里我该如何加速?,c#,arrays,linq,collections,.net-3.5,C#,Arrays,Linq,Collections,.net 3.5,假设我有一门课是这样的: class ItemLimits { public string strAccountNumber = string.Empty; public string strUserCode = string.Empty; public long lAccumulatedAmount = 0L; } 我有一个包含50000个元素的数组 我还有一个50000个项目(或多或少)的数据集,我需要在itemlimites数组中找到与此数据集匹配的元素 目前正在通过以下数据
class ItemLimits
{
public string strAccountNumber = string.Empty;
public string strUserCode = string.Empty;
public long lAccumulatedAmount = 0L;
}
我有一个包含50000个元素的数组
我还有一个50000个项目(或多或少)的数据集,我需要在itemlimites
数组中找到与此数据集匹配的元素
目前正在通过以下数据集循环执行此操作:
ItemLimits ilItemLimit = itemlimits.Where(s => s.strUserCode.Equals(dataset[i].User_UserCode, StringComparison.CurrentCultureIgnoreCase)
&& s.strAccountNumber.Equals(strUnEditedHomingAccountNo, StringComparison.CurrentCultureIgnoreCase)).First();
strUnEditedHomingAccountNo
是先前从数据集获取的
一旦我找到了我需要的ItemLimit
,我需要添加到它的lAccumulatedAmount
我从我的性能基准中看到,这在循环开始时非常快,但随着时间的推移会变慢。这是一个线性减速,你可以在我制作的图表中看到:
当我达到40000件物品时,每件物品大约需要40毫秒才能完成。这在我的头脑中是有意义的,因为我假设它只是一个接一个地迭代项目,直到找到匹配项,对于大量的项目,这显然是相当缓慢的
数组和数据集中的项目数可能会有很大的差异
我曾考虑尝试对数组进行排序并执行array.BinarySearch
,但由于struercode
和strAccountNumber
都可以更改,而且我也无法预测数据集的顺序,因此我不知道如何最有效地排序
这是程序中最慢的部分,这就是为什么我想尝试优化它(大约70%的时间都花在做这件事上,还有很多其他的事情要做)
如果有人能给我指点我能做什么,我将不胜感激
我正在使用.NET 3.5,我无法改变这一点。我认为您对导致此问题的原因是正确的,我建议您使用具有快速查找功能的工具来加快速度。有点像字典,速度很快。你已经知道如何比较,看看你是否有正确的记录,你也只寻找一个匹配,或第一个 尝试类似的方法,您需要更改数据集的类型(不知道您正在使用什么),并可能决定在制作
itemLimitDictionary
时如何处理键冲突,但除此之外,它应该可以很好地加快速度:
public void DoTheNeedfull(ItemLimit[] itemLimits, DataSet dataSet)
{
var itemLimitDictionary = itemLimits.ToDictionary(i => MakeKey(i.One, i.Two), i => i);
for(var i = 0; i < dataSet.Count; i++)
{
var strUnEditedHomingAccountNo = BlackMagicMethod(dataSet[i]);
var key = MakeKey(dataSet[i].User_UserCode, strUnEditedHomingAccountNo);
if(itemLimitDictionary.ContainsKey(key))
{
// do your thing
}
else
{
// maybe this is an error
}
}
}
private string MakeKey(string keyPartOne, string keyPartTwo)
{
return keyPartOne.ToUpperInvariant() + keyPartTwo.ToUpperInvariant();
}
public void DoTheNeedfull(ItemLimit[]itemLimits,数据集)
{
var itemLimitDictionary=itemLimits.ToDictionary(i=>MakeKey(i.One,i.Two),i=>i);
对于(var i=0;i
据我所知,您喜欢遍历数据集,而不是增加计数器。该计数器特定于数据集条目的某些属性
所以这听起来像是
GroupJoin()
linq语句的工作。这样,您将得到一个ItemLimits对象,其中所有匹配的数据集项都是IEnumerable
。然后,您可以在此内部枚举上调用Aggregate()
,并将此信息写入给定的ItemLimits
对象。我已经完全放弃了中的位置,并使用数组完成了此操作。使用此比较器进行BinarySearch
:
class ItemLimitsComparer : Comparer<ItemLimits>
{
public override int Compare(ItemLimits x, ItemLimits y)
{
if(Convert.ToInt32(x.strUserCode) < Convert.ToInt32(y.strUserCode))
{
return -1;
}
if(Convert.ToInt32(x.strUserCode) > Convert.ToInt32(y.strUserCode))
{
return 1;
}
if(Convert.ToInt32(x.strUserCode) == Convert.ToInt32(y.strUserCode))
{
if(Convert.ToInt64(x.strAccountNumber) < Convert.ToInt64(y.strAccountNumber))
{
return -1;
}
if(Convert.ToInt64(x.strAccountNumber) > Convert.ToInt64(y.strAccountNumber))
{
return 1;
}
if(Convert.ToInt64(x.strAccountNumber) == Convert.ToInt64(y.strAccountNumber))
{
return 0;
}
}
return 0;
}
}
这让我从所有50k项目的15分钟缩短到了25秒。这个问题似乎离题了,因为它属于Oops。是否可以将问题迁移到其他位置,或者我是否应该删除此项并在那里提问?我不知道,也许版主可以这样做。您可以从将ItemLimits存储在列表中开始,并在将其链接到匹配的数据记录后将其删除?Zache ItemLimits可以多次使用。他们必须呆在那里。我试着使用字典(我应该提到这一点),但出于某种原因,字典不允许我编辑值
部分。还有lol@BlackMagicMethod。实际上,我已经找到了一种进行二进制搜索的方法,在我的机器上使用它可以从15分钟减少到25秒。如果你首先进行转换调用并将值存储在局部变量中,你就可以避免一些方法调用,我认为这会增加readability@Zache抢手货完成。
int index = Array.BinarySearch(itlaCreditLimits, new ItemLimits { strUserCode = dataset[i].User_UserCode, strAccountNumber = strUnEditedHomingAccountNo }, new ItemLimitsComparer());
if(index < 0)
{
throw new Exception("Didn't find ItemLimit for UserCode = " + dataset.User_UserCode + " and account number " + strUnEditedHomingAccountNo);
}
ItemLimits ilItemLimit = itlaCreditLimits[index];