java - 映射大量多头的最快方法

标签 java performance

我正在编写一个将数字(长)转换为一小组结果对象的 Java 应用程序。这个映射过程对应用的性能非常关键,因为它经常被需要。

public static Object computeResult(long input) {
    Object result;
    // ... calculate
    return result;
}

大约有 150,000,000 个不同的键对象和大约 3,000 个不同的值。 从输入数字(长)到输出(不可变对象(immutable对象))的转换可以通过我的算法以每秒 4,000,000 次转换的速度计算。 (使用 4 个线程)

我想缓存 150M 不同的可能输入的映射以使翻译更快,但我发现创建这样的缓存有些困难:

public class Cache {
    private static long[] sortedInputs; // 150M length
    private static Object[] results; // 150M length

    public static Object lookupCachedResult(long input) {
        int index = Arrays.binarySearch(sortedInputs, input);
        return results[index];
    }
}

我尝试创建两个长度为 150M 的数组。第一个数组包含所有可能的输入 long,并按数字排序。第二个数组在与第一个数组的输入对应的索引处保存对 3000 个不同的、预先计算的结果对象之一的引用。

为了获得缓存的结果,我对第一个数组中的输入数字进行了二进制搜索。然后在第二个数组中的相同索引处查找缓存的结果。

遗憾的是,这种缓存方法并不比计算结果快。甚至不到一半,每秒只有大约 150 万次查找。 (同样使用4个线程)

谁能想到在这种情况下缓存结果的更快方法?

我怀疑是否有一个数据库引擎能够每秒回答超过 4,000,000 个查询,假设是一个普通的工作站。

最佳答案

散列是这里的方法,但我会避免使用 HashMap,因为它只适用于对象,即每次插入 long 时都必须构建一个 Long,这会减慢它的速度。由于 JIT,这个性能问题可能并不重要,但我建议至少尝试以下操作并针对 HashMap 变体衡量性能:

将您的多头数据保存在长度为 n > 3000 的长数组中,并通过非常简单的散列函数(因此非常高效)手动进行散列,例如 索引 = 键 % n。由于您事先知道 3000 个可能的值,因此您可以根据经验找到一个数组长度 n,这样这个简单的哈希函数就不会导致冲突。因此,您可以绕过重新散列等,并拥有真正的 O(1) 性能。

其次,我建议您查看 Java 数字库,例如

两者都由本地 Lapack 和 BLAS 实现支持,这些实现通常由非常聪明的人高度优化。也许您可以根据矩阵/vector 代数来制定您的算法,以便它一次(或逐 block )计算整个长数组。

关于java - 映射大量多头的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30718740/

相关文章:

java - 缩放和旋转点数组

linux - find 和 find2perl 之间的性能差异?

javascript - IE8/Javascript 冲突?开发中的 IE8 跨站点卡住 - 包括 Javascript 列表

java - 如何在 OpenStack Object Storage(Swift) 中上传照片和其他文件

java - Java:从不同的线程读取同一文件有时会在某些线程中返回空内容

java - FFMPEG 命令不适用于 Android 10

C++ eigen3 线性代数库,奇怪的性能结果

python - 性能:Python 3.x 与 Python 2.x

c++ - 为什么标准 R 中值函数比简单的 C++ 替代函数慢得多?

java - Spring boot 安全配置 - 必须指定 authenticationManager