使用以太坊`bind.NewTransactor()`的持久存储分配巨大吗?

时间:2018-08-10 18:03:50

标签: go memory cryptography ethereum go-ethereum

我正在开发与私有以太坊区块链网络交互的REST服务。首先,我将Java与Web3j库和Jersey一起使用。一切正常,但服务的一个实例(不是geth客户端)占用了500MB的内存!由于我需要同时运行多个实例(约40个)以进行仿真,我想要些轻的东西。

因此,我切换到Go(32位版本,Windows 10)和原始的go-ethereum软件包。但是,我很惊讶地发现,在我调用并存储bind.NewTransactor()的结果后,程序的内存消耗上升到约250MB ,该结果返回一个{{1 }}。我查看了来源,但无法解释这种行为。

那很正常吗(如果是,为什么?)还是我错过了什么?

这是我的代码:

*TransactOpts

1 个答案:

答案 0 :(得分:0)

好的,我没有真正找到问题的答案,但是当我找到解决方法时,我还是会分享它。

内存配置文件

按照@MichaelHampton的建议,我对程序进行了概要分析。 top 10命令显示了以下内容:

(pprof) top 10
Showing nodes accounting for 256MB, 99.88% of 256.30MB total
Dropped 15 nodes (cum <= 1.28MB)
    flat  flat%   sum%        cum   cum%
    256MB 99.88% 99.88%      256MB 99.88%  github.com/ethereum/go-ethereum/vendor/golang.org/x/crypto/scrypt.Key
        0     0% 99.88%      256MB 99.88%  github.com/ethereum/go-ethereum/accounts/abi/bind.NewTransactor
        0     0% 99.88%      256MB 99.88%  github.com/ethereum/go-ethereum/accounts/keystore.DecryptKey
        0     0% 99.88%      256MB 99.88%  github.com/ethereum/go-ethereum/accounts/keystore.decryptKeyV3
        0     0% 99.88%      256MB 99.88%  github.com/ethereum/go-ethereum/accounts/keystore.getKDFKey
        0     0% 99.88%   256.01MB 99.88%  main.main
        0     0% 99.88%   256.30MB   100%  runtime.main

如您所见,内存消耗来自软件包Key中的scrypt函数,该函数由bind.NewTransactor(...)间接调用。从文档中:

  

密钥从密码,salt和cost参数派生密钥,并返回一个长度为keyLen的字节片,可用作加密密钥。

尤其是,这对应于如何从JSON钱包文件生成私钥。实际上,该函数本身为密码计算分配了很多内存。不过,我不明白的是为什么这么大的内存分配似乎在密钥生成后仍然存在(当我紧接着用log.Fatal(http.ListenAndServe(":8080", nil))启动服务器时观察到了持久性)。

解决方法

为证实我的怀疑,我使用了另一种方式来生成我的*TransactOpts,该方式包括直接从密钥的十六进制表示形式获取密钥,而不是从钱包文件中生成密钥:

func main() {
    privateKey, err := crypto.HexToECDSA("myKeyInHex")

    if err != nil {
        log.Fatal(err)
    }

    auth := bind.NewKeyedTransactor(privateKey)

    _ = auth
}

尽管bind.NewTransactorbind.NewKeyedTransactor返回的对象完全相同(唯一的区别在于密钥的生成方式),但使用bind.NewTransactor则可产生256MB的持久存储力内存分配,而不是bind.NewKeyedTransactor的几个KB,如下所示:

(pprof) top 10
Showing nodes accounting for 11.04kB, 100% of 11.04kB total
Showing top 10 nodes out of 19
    flat  flat%   sum%        cum   cum%
  6.83kB 61.90% 61.90%     6.83kB 61.90%  time.initLocalFromTZI
  4.21kB 38.10%   100%     4.21kB 38.10%  github.com/ethereum/go-ethereum/crypto/sha3.(*state).clone (inline)
       0     0%   100%     4.21kB 38.10%  github.com/ethereum/go-ethereum/accounts/abi/bind.NewKeyedTransactor
       0     0%   100%     4.21kB 38.10%  github.com/ethereum/go-ethereum/crypto.Keccak256
       0     0%   100%     4.21kB 38.10%  github.com/ethereum/go-ethereum/crypto.PubkeyToAddress
       0     0%   100%     4.21kB 38.10%  github.com/ethereum/go-ethereum/crypto/sha3.(*state).Sum
       0     0%   100%     6.83kB 61.90%  github.com/pkg/profile.Start
       0     0%   100%     6.83kB 61.90%  github.com/pkg/profile.Start.func2
       0     0%   100%     6.83kB 61.90%  log.(*Logger).Output
       0     0%   100%     6.83kB 61.90%  log.(*Logger).formatHeader

因此,为了进行模拟,我将从JSON钱包中生成私钥,并将其存储在上游的文本文件中,然后使用bind.NewKeyedTransactor(...)。我知道这并不安全,但出于我的模拟目的就足够了。

但是,我很确定bind.NewTransactor在内存消耗方面没有预期的行为,因此我将打开一个issue on the go-ethereum repository