簡體   English   中英

Dictionary.Add的高運行時添加了大量的項目

[英]High Runtime for Dictionary.Add for a large amount of items

我有一個C#-Application,它將來自TextFile的數據存儲在Dictionary-Object中。 要存儲的數據量可能相當大,因此插入條目需要花費大量時間。 由於內部數組的大小調整存儲了Dictionary的數據,因此在Dictionary中有許多項目會變得更糟。 因此,我使用將要添加的項目數量初始化詞典,但這對速度沒有影響。

這是我的功能:

private Dictionary<IdPair, Edge> AddEdgesToExistingNodes(HashSet<NodeConnection> connections)
{
  Dictionary<IdPair, Edge> resultSet = new Dictionary<IdPair, Edge>(connections.Count);

  foreach (NodeConnection con in connections)
  {
    ...
    resultSet.Add(nodeIdPair, newEdge);
  }

  return resultSet;
}

在我的測試中,我插入~300k項目。 我用ANTS Performance Profiler檢查了運行時間,發現當我用所需的大小初始化Dictionary時,resultSet.Add(...)的平均時間不會改變。 它與我用新的Dictionary()初始化Dictionary時相同; (每次添加平均約0.256毫秒)。 這肯定是由字典中的數據量引起的(盡管我用所需的大小初始化它)。 對於前20k項,每個項的Add的平均時間為0.03 ms。

任何想法,如何使添加操作更快?

先謝謝你,弗蘭克

這是我的IdPair-Struct:

public struct IdPair
{
  public int id1;
  public int id2;

  public IdPair(int oneId, int anotherId)
  {
    if (oneId > anotherId)
    {
      id1 = anotherId;
      id2 = oneId;
    }
    else if (anotherId > oneId)
    {
      id1 = oneId;
      id2 = anotherId;
    }
    else
      throw new ArgumentException("The two Ids of the IdPair can't have the same value.");
  }
}

由於您有結構,因此您將獲得Equals()和GetHashCode()的默認實現。 正如其他人所指出的那樣,這不是很有效,因為它使用反射,但我不認為反射是問題。

我的猜測是你的哈希碼由默認的GetHashCode()不均勻地分配,這可能發生,例如,如果默認實現返回所有成員的簡單XOR(在這種情況下哈希(a,b)==哈希(b) , 一個))。 我找不到有關如何實現ValueType.GetHashCode()的任何文檔,但嘗試添加

public override int GetHashCode() {
    return oneId << 16 | (anotherId & 0xffff);
}

這可能會更好。

IdPair是一個struct ,你沒有重寫EqualsGetHashCode 這意味着將使用這些方法的默認實現。

對於值類型, EqualsGetHashCode的默認實現使用反射,這可能導致性能不佳。 嘗試提供自己的方法實現,看看是否有幫助。

我建議的實現,可能不完全是你需要/想要的:

public struct IdPair : IEquatable<IdPair>
{
    // ...

    public override bool Equals(object obj)
    {
        if (obj is IdPair)
            return Equals((IdPair)obj);

        return false;
    }

    public bool Equals(IdPair other)
    {
        return id1.Equals(other.id1)
            && id2.Equals(other.id2);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 269;
            hash = (hash * 19) + id1.GetHashCode();
            hash = (hash * 19) + id2.GetHashCode();
            return hash;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM