如何优化使用Dictionary <string,class =“”> </string,>的代码

时间:2012-06-21 07:48:50

标签: c# optimization dictionary

我有以下代码:

// Dictionary which I want to optimize
Dictionary<string, MyClass> myDict;
//
Dictionary<int, KKSKey> kksKeyList;

...    
...
...

// Classes
[Serializable]
public class MyClass : MyBaseClass
{
    Dictionary<int, DebugValue> myDebugValues;    
    ...
    ...
    ...
}

//
[Serializable]
public class DebugValue
{
    public int ValueType {get;set;}
    public double Value {get;set;}
    ...
    ...
    ...
}

public class KKSKey
{
    public string KKS { set; get; }
    public string Variable { set; get; }
    ...
    ...
    ...
}

我到处使用字典的原因是因为我需要通过密钥访问列表。

我在for循环中有以下行,运行时间超过550,000(是!)次。 myDict有大约10,000件商品,kksKeyList有超过550,000件商品。

以下每行都针对i = 0 to 550,000运行:

myDict[kksKeyList[i].KKS].myDebugValues[i].ValueType = DOUBLE;
myDict[kksKeyList[i].KKS].myDebugValues[i].Value = tempdouble;

基本上,上面的行正在填充通过TCP接收的原始数据的字典项。上述每一行每for个循环(550,000次)大约需要90-100毫秒。这对我的申请来说是不可接受的。它必须在50毫秒内完成上述一行。谁能建议如何优化上述操作的性能?我愿意接受任何建议,即使这意味着必要时重新定义相关课程。

2 个答案:

答案 0 :(得分:2)

您可以尝试:

string kks = kksKeyList[i].KKS;
myDict[kks].myDebugValues[i].ValueType = DOUBLE;
myDict[kks].myDebugValues[i].Value = tempdouble;

或者也许:

myDict[kksKeyList[i].KKS] = new DebugValue(DOUBLE, tempdouble)

如果它适合你的构造函数......

答案 1 :(得分:2)

你的时间太慢了。毫秒是这种问题的永恒,字典中的550,000个元素是鸡饲料。我的第一个想法是你的问题是你的数据源,而不是你的词典;一毫秒是网络通信的更多时间。

如果字典 问题,请查看您的记忆。字典是散列表,基本上是数组。当你创建一个时,它从一个特定大小的数组开始。随着它的扩展,它会分配一个新的,更大的阵列并抛弃旧的阵列。如果您的550,000元素字典以10个元素的空间开始,它将留下“可用”内存,这些内存中充斥着无法使用的大块内存,因为下一个分配仍然更大。 GC将努力重新安排内存并使所有这些块连续,如果它在您运行两个问题语句时执行此操作,则会减慢速度。要解决此问题,请在创建字典时首先为550,000个条目分配空间。这可能就足够了,但也可以致电GC.Collect()。这样可以一次性完成GC工作,并在您需要时为您提供干净的计时。

另一个内存问题可能是myDebugValues。你已经为myDict中的550,000个条目中的每一个获得了其中一个。就像你希望myDict从一开始就很大,这些都需要很小。我甚至可能会建议使用ListDictionary或HybridDictionary(System.Collections.Specialized)。

内存的关键是只使用真实内存而不是虚拟内存;一旦你的机器开始分页,你就有麻烦了。并保持你的GC快乐。

希望这会有所帮助,或者其他人提出更好的答案。 (我喜欢Urik,但优化者可能已经这样做了。)