【问题标题】:Improving performance of serialization / hash function提高序列化/哈希函数的性能
【发布时间】:2011-12-27 04:18:00
【问题描述】:

我正在研究一个专门的磁盘哈希表(之前对 Berkeley、ManagedESENT 等的实验没有成功)。它有一个相当简单的链式结构,文件中的每个键值对 (KVP) 后跟一个长 (Int64) 值,该值指向链中的下一个 KVP(如果没有,则使用零值) )。我正在使用 MD5 生成哈希码。

在分析代码以评估添加条目的速度时,散列函数负责大约 55% 的运行时间,这不足为奇。但是大约 25% 的 时间来自 ObjectToByteArray 序列化函数中的 binForm.Serialize(ms, obj) 调用。这两个功能如下所示。我假设我无法在哈希算法本身上获得任何大的收益,但我想知道我是否可以从序列化函数中获得一些性能?

    // 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 & 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();
    }

【问题讨论】:

  • 我认为您不必使用复杂的哈希函数,例如 md5。你甚至可以使用ObjectToByteArray(s).GetHashCode(),因为它不必像!unique!那样像md5
  • 这很有趣。除了我可以获得的任何序列化收益之外,我会试一试,看看它是否会加快速度。谢谢。
  • 这是Json序列化器+BinaryFormatter的性能对比codeproject.com/KB/IP/fastJSON.aspx
  • 我研究了 fastJSON,但无法弄清楚它如何用作二进制序列化程序(即如何产生一个字节 [])。
  • 当然,因为它不是二进制序列化器。它将您的对象转换为 Json 字符串 然后您可以获得 byte[] 为 Encoding.UTF8.GetBytes(jsonstring)

标签: c# serialization hash hashtable


【解决方案1】:

使用protobuf.net,找到here,快多了!

更新

通过查看您的代码,我假设没有要求计算的哈希值在 AppDomain 之间保持一致?如果不计算您的 HashCode 可以很简单:

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();
    }   
}

【讨论】:

  • 从我的经验来看,这确实很慢。
  • @Alex,抱歉你的评论是在我更新时出现的......我假设你指的是 BinaryFormatter?
  • 谢谢,里奇。我实际上使用 Protobuf 来序列化 KVP,这很棒。但是 Protobuf 只能序列化修饰过的“ProtoContract”类,对吧?如何使用它来序列化未知对象?
  • 写更新,没错。非常好的主意。我会试一试并报告。谢谢。
  • 如果您的 GenerateHash 方法只是将 GetHashCode 的相同 32 位结果加倍,那么您不妨为自己节省 4 个字节,而不必费心加倍:你不这样做不会有任何收获。
【解决方案2】:

二进制格式化程序以其缓慢的性能而闻名。尝试其他的序列化方法。

【讨论】:

  • 谢谢 - 我同意,这很慢。但对我来说,存在哪些更好的序列化替代方案并不明显(参见上面对 Protobuf 的评论)。有推荐的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-25
  • 2020-05-20
  • 2012-05-28
  • 1970-01-01
  • 2013-04-17
  • 1970-01-01
  • 2016-05-24
相关资源
最近更新 更多