使用 Java 摘要生成哈希的时间会变慢

A.r*_*olo 4 java performance message-digest wildfly

在使用 wildfly 8.2 和 Java 1.7 的生产环境中,我遇到了一个非常奇怪的情况。

情况是,当服务器启动超过 2 周时,登录性能开始下降。我一直在寻找可能表明问题出在哪里的线索。然后经过一些测试,我得出的结论是,问题在于明文插入的密码被加密以与已插入的密码进行比较。

当加密密码的函数被执行时,它需要将近 2 分钟,但是当服务器重新启动时,同样的执行时间不到 30 秒。

加密使用 java.security.MessageDigest 生成哈希。具体使用 SHA-256 迭代 50000 次。知道为什么这个过程会随着时间变慢吗?我正在使用 /dev/urandom 来生成随机数,所以这应该不是问题。

下面是函数代码:

protected byte[] hash(byte[] bytes, byte[] salt, int hashIterations) throws UnknownAlgorithmException {
    MessageDigest digest = getDigest(getAlgorithmName());
    if (salt != null) {
        digest.reset();
        digest.update(salt);
    }
    byte[] hashed = digest.digest(bytes);
    int iterations = hashIterations - 1; //already hashed once above
    //iterate remaining number:
    for (int i = 0; i < iterations; i++) {
        digest.reset();
        hashed = digest.digest(hashed);
    }
    return hashed;
}
Run Code Online (Sandbox Code Playgroud)

A.r*_*olo 5

经过几天的研究,我终于找到了我的问题的答案。我想在这里分享它,以防对其他人有用。

问题是由代码缓存内存引起的。我专注于堆内存,我没有看到任何问题,但是当我检查非堆内存时,我发现就在登录过程开始变慢时,代码缓存下降了一半以上使用的内存。

调查这个内存,我发现当这个空间有很大的下降时,可能会发生JIT编译器停止工作的情况。总之,这就是正在发生的事情,关闭 JIT 编译器导致我的加密循环的每次迭代都必须在每次执行时进行解释,这在逻辑上使过程变得更慢。

在这里,我留下了一些我认为对本主题有帮助的链接。

[1] - https://www.quora.com/In-Java-what-exactly-will-the-JVM-interpreter-and-the-JIT-compiler-do-with-the-bytecode

[2] - https://www.atlassian.com/blog/archives/codecache-is-full-compiler-has-been-disabled

感谢那些花时间回答它的人