Повышение производительности сериализации / хэш-функции

#c# #serialization #hash #hashtable

#c# #сериализация #хэш #хэш-таблица

Вопрос:

Я работаю над специализированной хеш-таблицей на диске (предыдущие эксперименты с Berkeley, ManagedEsent и т.д. Не увенчались успехом). Он имеет довольно простую цепную структуру, за каждой парой ключ-значение (KVP) в файле следует длинное значение (Int64), которое указывает на следующий KVP в цепочке (и использует нулевое значение, если его нет). Я использую MD5 для генерации хэш-кода.

При профилировании кода для оценки скорости добавления записей хэш-функция отвечает примерно за 55% времени выполнения, что не совсем удивительно. Но около 25% этого времени приходится на binForm.Serialize(ms, obj) вызов ObjectToByteArray функции сериализации. Обе функции показаны ниже. Я предполагаю, что я не смогу добиться больших успехов в самом алгоритме хэширования, но мне интересно, могу ли я повысить производительность функции сериализации?

     // Compute hash code
    long hash(object s)
    {
        byte[] y = md5.ComputeHash(ObjectToByteArray(s)); // Produces byte[16]
        long z = BitConverter.ToInt64(y, 0);
        long res = z amp; bitMask;
        return res;
    }

    // Convert an object to a byte array
    private byte[] ObjectToByteArray(Object obj)
    {
        if (obj == null)
            return null;

        MemoryStream ms = new MemoryStream();
        binForm.Serialize(ms, obj);
        return ms.ToArray();
    }
  

Комментарии:

1. Я не думаю, что вам нужно использовать сложную хэш-функцию, такую как md5. Вы даже можете использовать, ObjectToByteArray(s).GetHashCode() потому что это не обязательно должно быть таким !unique! , как md5

2. Это интересно. В дополнение к любым достижениям в сериализации, которые я могу получить, я попробую и посмотрю, ускорит ли это процесс. Спасибо.

3. И вот сравнение производительности сериализаторов Json BinaryFormatter codeproject.com/KB/IP/fastJSON.aspx

4. Я заглянул в FastJson, но не смог понять, как его можно использовать в качестве двоичного сериализатора (т. Е. Как создать byte[]).

5. Конечно, поскольку это не двоичный сериализатор. Он преобразует ваш объект в строку Json , после чего вы можете получить byte[] в виде Encoding.UTF8.GetBytes(jsonstring)

Ответ №1:

Использование protobuf.net , найденный здесь, это намного быстрее!

Обновить

Глядя на ваш код, я предполагаю, что нет требования, чтобы вычисленные хэши были согласованы между доменами приложений? В противном случае вычисление вашего хэш-кода может быть таким же простым, как:

 private static long GenerateHash(object key)
{
  long typeHash = key.GetType().GetHashCode();
  long keyHash = key.GetHashCode();
  return (typeHash << 32)   keyHash;
}
  

Для дальнейшего использования ваш MemoryStream действительно должен находиться в блоке using, иначе вы рискуете утечкой памяти:

 private byte[] ObjectToByteArray(Object obj)
{
    if (obj == null)
        return null;

    using (MemoryStream ms = new MemoryStream()) 
    {
      binForm.Serialize(ms, obj);
      return ms.ToArray();
    }   
}
  

Комментарии:

1. по моему опыту, это действительно довольно медленно.

2. @Alex, извините, ваш комментарий появился, когда я обновлял… Я полагаю, вы имеете в виду BinaryFormatter?

3. Спасибо, Рич. На самом деле я использую Protobuf для сериализации KVP, и это здорово. Но Protobuf может сериализовать только оформленные классы «ProtoContract», верно? Как я могу использовать его для сериализации неизвестного объекта?

4. Напишите обновление, это правильно. Очень хорошая идея. Я попробую это сделать и отчитаюсь. Спасибо.

5. Если ваш GenerateHash метод просто удвоит один и тот же 32-битный результат GetHashCode , то вы могли бы также сэкономить 4 байта и не утруждать себя удвоением: вы ничего не выиграете, делая это.

Ответ №2:

двоичный форматировщик известен своей низкой производительностью. попробуйте другие методы сериализации.

Комментарии:

1. Спасибо — я согласен, это довольно медленно. Но для меня не очевидно, какие существуют альтернативы сериализации получше (см. Комментарий к Protobuf выше). Есть ли у вас какие-либо рекомендации?