使用对象哈希码作为内存缓存键是否有意义?

时间:2014-04-21 18:22:14

标签: c# caching hash memorycache

我试图在MemoryCache对象中缓存昂贵函数的结果。

MemoryCache需要一个字符串的键,所以我想知道执行以下操作是否有效:

string key = Char.ConvertFromUtf32(myObject.GetHashCode());
if (!_resourceDescriptionCache.Contains(key))
{
    _resourceDescriptionCache[key] = ExpensiveFunction(myObject);
}
return (string)_resourceDescriptionCache[key];

使用单个UTF32字符作为潜在大缓存的密钥感觉很奇怪。

3 个答案:

答案 0 :(得分:2)

这取决于。

在许多情况下,使用GetHashCode()可能会导致错误的行为:

哈希代码用于在基于哈希表的集合中进行有效插入和查找。哈希码不是永久值。出于这个原因:

  • 不要序列化哈希码值或将它们存储在数据库中。
  • 请勿使用哈希码作为密钥从密钥集合中检索对象。
  • 不要跨应用程序域或进程发送哈希码。在某些情况下,可以基于每个进程或每个应用程序域计算哈希码。

http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

如果内存缓存(或将来可能发生)发生在与调用它的代码不同的进程或应用程序域中,则表示第3个条件失败。

  

使用单个UTF32字符作为潜在大缓存的密钥感觉很奇怪。

如果要缓存足够的东西,由于Birthday Problem,32位哈希的冲突率可能会高得令人不快。

当缓存数以千万计的东西时,我使用了一个名为City Hash的64位哈希(由谷歌创建,开源)并取得了很好的成功。您也可以使用Guid,尽管与64位哈希相比,GUID维护密钥的内存是GUID的两倍。

答案 1 :(得分:1)

Hashcodes可能会发生冲突。 return 0;GetHashCode的有效实施。多个密钥将共享一个不是你想要的缓存槽......你会混淆对象。

如果您的代码不能与return 0;一起使用GetHashCode,那么您的代码就会被破坏。

选择更好的缓存密钥。

答案 2 :(得分:-1)

内存缓存由普通的C#Dictionary支持。除了提供到期之外,它确实没有什么不同

碰撞的几率是2 ^ 32,这是整数的大小。即使你设法发生碰撞,字典也会有相应的安全措施(通过使用碰撞时的等于)

编辑:只有在字典被赋予未更改的密钥时才会处理密钥冲突(例如:Dictionary())。在这种情况下,由于MemoryCache使用字符串,因此没有碰撞检测。