Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fully switch to wasmer 1 by default #4076

Closed
matklad opened this issue Mar 11, 2021 · 28 comments
Closed

Fully switch to wasmer 1 by default #4076

matklad opened this issue Mar 11, 2021 · 28 comments
Assignees
Labels
T-SRE Team: issues relevant to the SRE team

Comments

@matklad
Copy link
Contributor

matklad commented Mar 11, 2021

In #3799, @ailisp implementing support for wasmer 1.0 🎉

However, we are still using wasmer 0.17 by default -- major upgrade of vm version is not a laughing matter, we must make sure that the two behave identically. This issue exists to track our progress on switching to wasmer 1.0 by default, and eventual removal of support for wasemer 0.17 from the tree.

The next step in transition is to deploy a fraction of nodes with wasmer1 to the beta net.

@matklad
Copy link
Contributor Author

matklad commented Mar 11, 2021

@ailisp am I correct that enabling wasmer1 is just cargo build --release --features wasmer1_default? Is anyone actively looking into deploying & monitoring that on betanet?

@matklad
Copy link
Contributor Author

matklad commented Mar 11, 2021

@bowenwang1996 is there anything else we can do besides "deploy to beta and observe" to make sure that transition goes smoothly?

@bowenwang1996
Copy link
Collaborator

@chefsale @mhalambek let's do the following:

  • Deploy a node on testnet and a node on mainnet using this commit 79f1732
  • Run them until the next release
  • Set up alerts to make sure we are notified when they crash

This should give us ~1 month of testing in production. @matklad are there other tests that you would like to see done?

@bowenwang1996 bowenwang1996 added the T-SRE Team: issues relevant to the SRE team label Mar 11, 2021
@ailisp
Copy link
Member

ailisp commented Mar 11, 2021

@matklad correct

@matklad
Copy link
Contributor Author

matklad commented Mar 12, 2021

are there other tests that you would like to see done?

If one node behaves OK, we should try to deploy half of the nodes, to make sure that network with mixed versions work.

@bowenwang1996
Copy link
Collaborator

If one node behaves OK, we should try to deploy half of the nodes, to make sure that network with mixed versions work.

I don't think that is needed because whether it works solely depends on the transactions, which means that it is sufficient to use a one-node canary that will apply all the transactions. Having more nodes does not improve testing coverage in this case.

@chefsale
Copy link
Contributor

I talked to @matklad, we wanted to create enable the wasmer1 based on the current release 1.18.0 and 1.18.1. They do not contain the wasmer changes. Even if we decide to create a build and run one node based of the commit: 79f1732, we still will need for the next release which includes this change.

So my proposal was to:

  1. actually wait until these changes cut an actual release, we make sure that that release without wasmer1 enabled is running fine
  2. create a release from that release 1.19.0-wasmer1 for example with the Make file cherry-picked on top which enables wasmer1
  3. Deploy on node with that release to mainnet and testnet
  4. Deploy that release on all of our nodes
  5. Make that release 1.19.1 and officially lets external people to use it.

I think this is most likely a safer approach, not sure how burning this is. cc: @matklad

@matklad
Copy link
Contributor Author

matklad commented Mar 18, 2021

Yes, I definitely agree that it's safer to release 1.19 without wasmer1, and than test wasmer1 on top of that, and that switch to wasmer in a separate (minor/patch) release.

That being said, deploying a node today from 79f1732 will help us to discover and fix bugs earlier. It won't affect when we ship, but it would improve the quality of what we ship, as more time will pass between last bug-fixes and actual deployment.

So, if that's not too difficult, I would prefer to have nodes from 79f1732 as an additional help.

@chefsale
Copy link
Contributor

Yes, in that case I will create a seperate branch from 79f1732 which enabled wasmer in the Makefile and we will deploy this.

@chefsale
Copy link
Contributor

Created a branch for the wasmer build: https://github.com/near/nearcore/tree/wasmer1-enabled

@chefsale
Copy link
Contributor

@chefsale
Copy link
Contributor

Please review: https://github.com/near/near-ops/pull/445. This is creating the wasmer1 enabled canaries. @bowenwang1996 @mhalambek @matklad

@chefsale
Copy link
Contributor

