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

[move-stdlib] Add vector::move_range native function #14863

Merged
merged 2 commits into from
Nov 13, 2024

Conversation

igor-aptos
Copy link
Contributor

Description

Memcopy (i.e. ptr::copy_nonoverlapping inside of Vec) is extremely efficient, and using Vec operations that use it directly is significantly faster (orders of magnitude on bigger vectors) than issuing operations in move.

Operations on vector that can be speed-up: insert, remove, append, split_off.

To keep amount of native functions short, instead of having native for each of those, providing one more general native function: vector::move_range, which is enough to support all 4 of the above, in addition to other uses.

Internally, we shortcircuit a few special cases, for faster speed.

How Has This Been Tested?

Full performance evaluation is in the follow-up PR: #14862

Key Areas to Review

Type of Change

  • Performance improvement

Which Components or Systems Does This Change Impact?

  • Move/Aptos Virtual Machine

Checklist

  • I have read and followed the CONTRIBUTING doc
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I identified and added all stakeholders and component owners affected by this change as reviewers
  • I tested both happy and unhappy path of the functionality
  • I have made corresponding changes to the documentation

Copy link

trunk-io bot commented Oct 3, 2024

⏱️ 2h 43m total CI duration on this PR
Slowest 15 Jobs Cumulative Duration Recent Runs
rust-move-unit-coverage 16m 🟩
rust-move-unit-coverage 16m 🟩
rust-move-unit-coverage 16m 🟩
rust-move-unit-coverage 14m 🟩
rust-move-unit-coverage 12m 🟩
rust-move-unit-coverage 11m 🟩
rust-move-tests 10m 🟩
rust-move-tests 10m 🟩
rust-move-unit-coverage 10m
rust-move-tests 10m 🟥
rust-move-tests 10m 🟩
rust-move-tests 9m 🟩
rust-cargo-deny 9m 🟩🟩🟩🟩🟩
check-dynamic-deps 4m 🟩🟩🟩🟩🟩
general-lints 2m 🟩🟩🟩🟩🟩

settingsfeedbackdocs ⋅ learn more about trunk.io

Copy link

codecov bot commented Oct 3, 2024

Codecov Report

Attention: Patch coverage is 75.65217% with 28 lines in your changes missing coverage. Please review.

Project coverage is 60.1%. Comparing base (8b0d35b) to head (b36187b).

Files with missing lines Patch % Lines
...party/move/move-vm/types/src/values/values_impl.rs 61.7% 18 Missing ⚠️
...s-move/framework/move-stdlib/src/natives/vector.rs 84.3% 8 Missing ⚠️
...party/move/move-vm/runtime/src/native_functions.rs 88.2% 2 Missing ⚠️
Additional details and impacted files
@@                 Coverage Diff                  @@
##           igor/move_mem_swap   #14863    +/-   ##
====================================================
  Coverage                60.1%    60.1%            
====================================================
  Files                     857      858     +1     
  Lines                  211341   211455   +114     
====================================================
+ Hits                   127147   127233    +86     
- Misses                  84194    84222    +28     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@igor-aptos igor-aptos force-pushed the igor/vector_utilities branch from 2253183 to 0f08236 Compare October 4, 2024 16:59
@igor-aptos igor-aptos force-pushed the igor/native_vector_move_range branch 2 times, most recently from d724063 to e4540db Compare October 8, 2024 19:00
@igor-aptos igor-aptos changed the base branch from igor/vector_utilities to igor/move_mem_swap October 8, 2024 19:01
@igor-aptos igor-aptos force-pushed the igor/native_vector_move_range branch from b36187b to 5b9f388 Compare October 21, 2024 23:10
@igor-aptos igor-aptos requested a review from ziaptos October 21, 2024 23:28
@igor-aptos
Copy link
Contributor Author

updated PR with addressed comments

Copy link
Contributor

@ziaptos ziaptos left a comment

Choose a reason for hiding this comment

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

More like a question that I have before stamping this.

Comment on lines 2486 to 2473
// potentially unnecessary as native call should've checked the types already
// (unlike other vector functions that are bytecodes)
check_elem_layout(type_param, from_c)?;
check_elem_layout(type_param, to_c)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

That's a good question. It has the same indirect guarantees as the from_self != to_self.

