看來你SimplifiedPricing
是一個較小的查找表和較大的名單上的外循環迭代。它看起來好像延遲的主要來源是小列表中每個項目的Equals檢查以匹配較大列表中的每個項目。此外,如果您有匹配項,則更新較大列表中的值,因此多次更新看起來多餘。
考慮到這一點,我會建議在較小的列表中建立一個Dictionary
,增加內存消耗,但會大大加快查找時間。首先,我們需要一些東西來保存這本詞典的關鍵。我會假設improd
和pplist
是整數,但它並不適用於這種情況下發揮作用:
public struct MyKey
{
public readonly int Improd;
public readonly int Pplist;
public MyKey(int improd, int pplist)
{
Improd = improd;
Pplist = pplist;
}
public override int GetHashCode()
{
return Improd.GetHashCode()^Pplist.GetHashCode();
}
public override bool Equals(object obj)
{
if (!(obj is MyKey)) return false;
var other = (MyKey)obj;
return other.Improd.Equals(this.Improd) && other.Pplist.Equals(this.Pplist);
}
}
現在,我們有一些一氣呵成比較Pplist和Improd,我們可以使用它作爲一個關鍵包含SimplifiedPricing
的字典。
IReadOnlyDictionary<MyKey, SimplifiedPricing> simplifiedPricingLookup =
(from sp in Settings.SimplifiedPricing
group sp by new MyKey(sp.PPPROD, sp.PPLIST) into g
select new {key = g.Key, value = g.Last()}).ToDictionary(o => o.key, o => o.value);
注意IReadOnlyDictionary
。這是展示我們在創建後不能修改這本字典的意圖,使我們能夠安全地並行主循環:
Parallel.ForEach(Settings.ProdCostsAndQtys, c =>
{
SimplifiedPricing value;
if (simplifiedPricingLookup.TryGetValue(new MyKey(c.improd, c.pplist), out value))
{
c.pricecur = value.PPP01;
c.priceeur = value.PPP01;
}
});
這應該您的單線程O(n²)
循環更改爲並行O(n)
循環,有輕微的開銷用於創建simplifiedPricingLookup
字典。
來源
2014-08-29 13:07:14
Bas
對此不太確定,但可以嘗試將「Where」函數的結果放入第二個循環外的變量中 – ppetrov 2014-08-29 12:44:37
如果將內部foreah更改爲外部,需要多長時間?如何製作使用ahash函數的自定義EqualityComparer? – 2014-08-29 12:46:11
有多少個獨特的PPPROD和PPLIST值? – hatchet 2014-08-29 12:48:19