Machines are running:
rpc-prod => canary-wasmer-mainnet-rpc-node-kmqt
near-core => canary-wasmer-testnet-rpc-node-gtfp

but they die:

Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]: Mar 18 12:26:11.859  WARN near_rust_allocator_proxy::allocator: Thread 3102 reached new record of memory usage 512MiB
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:    0: <near_rust_allocator_proxy::allocator::MyAllocator as core::alloc::global::GlobalAlloc>::alloc
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/near-rust-allocator-proxy-0.2.8/src/allocator.rs:203:26
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:    1: __rg_alloc
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/builds/buildkite-i-00c4cecfed2f7980e-1/nearprotocol/nearcore-perf-release/neard/src/main.rs:26:1
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       alloc::alloc::alloc
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/alloc/src/alloc.rs:74:14
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       alloc::alloc::Global::alloc_impl
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/alloc/src/alloc.rs:153:73
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       <alloc::alloc::Global as core::alloc::AllocRef>::alloc
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/alloc/src/alloc.rs:203:9
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       alloc::raw_vec::RawVec<T,A>::allocate_in
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/alloc/src/raw_vec.rs:186:45
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       alloc::raw_vec::RawVec<T,A>::with_capacity_in
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/alloc/src/raw_vec.rs:161:9
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       alloc::raw_vec::RawVec<T>::with_capacity
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/alloc/src/raw_vec.rs:92:9
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       alloc::vec::Vec<T>::with_capacity
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/alloc/src/vec.rs:355:20
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       base64::decode::decode_config
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/base64-0.11.0/src/decode.rs:109:22
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       base64::decode::decode
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/base64-0.11.0/src/decode.rs:85:5
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       near_primitives_core::serialize::from_base64
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/builds/buildkite-i-00c4cecfed2f7980e-1/nearprotocol/nearcore-perf-release/core/primitives-core/src/serialize.r
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:    2: near_primitives_core::serialize::base64_format::deserialize
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/builds/buildkite-i-00c4cecfed2f7980e-1/nearprotocol/nearcore-perf-release/core/primitives-core/src/serialize.r
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:    3: <<<near_primitives::state_record::_::<impl serde::de::Deserialize for near_primitives::state_record::StateRecord>::deserialize::__Visitor as ser
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/builds/buildkite-i-00c4cecfed2f7980e-1/nearprotocol/nearcore-perf-release/core/primitives/src/state_record.rs:
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       <core::marker::PhantomData<T> as serde::de::DeserializeSeed>::deserialize
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.123/src/de/mod.rs:785:9
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       <serde_json::de::MapAccess<R> as serde::de::MapAccess>::next_value_seed
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.61/src/de.rs:1984:9
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       serde::de::MapAccess::next_value
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.123/src/de/mod.rs:1846:9
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       <<near_primitives::state_record::_::<impl serde::de::Deserialize for near_primitives::state_record::StateRecord>::deserialize::__Visitor as serd
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/builds/buildkite-i-00c4cecfed2f7980e-1/nearprotocol/nearcore-perf-release/core/primitives/src/state_record.rs:
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       <&mut serde_json::de::Deserializer<R> as serde::de::Deserializer>::deserialize_struct
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.61/src/de.rs:1817:31
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       <serde_json::de::VariantAccess<R> as serde::de::VariantAccess>::struct_variant
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.61/src/de.rs:2037:9
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       <near_primitives::state_record::_::<impl serde::de::Deserialize for near_primitives::state_record::StateRecord>::deserialize::__Visitor as serde
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/builds/buildkite-i-00c4cecfed2f7980e-1/nearprotocol/nearcore-perf-release/core/primitives/src/state_record.rs:
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:    4: <&mut serde_json::de::Deserializer<R> as serde::de::Deserializer>::deserialize_enum
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.61/src/de.rs:1850:38
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       near_primitives::state_record::_::<impl serde::de::Deserialize for near_primitives::state_record::StateRecord>::deserialize
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/builds/buildkite-i-00c4cecfed2f7980e-1/nearprotocol/nearcore-perf-release/core/primitives/src/state_record.rs:
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       <core::marker::PhantomData<T> as serde::de::DeserializeSeed>::deserialize
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.123/src/de/mod.rs:785:9
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       <serde_json::de::SeqAccess<R> as serde::de::SeqAccess>::next_element_seed
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:              at var/lib/buildkite-agent/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.61/src/de.rs:1925:37
Mar 18 12:26:11 canary-wasmer-testnet-rpc-node-gtfp sh[3099]:       serde::de::SeqAccess::next_element

