先记录下,等测试完后,在完善
EOS 2.0之VM改进和参数设置
从EOS 2.0发布到现在有段时间了,今天单独研究下EOS VM的改进,以及相关的参数配置
引用官方介绍
借助EOSIO 2,我们将发布一个名为EOS VM的新WASM引擎,该引擎由三个组件组成,每个组件都有自己的功能并提供特定的性能增强。
区块链WebAssembly执行的强大组件三重奏
EOS VM Interpreter (eos-vm)
EOS VM解释器是一个WebAssembly解释器,提供了极快的解析/加载,确定性和高效的时限执行。从头开始设计解释器,使我们能够为将来对智能合约的调试支持腾出空间。
EOS VM Just In Time Compiler (JIT) (eos-vm-jit)
EOS VM即时(JIT)编译器是一种WebAssembly编译器,它采用WASM并即时生成本机代码。与WABT,Binaryen和EOS VM解释器之类的解释器相比,该体系结构能够非常快速地执行WASM智能合约,并提供显着的性能优势。这种JIT解决方案的绝对速度使我们能够在区块链上使用它,而无需其他解决方案进行较长的块编译时间。
EOS VM Optimized Compiler (eos-vm-oc-enable)
EOS VM Optimized编译器是EOS VM的第三个组件,它使用了利用多遍编译架构的专用编译器框架(LLVM)。通过优化编译器生成的本机代码通常比在WABT,Binaryen,EOS VM解释器和EOS VM JIT中执行的相同代码快一个数量级。最重要的是,它甚至比现有的WAVM引擎还要快,但是与WAVM不同,它可以利用我们的分层设计在区块链上安全使用。
参数配置
开启eos-vm-jit
wasm-runtime = eos-vm-jit
对于wasm-runtime还支持以下选项
- wabt
- eos_vm
- eos_vm_jit
- eos_vm_oc //EOS VM OC is a tier-up compiler and works in conjunction with the configured base WASM runtime. Enable EOS VM OC via 'eos-vm-oc-enable' option
开启 eos-vm-oc-enable
eos-vm-oc-enable = true
还可修改其他参数
- eos-vm-oc-cache-size-mb // Maximum size (in MiB) of the EOS VM OC code cache
- eos-vm-oc-compile-threads // eos-vm-oc-compile-threads must be set to a non-zero value
对于出块节点来说,官方意思是EOS VM Optimized编译器
还没有足够的实际场景测试,防止各BP节点部分开启与未开启的行为之间可能存在差异的风险,官方建议是在生产节点上不使用eos-vm-oc-enable = true
只单独使用eos-vm-jit
,
并且由于节点开启后处理会更快,也就是TPS会增加很多,将导致每个块的数据猛增,会导致查询慢,以及可能的稳定因素影响。官方建议先不要使用,等待官方更新支持。
可看此贴 https://github.com/EOSIO/eos/issues/8620
参考
EOS Bancor 算法测试
为了实际项目中,解决相对有限资源,异步动态价格交换的问题,测试下Bancor 算法
从EOS系统合约中,抽离出测试代码如下
#include <iostream>
#include <cmath>
#include <list>
typedef double real_type;
int64_t supply_amount = 10000000000000ll; // RAMCORE
struct connector {
int64_t balance;
double weight = .5;
};
int64_t convert_from_exchange( connector& reserve, const int64_t& tokens_amount )
{
const double R0 = reserve.balance;
const double S0 = supply_amount;
const double dS = -tokens_amount; // dS < 0, tokens are subtracted from supply
const double Fi = double(1) / reserve.weight;
double dR = R0 * ( std::pow(1. + dS / S0, Fi) - 1. ); // dR < 0 since dS < 0
if ( dR > 0 ) dR = 0; // rounding errors
reserve.balance -= int64_t(-dR);
supply_amount -= tokens_amount;
return int64_t(-dR);
}
int64_t convert_to_exchange( connector& reserve, const int64_t& tokens_amount )
{
const double S0 = supply_amount;
const double R0 = reserve.balance;
const double dR = tokens_amount; // dS < 0, tokens are subtracted from supply
const double F = reserve.weight;
double dS = S0 * ( std::pow(1. + dR / R0, F) - 1. );
if ( dS < 0 ) dS = 0; // rounding errors
reserve.balance += tokens_amount;
supply_amount += int64_t(dS);
return int64_t(dS);
}
// RAM / EOS
int main() {
struct connector base; // RAM
base.balance = 90091267903;
struct connector quote;
quote.balance = 56842445020ll; // EOS
int64_t ram_byte = 0;
int64_t tokens_amount = 10000000000;
int64_t total_tokens_amount = 0;
int64_t total_ram_byte = 0;
int total_num = 10; // 测试循环次数
std::list <int64_t > list_ram_byte;
// Buy EOS->RAM
int64_t tmp = 0;
for (int i = 0; i < total_num; ++i) {
tmp = convert_to_exchange( quote, tokens_amount );
ram_byte = convert_from_exchange( base, tmp );
total_ram_byte += ram_byte;
list_ram_byte.push_back(ram_byte);
total_tokens_amount += tokens_amount;
std::cout << "Buy EOS->RAM " << ram_byte << std::endl;
}
for (int i = 0; i < total_num; ++i) {
tmp = convert_to_exchange( base, list_ram_byte.back() );
list_ram_byte.pop_back();
tokens_amount = convert_from_exchange( quote, tmp );
std::cout << "One Sell RAM->EOS " << tokens_amount << std::endl;
}
// Sell RAM->EOS
//tmp = convert_to_exchange( base, total_ram_byte );
//tokens_amount = convert_from_exchange( quote, tmp );
//std::cout << "One Sell RAM->EOS " << tokens_amount << std::endl;
return 0;
}
测试结果如下
Buy EOS->RAM 13478152673
Buy EOS->RAM 9970155844
Buy EOS->RAM 7674007724
Buy EOS->RAM 6089163862
Buy EOS->RAM 4949324006
Buy EOS->RAM 4102144882
Buy EOS->RAM 3455335389
Buy EOS->RAM 2950326086
Buy EOS->RAM 2548490488
Buy EOS->RAM 2223515894
Sell RAM->EOS 9999999996
Sell RAM->EOS 10000000000
Sell RAM->EOS 9999999999
Sell RAM->EOS 10000000000
Sell RAM->EOS 9999999998
Sell RAM->EOS 10000000000
Sell RAM->EOS 9999999999
Sell RAM->EOS 10000000000
Sell RAM->EOS 10000000000
Sell RAM->EOS 10000000001
符合预期,剩余资源越少,价格越高的需求
参考
Windows10 WSL 开启 ssh,CLion远程调试
由于Linux代码调试需要,如果当前开发系统是windows的话,可以选择使用CLion 远程链接 WSL。
所以需要子系统开启ssh
安装 ssh
sudo apt-get install openssh-server
Linux 开启密码登录
sudo vim /etc/ssh/sshd_config
找到passwordAuthentication
项,修改成yes
重启ssh服务
sudo service sshd restart
查看服务状态
service ssh status
# * sshd is running 显示此内容则表示启动正常
如果提示 sshd error: could not load host key
则需要重新生成 key
dpkg-reconfigure openssh-server
如需密码设置
sudo passwd user-name
如果启动sshd时,报“Could not load host key”
Could not load host key: /etc/ssh/ssh_host_rsa_key
Could not load host key: /etc/ssh/ssh_host_ecdsa_key
Could not load host key: /etc/ssh/ssh_host_ed25519_key
查看下文件是否存在
ll /etc/ssh/
解决方法,重新生成密钥文件
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
Clion中子系统配置请参考《Clion Windows Linux子系统》
如果启动报 ssh:unrecognized service
sudo /etc/init.d/ssh restart
sudo /etc/init.d/ssh start
ubuntu 安装 gdb
sudo apt update
sudo apt install gdb
参考
https://www.jetbrains.com/help/clion/quick-tutorial-on-configuring-clion-on-windows.html#WSL
https://www.cnblogs.com/netonline/p/7410586.html
https://blog.csdn.net/zhouzme/article/details/81087837
http://www.gdbtutorial.com/tutorial/how-install-gdb
EOS 部署合约出现 deadline ? exceeded by ?us
测试环境
OS: Ubuntu 18.04 server
EOS: v2.0.1
合约:v1.9.1
部署系统合约时出现以下错误
error 2020-02-07T03:05:55.178 cleos main.cpp:4042 main ] Failed with error: deadline 2020-02-07T03:05:55.175 exceeded by 43us (2)
deadline 2020-02-07T03:05:55.175 exceeded by 43us
跟下代码(跳转github)
#define FC_CHECK_DEADLINE( DEADLINE, ... ) \
FC_MULTILINE_MACRO_BEGIN \
if( DEADLINE < fc::time_point::maximum() && DEADLINE < fc::time_point::now() ) { \
auto log_mgs = FC_LOG_MESSAGE( error, "deadline ${d} exceeded by ${t}us ", \
FC_FORMAT_ARG_PARAMS(__VA_ARGS__)("d", DEADLINE)("t", fc::time_point::now() - DEADLINE) ); \
auto msg = log_mgs.get_limited_message(); \
throw timeout_exception( std::move( log_mgs ), timeout_exception_code, "timeout_exception", std::move( msg ) ); \
} \
FC_MULTILINE_MACRO_END
跟踪宏的调用 (跳转github)
string exception::to_string( log_level ll )const
{
const auto deadline = fc::time_point::now() + format_time_limit;
std::stringstream ss;
try {
ss << my->_what;
try {
ss << " (" << variant( my->_code ).as_string() << ")\n";
} catch( std::bad_alloc& ) {
throw;
} catch( ... ) {
ss << "<- exception in to_string.\n";
}
for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) {
try {
FC_CHECK_DEADLINE(deadline);
查看 main.cpp:4042
(跳转github)
if (!print_recognized_errors(e, verbose)) {
// Error is not recognized
if (!print_help_text(e) || verbose) {
elog("Failed with error: ${e}", ("e", verbose ? e.to_detail_string() : e.to_string()));
}
}
发现该异常,为解析异常错误导致的解析超时错误,并非当时真实的错误。
继续查找 https://github.com/EOSIO/eos/issues/8443
2.0和1.8.9包括新的选项http-max-response-time-ms,该选项有助于减轻api节点的滥用。它允许您指定处理请求的时间限制。当前,这意味着将响应转换为json所需的时间受到限制,这是大多数api请求中最耗时的部分。我们将默认值设为30毫秒,以匹配默认的max-transaction-time。对于大块,30ms可能不足以让您的节点转换为json。当然取决于硬件等。随时随地将它放置在任何级别,您可以满足任何一个处理请求的要求。
解决方法
将http-max-response-time-ms
参数修改为30毫秒
http-max-response-time-ms = 30
参考
https://github.com/EOSIO/eos/issues/8443
https://github.com/EOSIO/eos/releases/tag/v1.8.9