最快的哈希函数/查找原始键

时间:2014-11-25 16:39:40

标签: performance hash hashmap hashtable

我的应用程序需要在数据集中每秒查找数百万次。 (HPC相关)

这是一个非常具体的用例,其中包含以下内容:

  • 数据集有一组固定的条目。它永远不会缩小,也不会增长。
  • 键是一个原语(一个2字节的int)
  • 永远不会有任何重复的键(呃!)
  • 数据集中的条目从不超过200-300个。
  • 键将倾向于聚集在0到1000范围内,而不是均匀分布在-32,768到32,767之间。

这种情况下最快的哈希函数是什么?

我至少知道一个:

hashValue = key % DATASET_FIXED_SIZE;  // Java syntax for modulo

但我相信在我的情况下,该功能的分布是次优的。

所以 - 用上面的“知识” - 是最快的哈希函数。我是数学新手所以我不知道具体用例是否有minimal perfect hash function这样的东西。如果有,请告诉我。 : - )

注意:由于数据集的大小是固定的,我只关心查找性能。

编辑:我不太关心设置时间。我非常愿意为这个额外的小部分查找性能交换设置时间。这意味着哈希表方法甚至可能不是最好的方法,例如如果n小于10,则使用强力阵列扫描,如果10 <10,则使用二进制搜索。 n&lt; 50并使用一些哈希表方法是n> 50(n是对的数量,0和50只是我提出的一些数字,以明确这一点)

更多信息:用例适用于内存数据结构。

2 个答案:

答案 0 :(得分:0)

如果您打算使用Java HashMap,我能想到的最好的hashCode()实现如下:

public class Sample
{
    private static int CLASS_ID = 0; 
    private final int id;

    public Sample()
    {
        CLASS_ID++;
        id = CLASS_ID;
    }

    // other constructors following the same pattern as in the default constructor

    @Override
    public int hashCode()
    {
        return id;
    }

}

示例的所有构造函数都将确保CLASS_ID递增,然后分配给id字段。这个hashCode()函数将始终为每个实例返回一个唯一值,这可以避免将两个实例放在哈希映射中的一个桶中 - 假设哈希映射具有足够的桶。这会提高性能,但会以内存为代价。

此外,这个实现有两个弊端:

1:如果创建的实例多于整数的大小,则此实现将不起作用。但是,如果您打算仅使用200到300个实例,则情况不应该如此。

2:最伟大的&#39;虽然使用CLASS_ID作为(全局状态)静态变量。静态变量将在程序的整个运行时间内保留在内存中。

U,,,作为程序员,你需要投入某些实施的成本和权衡。

答案 1 :(得分:0)

Koloboke不使用Murmur;即使是线性散列,它也会使用更简单的混合:https://github.com/OpenHFT/Koloboke/blob/344089c9fc7c2b53ba7d1299eb29214206e1ab1d/lib/impl/src/main/javaTemplates/net/openhft/koloboke/collect/impl/hash/LHash.java#L34

在你的情况下,我建议为0-1000范围内的密钥(不是哈希)创建一个直接查找表,使用线性哈希表乘以一个随机常量的哈希值(你可以为每个特定的情况尝试几个看看哪些结果可以减少碰撞,或者只是坚持使用像-1640531527这样的值。

int index = key * random & (rest_table_size_power_of_2 - 1);