cc: @matklad @ailisp

@bowenwang1996
Copy link
Collaborator

@chefsale can you post the reason why the crash? What you posted is just a stacktrace from memory stats, which does not indicate why the node crashed.

@chefsale
Copy link
Contributor

I mean the log is long, you can take a look at the full log at the machine: with journalctl -u neard, but the reason on the end says:

Mar 18 12:29:06 canary-wasmer-testnet-rpc-node-gtfp sh[14040]: Mar 18 12:29:06.617 ERROR near: DB version 17 is created by a newer version of neard, please update neard or delete data

I assume this is what you were looking for. The stacktrace from above is from this error i assume.

@bowenwang1996
Copy link
Collaborator

The stacktrace from above is from this error i assume.

No. As I said, it is the result of enabling memory_stats.

I assume this is what you were looking for.

Yes. This indicates that there is a database version mismatch, which is likely caused by you trying to run the node with a commit that has an older database version than what was run before. This has nothing to do with wasmer1. I'd suggest that you try a more recent commit.

@ailisp
Copy link
Member

ailisp commented Mar 18, 2021

The error is generated by CARGO_PROFILE_RELEASE_DEBUG=true. it can continue run after print these mem alloc > 512M fail error messages. Without this env var and rebuild there's no error.
The .near/data has a database version problem as mentioned by @bowenwang1996, so i copied key, config and genesis.json to .near2
Then observe top in combination of with/without .near2/data, wasmer0_default/wasmer1_default, wasmer1_default doesn't use more memory than wasmer0_default in peek and after peek, so I think this isn't an issue.
To make sure this is not related to wasmer1, I'll also check if previous commit/this commit with wasmer0_default, with CARGO_PROFILE_RELEASE_DEBUG=true, whether will it showing this error message, I think it will, because 512M is far less than the memory need for bootstrap a testnet node (top shows > 40% of 16G ram used at peek)

@ailisp
Copy link
Member

ailisp commented Mar 18, 2021

I just confirmed from build previous commit a637519 that this fail is not related to wasmer1. So there're two errors:

  1. large memory alloc warnings, which also happened in previous commit and this does not cause node crash. Also, we're okay with bootstrap a testnet node use high load of mem (and wasmer1 doesn't use more than wasmer0 node), this debug output is for observing memory consumption in long running node.
  2. database version error. This also unrelated to wasmer1, there's no database format change, can be resolved by @bowenwang1996 suggested way, or simply delete .near/data to let it create new version of database that state synced from other nodes, works too.

@chefsale
Copy link
Contributor

Machine on mainnet: canary-wasmer-mainnet-rpc-node-kmqt is running the version from commit: 79f1732 that is working.

I migrated testnet to the current master (rebased): https://github.com/near/nearcore/tree/wasmer1-enabled. It is running on the machine: canary-wasmer-testnet-rpc-node-jg6j working as well.

Let me know if you need anything else and when do we plan to start migrating testnet first. Probably give it a few days running first. cc: @matklad @ailisp @bowenwang1996

@matklad
Copy link
Contributor Author

matklad commented Mar 24, 2021

One important thing we need to do before switching to wasm 1.0 is auditing wasmer 1 error paths, to make sure that non-deterministic errors a-la OOM crash the node, instead of being treated as deterministic failure to execute the contract. We have this logic for wasmer 0.7 here, it needs to be updated to cover wasmer 1.0 as well.

@olonho volunteered to look into this, and maybe even write some fault-injection tests for this logic.

@bowenwang1996
Copy link
Collaborator

bowenwang1996 commented Apr 2, 2021

