使用go ethereum`bind.NewTransactor()`的巨大持久内存分配?
我正在开发一个与私有以太坊区块链网络交互的REST服务。首先,我将Java与Web3j库和Jersey一起使用。一切都按预期运行,但该服务的单个实例(不是geth客户端)占用了高达500MB的RAM由于出于模拟目的,我需要同时运行多个实例(~40),所以我想要一些更轻的 因此,我切换到Go(32位版本,Windows 10)和原始的Go以太坊软件包。然而,当我调用并存储bind.NewTransactor()的结果时,我非常惊讶地发现程序的内存消耗量上升到了~250MB,该结果返回一个使用go ethereum`bind.NewTransactor()`的巨大持久内存分配?,go,memory,cryptography,ethereum,go-ethereum,Go,Memory,Cryptography,Ethereum,Go Ethereum,我正在开发一个与私有以太坊区块链网络交互的REST服务。首先,我将Java与Web3j库和Jersey一起使用。一切都按预期运行,但该服务的单个实例(不是geth客户端)占用了高达500MB的RAM由于出于模拟目的,我需要同时运行多个实例(~40),所以我想要一些更轻的 因此,我切换到Go(32位版本,Windows 10)和原始的Go以太坊软件包。然而,当我调用并存储bind.NewTransactor()的结果时,我非常惊讶地发现程序的内存消耗量上升到了~250MB,该结果返回一个*tran
*transactiopts
。我看了资料来源,但无法解释这种行为
这是正常的(如果是,为什么?)
这是我的密码:
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所建议的那样,我的记忆分析了我的程序<代码>前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
虽然bind.NewTransactor
和bind.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
没有预期的内存消耗行为,因此我将打开一个“副本”?@Ullaakut感谢链接。然而,正如我所说,我不是在谈论geth节点,我只是在谈论运行我发布的代码。另外,到目前为止,我还没有尝试发送任何交易。事实上,上面代码中的ethclient连接部分可以删除,但内存消耗仍然很高……试试看。Geth是一个相当大的程序,内部代码非常相互关联。即使使用geth的一个子集,也可能需要运行大量代码。@raghasood。请看一下我编辑的问题和我的答案,你会看到我只处理加密实现问题,所以我不认为Geth的大小与此有关。
(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