什么是超大HashMap的有效替代方案?

时间:2015-04-03 19:28:15

标签: java hashmap

我试图使用“在中间遇见”来打破对称加密。攻击。为此,我需要存储2 ** 32个整数 - 整数对。我将映射从4字节的密文存储到4字节密钥。

起初我尝试使用数组,但后来我意识到你不能在java中有这么大的数组(最大大小由Integer.MAX_VALUE绑定)。

现在我正在使用HashMap,但是当地图变大时,即使用-Xmx8192M将最大内存增加到8GB,这也会变得太慢。

什么是超大型HashMap的有效替代方案?

这是我目前用来填充我的hashmap的代码:

HashMap<Integer, Integer> map = new HashMap<>(Integer.MAX_VALUE);
// Loop until integer overflow
for (int k = 1; k != 0; k++)
    map.put(encrypt_left(c, k), k);

即使让它运行了几个小时,我还没有看到这段代码完成。进度记录显示前22 ** 24值是在22秒内创建的,但随后性能会迅速下降。

4 个答案:

答案 0 :(得分:3)

  

我存储从4字节密文到4字节密钥的映射。

方便地,4个字节是int。如您所见,数组大小受Integer.MAX_VALUE限制。这表明你可以使用一个数组 - 但这是一个小小的挂断。整数已签名,但数组只允许值> = 0。

所以你创建了两个数组:一个用于正的cyphertexts,一个用于负的cyphertexts。然后你只需要确保你已经为JVM提供了足够的堆。

那是多少堆?

4个字节* Integer.MAX_VALUE * 2个阵列
= 17179869176字节
= ~16.0千兆字节。

答案 1 :(得分:2)

根据@MattBall的建议,我实现了自己的BigArray,它由4个独立的数组组成一个32位长的数组。

在没有建议的JVM参数的情况下运行它将导致OutOfMemoryError。将此与建议的JVM参数一起使用但RAM太少可能会导致计算机崩溃。

/**
 * Array that holds 2**32 integers, Implemented as four 30-bit arrays.
 * <p>
 * Requires 16 GB RAM solely for the array allocation. 
 * <p>
 * Example JVM Arguments: <code>-Xmx22000M -Xms17000M</code>
 * <p>
 * This sets the max memory to 22,000 MB and the initial memory to 17,000 MB
 * <p>
 * WARNING: don't use these settings if your machine does not have this much RAM.
 * 
 * @author popovitsj
 */
public class BigArray
{

    private int[] a_00= new int[1 << 30];
    private int[] a_01 = new int[1 << 30];
    private int[] a_10 = new int[1 << 30];
    private int[] a_11 = new int[1 << 30];

    private static final int A_00 = 0;
    private static final int A_01 = 1 << 30;
    private static final int A_10 = 1 << 31;
    private static final int A_11 = 3 << 30;
    private static final int A_30 = A_01 - 1;

    public void set(int index, int value)
    {
        getArray(index)[index & A_30] = value;
    }

    public int get(int index)
    {
        return getArray(index)[index & A_30];
    }

    private int[] getArray(int index)
    {
        switch (index & A_11)
        {
        case (A_00):
            return a_00;
        case (A_01):
            return a_01;
        case (A_10):
            return a_10;
        default:
            return a_11;
        }
    }
}

答案 2 :(得分:1)

在构建彩虹表时,请考虑您要生成的数据大小。还要考虑一个事实,即没有大量的RAM就可以解决这个问题。这是通过使用文件而不是全部放入内存来完成的。通常,您构建的文件大小适合您的文件缓冲区。例如4096字节或8192字节。如果你得到一个密钥,你只需将其除以文件缓冲区的大小,加载文件并查看mod x位置。 棘手的部分是您需要铺设加密数据,而不是密钥。因此,您从虚拟文件开始,并将密钥数据写入加密数据的位置。

所以,让我们说,你的密钥是1026,加密数据是126.写入1026的flke是0.rbt,因为126 * 4字节/ 4096 = 0.位置是126 * 4字节。 当然,你需要nio类。

答案 3 :(得分:1)

这是大数据问题,在这种情况下,它更像是一个大内存问题。计算应该在内存中进行,以提高性能。使用Hazelcast分发HashMap。它非常易于使用且性能非常高。 您可以使用2台或更多台机器来解决问题。

样本用法:

HazelcastInstance hzInstance = Hazelcast.newHazelcastInstance();
Map<Integer, Integer> map = hzInstance.getMap("map1");
map.put(x,y);
..