@@ -81,8 +81,26 @@ impl NativeFunctions {
where
I: IntoIterator<Item = (AccountAddress, Identifier, Identifier, NativeFunction)>,
{
let vector_bytecode_instruction_methods = HashSet::from([
"empty",
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think there's a general reason to disallow these in MoveVM. I'd rather keep the filter in AptosVM. Is there any other reason for wanting to remove it from AptosVM?

@igor-aptos igor-aptos force-pushed the igor/native_vector_move_range branch from 5b9f388 to fc3c349 Compare November 8, 2024 23:21
@igor-aptos
Copy link
Contributor Author

addressed all comments. move the filtering back to AptosVM. added comment for redundant check

@igor-aptos igor-aptos requested a review from ziaptos November 12, 2024 15:57
@igor-aptos igor-aptos force-pushed the igor/native_vector_move_range branch from fc3c349 to 9e0fd82 Compare November 12, 2024 18:04
@igor-aptos igor-aptos force-pushed the igor/native_vector_move_range branch from 9e0fd82 to db496b3 Compare November 12, 2024 18:20
{
return Err(SafeNativeError::Abort {
abort_code: EINDEX_OUT_OF_BOUNDS,
});

This comment was marked as resolved.

Copy link
Contributor

@vgao1996 vgao1996 left a comment

Choose a reason for hiding this comment

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

The implementation looks correct.

I have a question though: what is the rationale to implement this rather complex move_range operation rather than splitting it up into two smaller ones,

  • one that removes a slice from a vector
  • one that inserts a slice into another vector
    ?

let mut from_v = $from.borrow_mut();
let mut to_v = $to.borrow_mut();

if removal_position.checked_add(length).map_or(true, |end| end > from_v.len())
Copy link
Contributor

Choose a reason for hiding this comment

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

Personally I find this condition a bit hard to read -- the info density may be a bit too high. No strong objection though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's basically
removal_position + length > from_v.len()
just with checked_add. Not sure how to write it cleaner. Introducing new variables seems even more confusing to me

@@ -41,5 +41,8 @@ crate::gas_schedule::macros::define_gas_parameters!(
[bcs_serialized_size_failure: InternalGas, { RELEASE_V1_18.. => "bcs.serialized_size.failure" }, 3676],

[mem_swap_base: InternalGas, { RELEASE_V1_24.. => "mem.swap.base" }, 1500],

[vector_move_range_base: InternalGas, { RELEASE_V1_24.. => "vector.move_range.base" }, 4000],
[vector_move_range_per_index_moved: InternalGasPerArg, { RELEASE_V1_24.. => "vector.move_range.per_index_moved" }, 10],
Copy link
Contributor

Choose a reason for hiding this comment

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

Wow this is pretty cheap. I hope you've done some crude benchmarks at least?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In #14862, more concretely these are the results: https://gist.github.com/igor-aptos/e8d4e21edcbc75dddcb9382d4e077665

but yeah, memcopy is extremely cheap

@igor-aptos
Copy link
Contributor Author

I have a question though: what is the rationale to implement this rather complex move_range operation rather than splitting it up into two smaller ones,

one that removes a slice from a vector
one that inserts a slice into another vector

For "one that removes a slice from a vector", where would it put it? in a new vector? if so - you would then need two memcopy's, instead of one - making it two times more expensive.

As far as I can tell:

to_v.splice(insert_position..insert_position, from_v.splice(removal_position..(removal_position + length), []))

is a single memcopy, as splice is lazy (happens on consumption / drop)

I could create 4 native functions (insert, remove, append, split_off), instead of 1, but that would be less general, and overall seems better to have fewer more powerful native functions, than many specialized ones?

Copy link
Contributor

@vgao1996 vgao1996 left a comment

Choose a reason for hiding this comment

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

@igor-aptos sounds good. I was dumb.

Copy link
Contributor

@ziaptos ziaptos left a comment

Choose a reason for hiding this comment

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

Did another pass - LGTM

@igor-aptos igor-aptos changed the base branch from igor/move_mem_swap to main November 13, 2024 19:01
@igor-aptos igor-aptos force-pushed the igor/native_vector_move_range branch from db496b3 to 43449cb Compare November 13, 2024 19:04
@igor-aptos igor-aptos enabled auto-merge (squash) November 13, 2024 19:09
@igor-aptos igor-aptos force-pushed the igor/native_vector_move_range branch from 23770a3 to ce5f67b Compare November 13, 2024 22:36

This comment has been minimized.

This comment has been minimized.

This comment has been minimized.

Copy link
Contributor

✅ Forge suite realistic_env_max_load success on ce5f67b97c66349ba73fed29b9135522425eb6d7

two traffics test: inner traffic : committed: 14370.59 txn/s, latency: 2769.75 ms, (p50: 2700 ms, p70: 2700, p90: 3000 ms, p99: 3900 ms), latency samples: 5464060
two traffics test : committed: 100.07 txn/s, latency: 1620.58 ms, (p50: 1300 ms, p70: 1400, p90: 1700 ms, p99: 9500 ms), latency samples: 1740
Latency breakdown for phase 0: ["MempoolToBlockCreation: max: 2.034, avg: 1.596", "ConsensusProposalToOrdered: max: 0.316, avg: 0.293", "ConsensusOrderedToCommit: max: 0.360, avg: 0.348", "ConsensusProposalToCommit: max: 0.653, avg: 0.641"]
Max non-epoch-change gap was: 0 rounds at version 0 (avg 0.00) [limit 4], 0.88s no progress at version 1644577 (avg 0.20s) [limit 15].
Max epoch-change gap was: 0 rounds at version 0 (avg 0.00) [limit 4], 8.62s no progress at version 5964515 (avg 8.49s) [limit 15].
Test Ok

Copy link
Contributor

✅ Forge suite framework_upgrade success on ea6e45f0eee4b6da2ebf93b9b89d269d334fcf70 ==> ce5f67b97c66349ba73fed29b9135522425eb6d7

Compatibility test results for ea6e45f0eee4b6da2ebf93b9b89d269d334fcf70 ==> ce5f67b97c66349ba73fed29b9135522425eb6d7 (PR)
Upgrade the nodes to version: ce5f67b97c66349ba73fed29b9135522425eb6d7
framework_upgrade::framework-upgrade::full-framework-upgrade : committed: 1359.03 txn/s, submitted: 1362.16 txn/s, failed submission: 3.13 txn/s, expired: 3.13 txn/s, latency: 2292.95 ms, (p50: 2100 ms, p70: 2100, p90: 3600 ms, p99: 5700 ms), latency samples: 121640
framework_upgrade::framework-upgrade::full-framework-upgrade : committed: 1271.66 txn/s, submitted: 1274.63 txn/s, failed submission: 2.96 txn/s, expired: 2.96 txn/s, latency: 2406.53 ms, (p50: 2100 ms, p70: 2600, p90: 4200 ms, p99: 5700 ms), latency samples: 111620
5. check swarm health
Compatibility test for ea6e45f0eee4b6da2ebf93b9b89d269d334fcf70 ==> ce5f67b97c66349ba73fed29b9135522425eb6d7 passed
Upgrade the remaining nodes to version: ce5f67b97c66349ba73fed29b9135522425eb6d7
framework_upgrade::framework-upgrade::full-framework-upgrade : committed: 1240.31 txn/s, submitted: 1241.46 txn/s, failed submission: 1.15 txn/s, expired: 1.15 txn/s, latency: 2527.60 ms, (p50: 2100 ms, p70: 2700, p90: 4200 ms, p99: 6300 ms), latency samples: 107760
Test Ok

Copy link
Contributor

✅ Forge suite compat success on ea6e45f0eee4b6da2ebf93b9b89d269d334fcf70 ==> ce5f67b97c66349ba73fed29b9135522425eb6d7

Compatibility test results for ea6e45f0eee4b6da2ebf93b9b89d269d334fcf70 ==> ce5f67b97c66349ba73fed29b9135522425eb6d7 (PR)
1. Check liveness of validators at old version: ea6e45f0eee4b6da2ebf93b9b89d269d334fcf70
compatibility::simple-validator-upgrade::liveness-check : committed: 13833.11 txn/s, latency: 2458.34 ms, (p50: 1600 ms, p70: 1700, p90: 2500 ms, p99: 22900 ms), latency samples: 511520
2. Upgrading first Validator to new version: ce5f67b97c66349ba73fed29b9135522425eb6d7
compatibility::simple-validator-upgrade::single-validator-upgrading : committed: 7667.72 txn/s, latency: 3736.52 ms, (p50: 4200 ms, p70: 4300, p90: 4500 ms, p99: 4600 ms), latency samples: 143860
compatibility::simple-validator-upgrade::single-validator-upgrade : committed: 6887.82 txn/s, latency: 4339.07 ms, (p50: 4600 ms, p70: 4600, p90: 4700 ms, p99: 6200 ms), latency samples: 261340
3. Upgrading rest of first batch to new version: ce5f67b97c66349ba73fed29b9135522425eb6d7
compatibility::simple-validator-upgrade::half-validator-upgrading : committed: 7265.61 txn/s, latency: 3799.33 ms, (p50: 3900 ms, p70: 4300, p90: 5300 ms, p99: 5700 ms), latency samples: 135300
compatibility::simple-validator-upgrade::half-validator-upgrade : committed: 7398.03 txn/s, latency: 4355.64 ms, (p50: 4500 ms, p70: 4800, p90: 6000 ms, p99: 6300 ms), latency samples: 248300
4. upgrading second batch to new version: ce5f67b97c66349ba73fed29b9135522425eb6d7
compatibility::simple-validator-upgrade::rest-validator-upgrading : committed: 11407.44 txn/s, latency: 2420.97 ms, (p50: 2400 ms, p70: 2900, p90: 3400 ms, p99: 3600 ms), latency samples: 201360
compatibility::simple-validator-upgrade::rest-validator-upgrade : committed: 4301.75 txn/s, submitted: 4301.89 txn/s, expired: 0.14 txn/s, latency: 3061.16 ms, (p50: 2500 ms, p70: 3200, p90: 6200 ms, p99: 7500 ms), latency samples: 343149
5. check swarm health
Compatibility test for ea6e45f0eee4b6da2ebf93b9b89d269d334fcf70 ==> ce5f67b97c66349ba73fed29b9135522425eb6d7 passed
Test Ok

@igor-aptos igor-aptos merged commit 61e6563 into main Nov 13, 2024
46 checks passed
@igor-aptos igor-aptos deleted the igor/native_vector_move_range branch November 13, 2024 23:10
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.

4 participants