@matklad @chefsale I thought about this again and realized that what I said before didn't make sense. We should run more nodes with wasmer1 since this will increase the chance of nondeterministic errors happening and can help better test wasmer1. I suggest the following:

  • First, we switch all our testnet nodes to use wasmer1
  • If that works well, we switch all our mainnet nodes to use wasmer1.
  • If no issue is observed for more than 1 month, we can switch to wasmer1 by default.

What do you think?

@matklad
Copy link
Contributor Author

matklad commented Apr 2, 2021

How hard would it be to switch only half of nodes at a time? I fear cases where we need to rollback wasmer 1.0 due to some yet unknown issue, and, after rollback, realize that wasmer 0.17 is broken as well, because we didn't use it on the test net for some time.

Other than that, good idea. We probably need to merge #4181 first though (might be done with it today even?)

@bowenwang1996
Copy link
Collaborator

How hard would it be to switch only half of nodes at a time? I fear cases where we need to rollback wasmer 1.0 due to some yet unknown issue, and, after rollback, realize that wasmer 0.17 is broken as well, because we didn't use it on the test net for some time.

Sure we can do that

@matklad
Copy link
Contributor Author

matklad commented Apr 9, 2021

One more thing to do here: re-run params estimator, to makes sure that wasmer1 estimated fees are not worse than 0.17 fees. Note that we don't necessary want to lower the fees together with wasmer1. We can do that separately, as long as estimates are lower, and we might want to batch fees lowering with other changes, like addition of fees for contract compilation on deployment.

@matklad
Copy link
Contributor Author

matklad commented May 12, 2021

@ailisp @olonho @bowenwang1996 I realized there's an unresolved question about wasmer 1 rollout. Namely: should we switch to wasmer 1 in lockstep with enabling compilation on deploy, removing memory cache and upgrade costs?

Summary of the current state:

  • wasmer 0.17 is default, it has on-disk contract cache and in-memory contract cache. It doesn't have compilation on deployment.
  • wasmer 1.0 is not default, it has on-disk contract cache, but it doesn't have in-memory cache. It doesn't have compilation on deployment.

Cost measurements show that wasmer1 is not slower for all metrics (ref). Note that costs do not reflect in-memory cache -- during estimation, the cache is disabled.

I see three ways forward:

  1. we just flip default to wasmer1
  2. we add in-memory caching to wasmer1 and flip the default
  3. we don't add in-memory caching, we do enable precompilation, upgrade costs and switch to wasmer1

To me, it seems that option 2. is the safest, as it minimizes the diff with the current state, and doesn't requite protocol upgrade as it doesn't touch costs. So, do you agree that we should do the following?

checkbox list to make sure we have consensus:

@olonho
Copy link
Contributor

olonho commented May 13, 2021

Fine, let's make 4231 less intrusive. Also attached there latest costs update.

matklad added a commit to matklad/nearcore that referenced this issue May 13, 2021
This PR ports wasmer0 implementation of in-memory cache to wasme1 as
well.

The goal here is to keep the behavior between two wasmers as close as
possible. We absolutely do want to get rid of the in-memory cache, but
it's safer not to do that while also doing a major wasmer upgrade!

See near#4076 (comment)
for context
near-bulldozer bot pushed a commit that referenced this issue May 17, 2021
This PR ports wasmer0 implementation of in-memory cache to wasme1 as
well.

The goal here is to keep the behavior between two wasmers as close as
possible. We absolutely do want to get rid of the in-memory cache, but
it's safer not to do that while also doing a major wasmer upgrade!

See #4076 (comment)
for context

Test Plan
----------- 

```
$ cargo test -p near-vm-runner --features wasmer0_vm,wasmer1_vm,no_cache
$ $ cargo test -p near-vm-runner --features wasmer0_vm,wasmer1_vm
```
@bowenwang1996
Copy link
Collaborator

@matklad should we close this one given that we are now planning to move to wasmer2?

@matklad
Copy link
Contributor Author

matklad commented Jul 8, 2021

Yeah, let's close this for now: it's pretty clear that we need to do significant changes on the wasmer side before we can reconsider this, and that'll require re-starting the process here. In particular, wasmerio/wasmer#2329 is still outstanding.

@matklad matklad closed this as completed Jul 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-SRE Team: issues relevant to the SRE team
Projects
None yet
Development

No branches or pull requests

6 participants