Высокое Время выполнения для Словаря. Добавьте для большого количества объектов

У меня есть C#-Application, который хранит данные от TextFile в Объекте Словаря. Объем данных, который будет сохранен, может быть довольно большим, таким образом, требуется много времени, вставляя записи. Со многими объектами в Словаре это становится еще хуже из-за изменения размеров внутреннего массива, который хранит данные для Словаря. Таким образом, я инициализировал Словарь с количеством объектов, которые будут добавлены, но это не оказывает влияния на скорость.

Вот моя функция:

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 объекты. Я проверил время выполнения с Профилировщиком Производительности МУРАВЬЕВ и нашел, что Среднее время для набора результатов. Добавьте (...) не изменяется, когда я инициализирую Словарь с необходимым размером. Это совпадает с, когда я инициализирую Словарь с новым Словарем (); (приблизительно 0,256 мс в среднем для каждого Добавляют). Это определенно вызывается объемом данных в Словаре (ХОТЯ я инициализировал его с желаемым размером). Для первых 20k объектов Добавляет среднее время для, 0,03 мс для каждого объекта.

Какая-либо идея, как сделать добавлять-операцию быстрее?

Заранее спасибо, Frank

Вот моя IdPair-структура:

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.");
  }
}
5
задан LukeH 5 May 2010 в 11:41
поделиться

2 ответа

Поскольку у вас структура, вы получаете реализацию Equals() и GetHashCode() по умолчанию. Как отмечали другие, это не очень эффективно, поскольку использует отражение, но я не думаю, что проблема в отражении.

Мое предположение заключается в том, что ваши хэш-коды распределяются неравномерно с помощью стандартного GetHashCode(), что может произойти, например, если реализация по умолчанию возвращает простое XOR всех членов (в этом случае hash(a, b) == hash(b, a)). Я не могу найти документацию о том, как реализована функция ValueType.GetHashCode(), но попробуйте добавить

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

что может быть лучше.

9
ответ дан 18 December 2019 в 10:42
поделиться

IdPair - это структура , и вы не переопределили Equals или GetHashCode . Это означает, что будет использоваться реализация этих методов по умолчанию.

Для типов значений реализация по умолчанию Equals и GetHashCode использует отражение, что, вероятно, приведет к снижению производительности. Попробуйте предоставить собственную реализацию методов и посмотрите, поможет ли это.

Предлагаемая мной реализация, возможно, это не совсем то, что вам нужно / нужно:

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;
        }
    }
}
7
ответ дан 18 December 2019 в 10:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: