Java C++;openssl SHA256运行速度比JDK SHA256实现慢

Java C++;openssl SHA256运行速度比JDK SHA256实现慢,java,c++,openssl,bitcoin,sha256,Java,C++,Openssl,Bitcoin,Sha256,我正在做一个项目,作为项目的一部分,我必须大致模拟比特币的工作证明计算。这涉及在固定的“块哈希”字符串和每次迭代递增的32位int nonce的串联上迭代计算SHA256两次。如果计算的哈希值小于“TargetHash”字符串,我们将中断循环并打印nonce值 我试图比较两种顺序实现,一种是使用C++使用OpenSSL的Sa256实现,另一种是java使用JDK的内部Sa256实现。我原本期望OpenSSL实现比JDK快得多,但事实恰恰相反 以下是我的Java代码: import java.ni

我正在做一个项目,作为项目的一部分,我必须大致模拟比特币的工作证明计算。这涉及在固定的“块哈希”字符串和每次迭代递增的32位int nonce的串联上迭代计算SHA256两次。如果计算的哈希值小于“TargetHash”字符串,我们将中断循环并打印nonce值

我试图比较两种顺序实现,一种是使用C++使用OpenSSL的Sa256实现,另一种是java使用JDK的内部Sa256实现。我原本期望OpenSSL实现比JDK快得多,但事实恰恰相反

以下是我的Java代码:

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


public class SHA256 {
    /**
     * convert byte[] to hex string
     *
     * @param hash
     * @return hex string
     */
    private static String bytesToHex(byte[] hash) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < hash.length; i++) {
            String hex = Integer.toHexString(0xff & hash[i]);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }

    /**
     * get a sha256 of the input string
     *
     * @param inputString
     * @return resulting hash in hex string
     */
    public static String SHA256(String inputString) {
        try {
            MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
            return bytesToHex(sha256.digest(inputString.getBytes(StandardCharsets.UTF_8)));
        } catch (NoSuchAlgorithmException ex) {
            System.err.println(ex.toString());
            return null;
        }
    }

    public static void main(String[] args){
        String blockHash = SHA256("Some random string to generate a block hash.");
        System.out.println("blockHash: " + blockHash);
        String targetHash = "000000938023b712892a41e8438e3ff2242a68747105de0395826f60b38d88dc";
        String tmp_hash="undefined";
        int nonce = 0;
        for(nonce=Integer.MIN_VALUE; nonce<=Integer.MAX_VALUE; nonce++) {
            tmp_hash = SHA256(SHA256(blockHash+String.valueOf(nonce)));
            if(targetHash.compareTo(tmp_hash)>0)
                break;
        }
        System.out.println("Resulting Hash: " + tmp_hash);
        System.out.println("Nonce:" + nonce);
    }
}

这只是为了一个简单的目标,对于更困难的目标,差别更大。我非常肯定,这里OpenSSL Sa256的实现不是瓶颈,而是其他的东西,但是C++是新的,我不知道什么。我之前使用了to_string(nonce)和s1.compare(s2),我用fmt::format和strcmp替换了它们,因为它们速度更快,但仍然只能获得几秒钟的时间。任何想法都会得到真正的赞赏。

< P>你的C++代码的瓶颈是你的自定义BythytoSoxx字符串函数。在循环中调用stringstream函数只会影响性能

你可能想从另一个问题来看这个问题


用以下代码段替换stringstream函数。它更快,因为它直接操作字符串内存

static const char characters[] = "0123456789ABCDEF";
std::string result (SHA256_DIGEST_LENGTH * 2, ' ');
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
    result[2*i] = characters[(unsigned int) hash[i] >> 4];
    result[2*i+1] = characters[(unsigned int) hash[i] & 0x0F];
}
return result;
静态常量字符[]=“0123456789ABCDEF”;
std::字符串结果(SHA256_摘要_长度*2');
对于(int i=0;i>4];
结果[2*i+1]=字符[(无符号整数)散列[i]&0x0F];
}
返回结果;

我想知道为什么这个答案被否决。@我想这个答案被编辑了两次,原来有点简洁。这可能会邀请某人的投票。随着这种变化,C++程序在java程序中所花的时间是1/3。我认为这是一个相当好的进步。还有更多的改进要做,但这应该是最重要的。我想知道在速度方面,
fmt::format(“{}{}”,blockHash,nonce)
blockHash+std::to_string(nonce)
相比有什么不同。@aayushARM这取决于你想要实现什么。现在您正在基于字符串值进行比较。实际上,您可以直接比较原始数据,方法是根据64位或32位系统将哈希值强制转换为uint64_t数组或uint32_t数组。但这与Java代码所做的不同。因此,加速比不再相关。为什么不使用
0000008CE61C628FFB00B6668687504FD5D44DA0A57ADB40D60FF59F8E4AF0A4A
作为
targetHash
并比较是否相等(在两个程序中)?我不确定为什么要这样做。考虑到这两种实现都顺序递增nonce,更快的代码应该更早到达结果散列,因此无论我是使用targetHash还是结果散列,基准测试都不应该受到影响。只是因为在散列上执行
很奇怪。这没有道理。他们不是平等就是不平等。BTW <代码>(Tracethas= = TMPHASH)< /C>或<代码>(TMPHASHAS< TAGEHASH)< /C>,而不是做<代码>(STMPMP(TMPCMHAS.CXSTRE),TAGTHASH.CXString())< /C> >是比较C++代码>比较代码> STD::String
javac SHA256.java
time java SHA256
blockHash: 596143a6a70a23c86e4b218afeb05d151ed45a39e96368e213d17e0a491d894a
Resulting Hash: 0000008ce61c628ffb00b6668687504fd5d44da0a57adb40d6ff59f8e4af0a4a
Nonce:-2135751361

real    0m22.258s
user    0m22.977s
sys 0m0.097s

g++ -O2 -DFMT_HEADER_ONLY main.cpp -lcrypto -lssl
time ./a.out
blockHash: 596143a6a70a23c86e4b218afeb05d151ed45a39e96368e213d17e0a491d894a
Resulting Hash: 0000008ce61c628ffb00b6668687504fd5d44da0a57adb40d6ff59f8e4af0a4a
Nonce: -2135751361

real    0m35.703s
user    0m35.693s
sys 0m0.005s
static const char characters[] = "0123456789ABCDEF";
std::string result (SHA256_DIGEST_LENGTH * 2, ' ');
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
    result[2*i] = characters[(unsigned int) hash[i] >> 4];
    result[2*i+1] = characters[(unsigned int) hash[i] & 0x0F];
}
return result;