#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!
, как md52. Это интересно. В дополнение к любым достижениям в сериализации, которые я могу получить, я попробую и посмотрю, ускорит ли это процесс. Спасибо.
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 выше). Есть ли у вас какие-либо рекомендации?