diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 80e260f65d6..063379e37c3 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -312,7 +312,7 @@ struct controller_impl { cfg.reversible_cache_size, false, cfg.db_map_mode, cfg.db_hugepage_paths ), blog( cfg.blog ), fork_db( cfg.state_dir ), - wasmif( cfg.wasm_runtime, cfg.eosvmoc_tierup, db, cfg.state_dir, cfg.eosvmoc_config ), + wasmif( cfg.wasm_runtime, cfg.eosvmoc_tierup, db, cfg.state_dir, cfg.eosvmoc_config, !cfg.profile_accounts.empty() ), resource_limits( db, [&s]() { return s.get_deep_mind_logger(); }), authorization( s, db ), protocol_features( std::move(pfs), [&s]() { return s.get_deep_mind_logger(); } ), @@ -3247,6 +3247,10 @@ bool controller::contracts_console()const { return my->conf.contracts_console; } +bool controller::is_profiling(account_name account) const { + return my->conf.profile_accounts.find(account) != my->conf.profile_accounts.end(); +} + chain_id_type controller::get_chain_id()const { return my->chain_id; } diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index fc3253f7241..133aafd6a24 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -100,6 +100,8 @@ namespace eosio { namespace chain { flat_set resource_greylist; flat_set trusted_producers; uint32_t greylist_limit = chain::config::maximum_elastic_resource_multiplier; + + flat_set profile_accounts; }; enum class block_status { @@ -289,6 +291,8 @@ namespace eosio { namespace chain { bool contracts_console()const; + bool is_profiling(account_name name) const; + chain_id_type get_chain_id()const; db_read_mode get_read_mode()const; diff --git a/libraries/chain/include/eosio/chain/wasm_interface.hpp b/libraries/chain/include/eosio/chain/wasm_interface.hpp index 8b08a4edb58..48b6c365dfb 100644 --- a/libraries/chain/include/eosio/chain/wasm_interface.hpp +++ b/libraries/chain/include/eosio/chain/wasm_interface.hpp @@ -44,7 +44,7 @@ namespace eosio { namespace chain { } } - wasm_interface(vm_type vm, bool eosvmoc_tierup, const chainbase::database& d, const boost::filesystem::path data_dir, const eosvmoc::config& eosvmoc_config); + wasm_interface(vm_type vm, bool eosvmoc_tierup, const chainbase::database& d, const boost::filesystem::path data_dir, const eosvmoc::config& eosvmoc_config, bool profile); ~wasm_interface(); //call before dtor to skip what can be minutes of dtor overhead with some runtimes; can cause leaks diff --git a/libraries/chain/include/eosio/chain/wasm_interface_private.hpp b/libraries/chain/include/eosio/chain/wasm_interface_private.hpp index 3e15ed824de..df0a98cadc7 100644 --- a/libraries/chain/include/eosio/chain/wasm_interface_private.hpp +++ b/libraries/chain/include/eosio/chain/wasm_interface_private.hpp @@ -58,13 +58,17 @@ namespace eosio { namespace chain { }; #endif - wasm_interface_impl(wasm_interface::vm_type vm, bool eosvmoc_tierup, const chainbase::database& d, const boost::filesystem::path data_dir, const eosvmoc::config& eosvmoc_config) : db(d), wasm_runtime_time(vm) { + wasm_interface_impl(wasm_interface::vm_type vm, bool eosvmoc_tierup, const chainbase::database& d, const boost::filesystem::path data_dir, const eosvmoc::config& eosvmoc_config, bool profile) : db(d), wasm_runtime_time(vm) { #ifdef EOSIO_EOS_VM_RUNTIME_ENABLED if(vm == wasm_interface::vm_type::eos_vm) runtime_interface = std::make_unique>(); #endif #ifdef EOSIO_EOS_VM_JIT_RUNTIME_ENABLED - if(vm == wasm_interface::vm_type::eos_vm_jit) + if(vm == wasm_interface::vm_type::eos_vm_jit && profile) { + eosio::vm::set_profile_interval_us(200); + runtime_interface = std::make_unique(); + } + if(vm == wasm_interface::vm_type::eos_vm_jit && !profile) runtime_interface = std::make_unique>(); #endif #ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED @@ -86,7 +90,7 @@ namespace eosio { namespace chain { if(is_shutting_down) for(wasm_cache_index::iterator it = wasm_instantiation_cache.begin(); it != wasm_instantiation_cache.end(); ++it) wasm_instantiation_cache.modify(it, [](wasm_cache_entry& e) { - e.module.release(); + e.module.release()->fast_shutdown(); }); } diff --git a/libraries/chain/include/eosio/chain/webassembly/common.hpp b/libraries/chain/include/eosio/chain/webassembly/common.hpp index 699ba8a598c..a359dca823f 100644 --- a/libraries/chain/include/eosio/chain/webassembly/common.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/common.hpp @@ -58,57 +58,56 @@ namespace eosio { namespace chain { }; // define the type converter for eosio - struct type_converter : public eosio::vm::type_converter { - using base_type = eosio::vm::type_converter; - using base_type::type_converter; + template + struct basic_type_converter : public eosio::vm::type_converter { + using base_type = eosio::vm::type_converter; + using base_type::base_type; using base_type::from_wasm; using base_type::to_wasm; - using base_type::as_value; - using base_type::as_result; - using base_type::elem_type; - using base_type::get_host; - - EOS_VM_FROM_WASM(memcpy_params, (void* dst, const void* src, vm::wasm_size_t size)) { - validate_pointer(dst, size); - validate_pointer(src, size); - validate_pointer(dst, 1); - return { dst, src, size }; + + EOS_VM_FROM_WASM(bool, (uint32_t value)) { return value ? 1 : 0; } + + EOS_VM_FROM_WASM(memcpy_params, (vm::wasm_ptr_t dst, vm::wasm_ptr_t src, vm::wasm_size_t size)) { + auto d = this->template validate_pointer(dst, size); + auto s = this->template validate_pointer(src, size); + this->template validate_pointer(dst, 1); + return { d, s, size }; } - EOS_VM_FROM_WASM(memcmp_params, (const void* lhs, const void* rhs, vm::wasm_size_t size)) { - validate_pointer(lhs, size); - validate_pointer(rhs, size); - return { lhs, rhs, size }; + EOS_VM_FROM_WASM(memcmp_params, (vm::wasm_ptr_t lhs, vm::wasm_ptr_t rhs, vm::wasm_size_t size)) { + auto l = this->template validate_pointer(lhs, size); + auto r = this->template validate_pointer(rhs, size); + return { l, r, size }; } - EOS_VM_FROM_WASM(memset_params, (void* dst, int32_t val, vm::wasm_size_t size)) { - validate_pointer(dst, size); - validate_pointer(dst, 1); - return { dst, val, size }; + EOS_VM_FROM_WASM(memset_params, (vm::wasm_ptr_t dst, int32_t val, vm::wasm_size_t size)) { + auto d = this->template validate_pointer(dst, size); + this->template validate_pointer(dst, 1); + return { d, val, size }; } template - auto from_wasm(void* ptr) const + auto from_wasm(vm::wasm_ptr_t ptr) const -> std::enable_if_t< std::is_pointer_v, vm::argument_proxy > { - validate_pointer>(ptr, 1); - return {ptr}; + auto p = this->template validate_pointer>(ptr, 1); + return {p}; } template - auto from_wasm(void* ptr, vm::tag = {}) const + auto from_wasm(vm::wasm_ptr_t ptr, vm::tag = {}) const -> std::enable_if_t< vm::is_argument_proxy_type_v && std::is_pointer_v, T> { if constexpr(T::is_legacy()) { - EOS_ASSERT(ptr != this->get_interface().get_memory(), wasm_execution_error, "references cannot be created for null pointers"); + EOS_ASSERT(ptr != 0, wasm_execution_error, "references cannot be created for null pointers"); } - this->template validate_pointer(ptr, 1); - return {ptr}; + auto p = this->template validate_pointer(ptr, 1); + return {p}; } - EOS_VM_FROM_WASM(null_terminated_ptr, (const void* ptr)) { - validate_null_terminated_pointer(ptr); - return {static_cast(ptr)}; + EOS_VM_FROM_WASM(null_terminated_ptr, (vm::wasm_ptr_t ptr)) { + auto p = this->validate_null_terminated_pointer(ptr); + return {static_cast(p)}; } EOS_VM_FROM_WASM(name, (uint64_t e)) { return name{e}; } uint64_t to_wasm(name&& n) { return n.to_uint64_t(); } @@ -116,6 +115,8 @@ namespace eosio { namespace chain { EOS_VM_FROM_WASM(float64_t, (double f)) { return ::to_softfloat64(f); } }; + using type_converter = basic_type_converter; + using eos_vm_host_functions_t = eosio::vm::registered_host_functions; diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc.hpp index bf672c35eb5..76697b22077 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc.hpp @@ -185,82 +185,27 @@ struct wasm_function_type_provider { struct eos_vm_oc_execution_interface { inline const auto& operand_from_back(std::size_t index) const { return *(os - index - 1); } - eosio::vm::native_value* os; -}; - -struct eos_vm_oc_type_converter : public eosio::vm::type_converter { - using base_type = eosio::vm::type_converter; - using base_type::type_converter; - using base_type::to_wasm; - using base_type::as_result; - using base_type::get_host; - - EOS_VM_FROM_WASM(bool, (uint32_t value)) { return value ? 1 : 0; } - - EOS_VM_FROM_WASM(memcpy_params, (vm::wasm_ptr_t dst, vm::wasm_ptr_t src, vm::wasm_size_t size)) { - auto d = array_ptr_impl(dst, size); - auto s = array_ptr_impl(src, size); - array_ptr_impl(dst, 1); - return { d, s, size }; - } - - EOS_VM_FROM_WASM(memcmp_params, (vm::wasm_ptr_t lhs, vm::wasm_ptr_t rhs, vm::wasm_size_t size)) { - auto l = array_ptr_impl(lhs, size); - auto r = array_ptr_impl(rhs, size); - return { l, r, size }; - } - - EOS_VM_FROM_WASM(memset_params, (vm::wasm_ptr_t dst, int32_t val, vm::wasm_size_t size)) { - auto d = array_ptr_impl(dst, size); - array_ptr_impl(dst, 1); - return { d, val, size }; - } template - auto from_wasm(vm::wasm_ptr_t ptr) const - -> std::enable_if_t< std::is_pointer_v, - vm::argument_proxy > { - void* p = array_ptr_impl>(ptr, 1); - return {p}; + inline void* validate_pointer(vm::wasm_ptr_t ptr, vm::wasm_size_t len) const { + return array_ptr_impl(ptr, len); } - template - auto from_wasm(vm::wasm_ptr_t ptr, vm::wasm_size_t len, vm::tag = {}) const - -> std::enable_if_t, T> { - void* p = array_ptr_impl(ptr, len); - return {static_cast(p), len}; + inline void* validate_null_terminated_pointer(vm::wasm_ptr_t ptr) const { + return null_terminated_ptr_impl(ptr); } - template - auto from_wasm(vm::wasm_ptr_t ptr, vm::wasm_size_t len, vm::tag = {}) const - -> std::enable_if_t< vm::is_argument_proxy_type_v && - vm::is_span_type_v, T> { - void* p = array_ptr_impl(ptr, len); - return {p, len}; - } + eosio::vm::native_value* os; +}; - template - auto from_wasm(vm::wasm_ptr_t ptr, vm::tag = {}) const - -> std::enable_if_t< vm::is_argument_proxy_type_v && - std::is_pointer_v, T> { - if constexpr(T::is_legacy()) { - EOS_ASSERT(ptr != 0, wasm_execution_error, "references cannot be created for null pointers"); - } - void* p = array_ptr_impl(ptr, 1); - return {p}; - } +struct eos_vm_oc_type_converter : public basic_type_converter { + using base_type = basic_type_converter; + using base_type::basic_type_converter; + using base_type::to_wasm; - EOS_VM_FROM_WASM(null_terminated_ptr, (vm::wasm_ptr_t ptr)) { - auto p = null_terminated_ptr_impl(ptr); - return {static_cast(p)}; - } - EOS_VM_FROM_WASM(name, (uint64_t e)) { return name{e}; } - uint64_t to_wasm(name&& n) { return n.to_uint64_t(); } vm::wasm_ptr_t to_wasm(void*&& ptr) { return convert_native_to_wasm(static_cast(ptr)); } - EOS_VM_FROM_WASM(float32_t, (float f)) { return ::to_softfloat32(f); } - EOS_VM_FROM_WASM(float64_t, (double f)) { return ::to_softfloat64(f); } template inline decltype(auto) as_value(const vm::native_value& val) const { diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm.hpp index 6f4bf2ceccd..03af69ba096 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm.hpp @@ -10,6 +10,7 @@ //eos-vm includes #include +#include namespace eosio { namespace chain { namespace webassembly { namespace eos_vm_runtime { @@ -18,7 +19,7 @@ struct apply_options; }} template -using eos_vm_backend_t = eosio::vm::backend; +using eos_vm_backend_t = eosio::vm::backend; template using eos_vm_null_backend_t = eosio::vm::backend; @@ -34,6 +35,10 @@ void validate(const bytes& code, const wasm_config& cfg, const whitelisted_intri struct apply_options; +struct profile_config { + boost::container::flat_set accounts_to_profile; +}; + template class eos_vm_runtime : public eosio::chain::wasm_runtime_interface { public: @@ -54,4 +59,14 @@ class eos_vm_runtime : public eosio::chain::wasm_runtime_interface { friend class eos_vm_instantiated_module; }; +class eos_vm_profile_runtime : public eosio::chain::wasm_runtime_interface { + public: + eos_vm_profile_runtime(); + bool inject_module(IR::Module&) override; + std::unique_ptr instantiate_module(const char* code_bytes, size_t code_size, std::vector, + const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version) override; + + void immediately_exit_currently_running_module() override; +}; + }}}}// eosio::chain::webassembly::eos_vm_runtime diff --git a/libraries/chain/include/eosio/chain/webassembly/runtime_interface.hpp b/libraries/chain/include/eosio/chain/webassembly/runtime_interface.hpp index 882ea2169da..b75b53adf2c 100644 --- a/libraries/chain/include/eosio/chain/webassembly/runtime_interface.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/runtime_interface.hpp @@ -13,6 +13,7 @@ class apply_context; class wasm_instantiated_module_interface { public: virtual void apply(apply_context& context) = 0; + virtual void fast_shutdown() {} virtual ~wasm_instantiated_module_interface(); }; diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index 5a53207bc3a..7a35ec0ca8a 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -33,8 +33,8 @@ namespace eosio { namespace chain { - wasm_interface::wasm_interface(vm_type vm, bool eosvmoc_tierup, const chainbase::database& d, const boost::filesystem::path data_dir, const eosvmoc::config& eosvmoc_config) - : my( new wasm_interface_impl(vm, eosvmoc_tierup, d, data_dir, eosvmoc_config) ) {} + wasm_interface::wasm_interface(vm_type vm, bool eosvmoc_tierup, const chainbase::database& d, const boost::filesystem::path data_dir, const eosvmoc::config& eosvmoc_config, bool profile) + : my( new wasm_interface_impl(vm, eosvmoc_tierup, d, data_dir, eosvmoc_config, profile) ) {} wasm_interface::~wasm_interface() {} diff --git a/libraries/chain/webassembly/runtimes/eos-vm.cpp b/libraries/chain/webassembly/runtimes/eos-vm.cpp index 1c53b62d654..7572bf53872 100644 --- a/libraries/chain/webassembly/runtimes/eos-vm.cpp +++ b/libraries/chain/webassembly/runtimes/eos-vm.cpp @@ -162,6 +162,72 @@ class eos_vm_instantiated_module : public wasm_instantiated_module_interface { std::unique_ptr _instantiated_module; }; +class eos_vm_profiling_module : public wasm_instantiated_module_interface { + using backend_t = eosio::vm::backend; + public: + eos_vm_profiling_module(std::unique_ptr mod, const char * code, std::size_t code_size) : + _instantiated_module(std::move(mod)), + _original_code(code, code + code_size) {} + + + void apply(apply_context& context) override { + _instantiated_module->set_wasm_allocator(&context.control.get_wasm_allocator()); + apply_options opts; + if(context.control.is_builtin_activated(builtin_protocol_feature_t::configurable_wasm_limits)) { + const wasm_config& config = context.control.get_global_properties().wasm_configuration; + opts = {config.max_pages, config.max_call_depth}; + } + auto fn = [&]() { + eosio::chain::webassembly::interface iface(context); + _instantiated_module->initialize(&iface, opts); + _instantiated_module->call( + iface, "env", "apply", + context.get_receiver().to_uint64_t(), + context.get_action().account.to_uint64_t(), + context.get_action().name.to_uint64_t()); + }; + profile_data* prof = start(context); + try { + scoped_profile profile_runner(prof); + checktime_watchdog wd(context.trx_context.transaction_timer); + _instantiated_module->timed_run(wd, fn); + } catch(eosio::vm::timeout_exception&) { + context.trx_context.checktime(); + } catch(eosio::vm::wasm_memory_exception& e) { + FC_THROW_EXCEPTION(wasm_execution_error, "access violation"); + } catch(eosio::vm::exception& e) { + FC_THROW_EXCEPTION(wasm_execution_error, "eos-vm system failure"); + } + } + + void fast_shutdown() override { + _prof.clear(); + } + + profile_data* start(apply_context& context) { + name account = context.get_receiver(); + if(!context.control.is_profiling(account)) return nullptr; + if(auto it = _prof.find(account); it != _prof.end()) { + return it->second.get(); + } else { + auto code_sequence = context.control.db().get(account).code_sequence; + std::string basename = account.to_string() + "." + std::to_string(code_sequence); + auto prof = std::make_unique(basename + ".profile", *_instantiated_module); + auto [pos,_] = _prof.insert(std::pair{ account, std::move(prof)}); + std::ofstream outfile(basename + ".wasm"); + outfile.write(_original_code.data(), _original_code.size()); + return pos->second.get(); + } + return nullptr; + } + + private: + + std::unique_ptr _instantiated_module; + boost::container::flat_map> _prof; + std::vector _original_code; +}; + template eos_vm_runtime::eos_vm_runtime() {} @@ -195,6 +261,32 @@ std::unique_ptr eos_vm_runtime::instan template class eos_vm_runtime; template class eos_vm_runtime; +eos_vm_profile_runtime::eos_vm_profile_runtime() {} + +void eos_vm_profile_runtime::immediately_exit_currently_running_module() { + throw wasm_exit{}; +} + +bool eos_vm_profile_runtime::inject_module(IR::Module& module) { + return false; +} + +std::unique_ptr eos_vm_profile_runtime::instantiate_module(const char* code_bytes, size_t code_size, std::vector, + const digest_type&, const uint8_t&, const uint8_t&) { + + using backend_t = eosio::vm::backend; + try { + wasm_code_ptr code((uint8_t*)code_bytes, code_size); + apply_options options = { .max_pages = 65536, + .max_call_depth = 0 }; + std::unique_ptr bkend = std::make_unique(code, code_size, nullptr, options); + eos_vm_host_functions_t::resolve(bkend->get_module()); + return std::make_unique(std::move(bkend), code_bytes, code_size); + } catch(eosio::vm::exception& e) { + FC_THROW_EXCEPTION(wasm_execution_error, "Error building eos-vm interp: ${e}", ("e", e.what())); + } +} + } template diff --git a/libraries/eos-vm b/libraries/eos-vm index 5f5cf516465..7d393f438f8 160000 --- a/libraries/eos-vm +++ b/libraries/eos-vm @@ -1 +1 @@ -Subproject commit 5f5cf516465d6c6b9f212a99651ffe3b28760462 +Subproject commit 7d393f438f8c99229beac8827e6dce4bd3259aa7 diff --git a/libraries/rodeos/embedded_rodeos.cpp b/libraries/rodeos/embedded_rodeos.cpp index f5f560624d1..f1cfce84040 100644 --- a/libraries/rodeos/embedded_rodeos.cpp +++ b/libraries/rodeos/embedded_rodeos.cpp @@ -193,7 +193,7 @@ extern "C" rodeos_bool rodeos_write_deltas(rodeos_error* error, rodeos_db_snapsh extern "C" rodeos_filter* rodeos_create_filter(rodeos_error* error, uint64_t name, const char* wasm_filename) { return handle_exceptions(error, nullptr, [&]() -> rodeos_filter* { // - return std::make_unique(eosio::name{ name }, wasm_filename).release(); + return std::make_unique(eosio::name{ name }, wasm_filename, false).release(); }); } diff --git a/libraries/rodeos/include/b1/rodeos/filter.hpp b/libraries/rodeos/include/b1/rodeos/filter.hpp index 8b4b405d288..c157fffd634 100644 --- a/libraries/rodeos/include/b1/rodeos/filter.hpp +++ b/libraries/rodeos/include/b1/rodeos/filter.hpp @@ -15,7 +15,7 @@ namespace b1::rodeos::filter { struct callbacks; using rhf_t = registered_host_functions; -using backend_t = eosio::vm::backend; +using backend_t = eosio::vm::backend; struct filter_state : b1::rodeos::data_state, b1::rodeos::console_state, b1::rodeos::filter_callback_state { eosio::vm::wasm_allocator wa = {}; diff --git a/libraries/rodeos/include/b1/rodeos/rodeos.hpp b/libraries/rodeos/include/b1/rodeos/rodeos.hpp index 6188c8daea0..6cac39aad52 100644 --- a/libraries/rodeos/include/b1/rodeos/rodeos.hpp +++ b/libraries/rodeos/include/b1/rodeos/rodeos.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include namespace b1::rodeos { @@ -73,8 +74,9 @@ struct rodeos_filter { eosio::name name = {}; std::unique_ptr backend = {}; std::unique_ptr filter_state = {}; + std::unique_ptr prof = {}; - rodeos_filter(eosio::name name, const std::string& wasm_filename); + rodeos_filter(eosio::name name, const std::string& wasm_filename, bool profile); void process(rodeos_db_snapshot& snapshot, const eosio::ship_protocol::get_blocks_result_base& result, eosio::input_stream bin, const std::function& push_data); diff --git a/libraries/rodeos/rodeos.cpp b/libraries/rodeos/rodeos.cpp index c9b443e67db..8930d36fd1b 100644 --- a/libraries/rodeos/rodeos.cpp +++ b/libraries/rodeos/rodeos.cpp @@ -238,7 +238,7 @@ void rodeos_db_snapshot::write_deltas(const ship_protocol::get_blocks_result_v1& std::once_flag registered_filter_callbacks; -rodeos_filter::rodeos_filter(eosio::name name, const std::string& wasm_filename) : name{ name } { +rodeos_filter::rodeos_filter(eosio::name name, const std::string& wasm_filename, bool profile) : name{ name } { std::call_once(registered_filter_callbacks, filter::register_callbacks); std::ifstream wasm_file(wasm_filename, std::ios::binary); @@ -256,6 +256,9 @@ rodeos_filter::rodeos_filter(eosio::name name, const std::string& wasm_filename) backend = std::make_unique(code, nullptr); filter_state = std::make_unique(); filter::rhf_t::resolve(backend->get_module()); + if (profile) { + prof = std::make_unique(wasm_filename + ".profile", *backend); + } } void rodeos_filter::process(rodeos_db_snapshot& snapshot, const ship_protocol::get_blocks_result_base& result, @@ -275,6 +278,7 @@ void rodeos_filter::process(rodeos_db_snapshot& snapshot, const ship_protocol::g backend->set_wasm_allocator(&filter_state->wa); backend->initialize(&cb); try { + eosio::vm::scoped_profile profile_runner(prof.get()); (*backend)(cb, "env", "apply", uint64_t(0), uint64_t(0), uint64_t(0)); if (!filter_state->console.empty()) diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 175d9812558..c71c498686a 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -263,6 +263,8 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip #endif })->default_value(eosio::chain::config::default_wasm_runtime, default_wasm_runtime_str), wasm_runtime_opt.c_str() ) + ("profile-account", boost::program_options::value>()->composing(), + "The name of an account whose code will be profiled") ("abi-serializer-max-time-ms", bpo::value()->default_value(config::default_abi_serializer_max_time_us / 1000), "Override default maximum ABI serialization time allowed in ms") ("chain-state-db-size-mb", bpo::value()->default_value(config::default_state_size / (1024 * 1024)), "Maximum size (in MiB) of the chain state database") @@ -758,6 +760,8 @@ void chain_plugin::plugin_initialize(const variables_map& options) { if( options.count( "wasm-runtime" )) my->wasm_runtime = options.at( "wasm-runtime" ).as(); + LOAD_VALUE_SET( options, "profile-account", my->chain_config->profile_accounts ); + if(options.count("abi-serializer-max-time-ms")) { my->abi_serializer_max_time_us = fc::microseconds(options.at("abi-serializer-max-time-ms").as() * 1000); my->chain_config->abi_serializer_max_time_us = my->abi_serializer_max_time_us; diff --git a/programs/rodeos/cloner_plugin.cpp b/programs/rodeos/cloner_plugin.cpp index 09f700dcd49..43de0904f39 100644 --- a/programs/rodeos/cloner_plugin.cpp +++ b/programs/rodeos/cloner_plugin.cpp @@ -34,6 +34,7 @@ struct cloner_config : ship_client::connection_config { bool exit_on_filter_wasm_error = false; eosio::name filter_name = {}; // todo: remove std::string filter_wasm = {}; // todo: remove + bool profile = false; }; struct cloner_plugin_impl : std::enable_shared_from_this { @@ -72,7 +73,7 @@ struct cloner_session : ship_client::connection_callbacks, std::enable_shared_fr cloner_session(cloner_plugin_impl* my) : my(my), config(my->config) { // todo: remove if (!config->filter_wasm.empty()) - filter = std::make_unique(config->filter_name, config->filter_wasm); + filter = std::make_unique(config->filter_name, config->filter_wasm, config->profile); } void connect(asio::io_context& ioc) { @@ -222,6 +223,7 @@ void cloner_plugin::set_program_options(options_description& cli, options_descri // todo: remove op("filter-name", bpo::value(), "Filter name"); op("filter-wasm", bpo::value(), "Filter wasm"); + op("profile-filter", bpo::bool_switch(), "Enable filter profiling"); } void cloner_plugin::plugin_initialize(const variables_map& options) { @@ -240,6 +242,7 @@ void cloner_plugin::plugin_initialize(const variables_map& options) { if (options.count("filter-name") && options.count("filter-wasm")) { my->config->filter_name = eosio::name{ options["filter-name"].as() }; my->config->filter_wasm = options["filter-wasm"].as(); + my->config->profile = options["profile-filter"].as(); } else if (options.count("filter-name") || options.count("filter-wasm")) { throw std::runtime_error("filter-name and filter-wasm must be used together"); } diff --git a/tests/rodeos_test.py b/tests/rodeos_test.py index b4a79b8c911..affdddf4813 100755 --- a/tests/rodeos_test.py +++ b/tests/rodeos_test.py @@ -121,7 +121,8 @@ def __enter__(self): def __exit__(self, exc_type, exc_value, traceback): if self.rodeos is not None: - self.rodeos.kill() + self.rodeos.send_signal(signal.SIGINT) + self.rodeos.wait() if self.rodeosStdout is not None: self.rodeosStdout.close() if self.rodeosStderr is not None: