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

Replace serde json wasm #312

Closed
wants to merge 6 commits into from
Closed

Conversation

webmaster128
Copy link
Member

@webmaster128 webmaster128 commented Apr 30, 2020

Closes #110

At webmaster128/serde_json_wasm#1 there is a diff showing what needs to be done to remote float instructions from serde_json. I think this does the job.

  • Patch serde_json and integrate
  • Publish fork as replace git reference with crates.io package

@webmaster128 webmaster128 requested a review from ethanfrey April 30, 2020 13:46
@@ -29,7 +29,7 @@ backtraces = ["snafu/backtraces"]

[dependencies]
base64 = "0.11.0"
serde-json-wasm = "0.1.2"
serde_json = { git = "https://github.com/webmaster128/serde_json_wasm", branch="float-feature" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow. I need to look at this.

Can you put this repo under confio or cosmwasm? Let me know if you need permissions.

Two main questions:

  • it seems you recompiled the contract and it worked with check_wasm. Awesome!
  • gas was not affected significantly:+1:
  • this increased contract size by 70kb. I wonder if you can do some size profiling. I used twilly on the output before wasm-opt. Eg just compile with the rustflags argument and see what is taking up the space... maybe there is something easy to trim out

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current state is that cargo wasm works perfectly but cargo +nightly wasm still has disallowed instructions in it. I think it is related to how the different compilers handle the many #[inline] statements from the 'serde-rs/json'. I'm in the process of kicking out much more code. Let's see

@webmaster128
Copy link
Member Author

No matter what I do, starting from Rust 1.43 a seemingly unused function is created

(func $_ZN4core3fmt5float52_$LT$impl$u20$core..fmt..Display$u20$for$u20$f64$GT$3fmt17h0f5e2db0ac6eccddE (type 1) (param i32 i32) (result i32)

which then calls

  (func $_ZN4core3fmt5float29float_to_decimal_common_exact17hd8511abc64c7c0afE (type 14) (param i32 f64 i32 i32) (result i32)
    (local i32 i64 i32 i64 i32 i64 i64 i64 i32 i32 i32)
    global.get 0
    i32.const 1136
    i32.sub
    local.tee 4
    global.set 0
    block  ;; label = @1
      block  ;; label = @2
        local.get 1
        i64.reinterpret_f64
        local.tee 5
        i64.const 9223372036854775807
        i64.and
        i64.eqz
        i32.eqz
        br_if 0 (;@2;)
        i32.const 4
        local.set 6
        br 1 (;@1;)
      end
      local.get 5
      i64.const 4503599627370495

where we get the float instructions from. My old Rust stable did not have this issue.

@webmaster128
Copy link
Member Author

webmaster128 commented May 3, 2020

Turns out that an implementation of float_to_decimal_common_exact was included in both Rust versions, but between 1.42.0 and 1.43.0 the Wasm output changed. In the libcore source diff I don't see a significant difference. The changed Wasm instructions look like an optimization, where the reference to the number was a pointer before and is the actual value now:

Bildschirmfoto 2020-05-03 um 17 21 10

Look at the second parameter as well as the code around local.get 1.


That explains the difference between the old stable builds and the nightly builds. No idea if we can trace down where impl Display for f32 { and impl Display for f64 { are used.

@webmaster128
Copy link
Member Author

@ethanfrey this is more or less what I do to test the resulting instructions from a local version of serde_json:

# - Checkout serde_json_wasm next to cosmwasm
# - Delete local replace-serde-json-wasm if it exists and is outdated. Simon does happy rabasing on this branch.
$ git fetch --all && git checkout replace-serde-json-wasm
$ cd contracts/hackatom
$ echo "" >> Cargo.toml
$ echo "[patch.crates-io]" >> Cargo.toml
$ echo "serde_json = { path = '../../../serde_json_wasm' }" >> Cargo.toml
$ echo "" >> Cargo.toml
$ echo "[patch.'https://github.com/webmaster128/serde_json_wasm']" >> Cargo.toml
$ echo "serde_json = { path = '../../../serde_json_wasm' }" >> Cargo.toml
$ cargo wasm
$ wasm2wat target/wasm32-unknown-unknown/release/hackatom.wasm | grep 'float_to_decimal_common_exact' -C 40
$ wasm2wat target/wasm32-unknown-unknown/release/hackatom.wasm | grep 'f64' -C 20

@webmaster128 webmaster128 mentioned this pull request May 6, 2020
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reconsider or fix json lib
2 participants