gpt4 book ai didi

go - go-ethereum `bind.NewTransactor()` 的巨大持久内存分配?

转载 作者:数据小太阳 更新时间:2023-10-29 03:36:44 27 4
gpt4 key购买 nike

我正在开发与私有(private)以太坊区 block 链网络交互的 REST 服务。首先,我将 Java 与 Web3j 库和 Jersey 结合使用。一切都按预期工作,但服务的单个实例(不是 geth 客户端)占用了高达 500MB 的 RAM!因为我需要同时运行多个实例(~40)以进行模拟,我想要更轻便的东西。

因此我切换到 Go(32 位版本,Windows 10)和原始的 go-ethereum 包。然而,当我调用并存储 bind.NewTransactor() 的结果时,我很惊讶地发现程序的内存消耗上升到 ~250MB ,它返回一个 *TransactOpts。我查看了资料来源,但无法解释这种行为。

这是正常的吗(如果是,为什么?)还是我遗漏了什么?

这是我的代码:

import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"strings"
)

const WALLET_PATH string = "path/to/json/wallet"

func main() {

data, _ := ioutil.ReadFile(WALLET_PATH)
// up to this point, the program only takes a few MBs of RAM

auth, _ := bind.NewTransactor(strings.NewReader(string(data)), "mypassphrase")
// and here the allocated memory rises up to ~270MB
_ = auth
}

最佳答案

好吧,我真的没有找到我的问题的答案,但我确实找到了解决方法,所以无论如何我都会分享它。

内存分析

正如@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

可以看到,内存消耗来自scrypt包中的Key函数,它被bind.NewTransactor(...)间接调用。来自文档:

Key derives a key from the password, salt, and cost parameters, returning a byte slice of length keyLen that can be used as cryptographic key.

特别是,这对应于如何从 JSON 钱包文件生成私钥。实际上,该函数本身会为密码计算分配大量内存。但我不明白的是为什么这个巨大的内存分配似乎在 key 生成后持续存在(当我用 log.Fatal(http.ListenAndServe( ":8080", nil)) 紧随其后)。

解决方法

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

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

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

auth := bind.NewKeyedTransactor(privateKey)

_ = auth
}

虽然 bind.NewTransactorbind.NewKeyedTransactor 返回完全相同的对象(唯一的区别是 key 是如何生成的),使用 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 .

关于go - go-ethereum `bind.NewTransactor()` 的巨大持久内存分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51791869/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com