From a10b5ae7534d270575d58c6647bdbbdb6fee7d8b Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 25 Sep 2024 08:57:32 -0700 Subject: [PATCH] [move][stdlib] Add vector::split_off and vector::remove library methods --- .../aptos-gas-calibration/src/measurements.rs | 20 +- .../src/measurements_helpers.rs | 20 +- aptos-move/aptos-vm-benchmarks/src/helper.rs | 20 +- aptos-move/e2e-benchmark/src/main.rs | 191 ++++++++++++++-- aptos-move/e2e-tests/src/executor.rs | 36 ++- .../framework/aptos-stdlib/doc/big_vector.md | 2 +- .../framework/move-stdlib/doc/features.md | 57 +++++ .../framework/move-stdlib/doc/vector.md | 137 +++++++++-- .../framework/move-stdlib/doc/vector_ext.md | 201 +++++++++++++++++ .../move-stdlib/sources/configs/features.move | 8 + .../framework/move-stdlib/sources/mem.move | 1 + .../framework/move-stdlib/sources/vector.move | 111 +++++++-- .../move-stdlib/tests/vector_tests.move | 35 ++- crates/transaction-generator-lib/src/args.rs | 18 ++ .../src/publishing/module_simple.rs | 73 ++++++ .../src/publishing/raw_module_data.rs | 213 ++++++++++++------ .../sources/vector_example.move | 47 ++++ testsuite/single_node_performance.py | 3 + 18 files changed, 1026 insertions(+), 167 deletions(-) create mode 100644 aptos-move/framework/move-stdlib/doc/vector_ext.md create mode 100644 testsuite/module-publish/src/packages/framework_usecases/sources/vector_example.move diff --git a/aptos-move/aptos-gas-calibration/src/measurements.rs b/aptos-move/aptos-gas-calibration/src/measurements.rs index fa0257ce29a0c..92b8688b141cb 100644 --- a/aptos-move/aptos-gas-calibration/src/measurements.rs +++ b/aptos-move/aptos-gas-calibration/src/measurements.rs @@ -162,15 +162,17 @@ fn compile_and_run_samples_ir( .equation_names .push(format!("{}::{}", &identifier, func_identifier.0)); - let elapsed = executor.exec_func_record_running_time( - &module_id, - &func_identifier.0, - vec![], - func_identifier.1.clone(), - iterations, - ExecFuncTimerDynamicArgs::NoArgs, - GasMeterType::UnmeteredGasMeter, - ); + let elapsed = executor + .exec_func_record_running_time( + &module_id, + &func_identifier.0, + vec![], + func_identifier.1.clone(), + iterations, + ExecFuncTimerDynamicArgs::NoArgs, + GasMeterType::UnmeteredGasMeter, + ) + .elapsed_micros; gas_measurement.regular_meter.push(elapsed); // record with abstract gas meter diff --git a/aptos-move/aptos-gas-calibration/src/measurements_helpers.rs b/aptos-move/aptos-gas-calibration/src/measurements_helpers.rs index 3f242b4457d4e..cfcc0952696a2 100644 --- a/aptos-move/aptos-gas-calibration/src/measurements_helpers.rs +++ b/aptos-move/aptos-gas-calibration/src/measurements_helpers.rs @@ -94,15 +94,17 @@ pub fn execute_user_txn( iterations: u64, args: Vec>, ) -> u128 { - let elapsed = executor.exec_func_record_running_time( - module_name, - function_name, - vec![], - args, - iterations, - ExecFuncTimerDynamicArgs::NoArgs, - GasMeterType::UnmeteredGasMeter, - ); + let elapsed = executor + .exec_func_record_running_time( + module_name, + function_name, + vec![], + args, + iterations, + ExecFuncTimerDynamicArgs::NoArgs, + GasMeterType::UnmeteredGasMeter, + ) + .elapsed_micros; println!("running time (microseconds): {}", elapsed); elapsed } diff --git a/aptos-move/aptos-vm-benchmarks/src/helper.rs b/aptos-move/aptos-vm-benchmarks/src/helper.rs index aea964f3e20e2..25d12122a61a5 100644 --- a/aptos-move/aptos-vm-benchmarks/src/helper.rs +++ b/aptos-move/aptos-vm-benchmarks/src/helper.rs @@ -64,15 +64,17 @@ pub fn execute_module_txn( // sign user transaction and only records the body of the transaction pub fn execute_user_txn(executor: &mut FakeExecutor, module_name: &ModuleId, function_name: &str) { - let elapsed = executor.exec_func_record_running_time( - module_name, - function_name, - vec![], - vec![], - 10, - ExecFuncTimerDynamicArgs::NoArgs, - GasMeterType::UnmeteredGasMeter, - ); + let elapsed = executor + .exec_func_record_running_time( + module_name, + function_name, + vec![], + vec![], + 10, + ExecFuncTimerDynamicArgs::NoArgs, + GasMeterType::UnmeteredGasMeter, + ) + .elapsed_micros; println!("running time (microseconds): {}", elapsed); } diff --git a/aptos-move/e2e-benchmark/src/main.rs b/aptos-move/e2e-benchmark/src/main.rs index 6ac46ffd3f785..c80223ef0f110 100644 --- a/aptos-move/e2e-benchmark/src/main.rs +++ b/aptos-move/e2e-benchmark/src/main.rs @@ -3,7 +3,7 @@ use aptos_language_e2e_tests::{ account::Account, - executor::{ExecFuncTimerDynamicArgs, FakeExecutor, GasMeterType}, + executor::{ExecFuncTimerDynamicArgs, FakeExecutor, GasMeterType, TimeAndGas}, }; use aptos_transaction_generator_lib::{ publishing::{ @@ -46,7 +46,7 @@ fn execute_and_time_entry_point( publisher_address: &AccountAddress, executor: &mut FakeExecutor, iterations: u64, -) -> u128 { +) -> TimeAndGas { let mut rng = StdRng::seed_from_u64(14); let entry_fun = entry_point .create_payload( @@ -102,6 +102,78 @@ TokenV1MintAndTransferNFTSequential 6 0.991 1.067 543.7 TokenV2AmbassadorMint { numbered: true } 6 0.987 1.052 474.4 LiquidityPoolSwap { is_stable: true } 6 0.970 1.042 555.4 LiquidityPoolSwap { is_stable: false } 6 0.925 1.001 535.3 + + + +(146, EntryPoints::CoinInitAndMint), + (154, EntryPoints::FungibleAssetMint), + (23, EntryPoints::IncGlobalMilestoneAggV2 { + milestone_every: 1, + }), + (12, EntryPoints::IncGlobalMilestoneAggV2 { + milestone_every: 2, + }), + (6871, EntryPoints::EmitEvents { count: 1000 }), + // long vectors with small elements + (15890, EntryPoints::VectorTrimAppend { + // baseline, only vector creation + vec_len: 3000, + element_len: 1, + index: 0, + repeats: 0, + }), + (38047, EntryPoints::VectorTrimAppend { + vec_len: 3000, + element_len: 1, + index: 100, + repeats: 1000, + }), + (25923, EntryPoints::VectorTrimAppend { + vec_len: 3000, + element_len: 1, + index: 2990, + repeats: 1000, + }), + (35590, EntryPoints::VectorRemoveInsert { + vec_len: 3000, + element_len: 1, + index: 100, + repeats: 1000, + }), + (28141, EntryPoints::VectorRemoveInsert { + vec_len: 3000, + element_len: 1, + index: 2998, + repeats: 1000, + }), + (53500, EntryPoints::VectorRangeMove { + vec_len: 3000, + element_len: 1, + index: 1000, + move_len: 500, + repeats: 1000, + }), + // vectors with large elements + (654, EntryPoints::VectorTrimAppend { + // baseline, only vector creation + vec_len: 100, + element_len: 100, + index: 0, + repeats: 0, + }), + (11147, EntryPoints::VectorTrimAppend { + vec_len: 100, + element_len: 100, + index: 10, + repeats: 1000, + }), + (5545, EntryPoints::VectorRangeMove { + vec_len: 100, + element_len: 100, + index: 50, + move_len: 10, + repeats: 1000, + }), "; struct CalibrationInfo { @@ -145,7 +217,7 @@ fn main() { loop_type: LoopType::Arithmetic, }, // This is a cheap bcs (serializing vec), so not representative of what BCS native call should cost. - // (, EntryPoints::Loop { loop_count: Some(1000), loop_type: LoopType::BCS { len: 1024 }}), + // (, EntryPoints::Loop { loop_count: Some(1000), loop_type: LoopType::BcsToBytes { len: 1024 }}), EntryPoints::CreateObjects { num_objects: 10, object_payload_size: 0, @@ -162,9 +234,9 @@ fn main() { num_objects: 100, object_payload_size: 10 * 1024, }, - EntryPoints::InitializeVectorPicture { length: 40 }, - EntryPoints::VectorPicture { length: 40 }, - EntryPoints::VectorPictureRead { length: 40 }, + EntryPoints::InitializeVectorPicture { length: 128 }, + EntryPoints::VectorPicture { length: 128 }, + EntryPoints::VectorPictureRead { length: 128 }, EntryPoints::InitializeVectorPicture { length: 30 * 1024 }, EntryPoints::VectorPicture { length: 30 * 1024 }, EntryPoints::VectorPictureRead { length: 30 * 1024 }, @@ -187,14 +259,83 @@ fn main() { EntryPoints::TokenV2AmbassadorMint { numbered: true }, EntryPoints::LiquidityPoolSwap { is_stable: true }, EntryPoints::LiquidityPoolSwap { is_stable: false }, + EntryPoints::CoinInitAndMint, + EntryPoints::FungibleAssetMint, + EntryPoints::IncGlobalMilestoneAggV2 { + milestone_every: 1, + }, + EntryPoints::IncGlobalMilestoneAggV2 { + milestone_every: 2, + }, + EntryPoints::EmitEvents { count: 1000 }, + // long vectors with small elements + EntryPoints::VectorSplitOffAppend { + // baseline, only vector creation + vec_len: 3000, + element_len: 1, + index: 0, + repeats: 0, + }, + EntryPoints::VectorSplitOffAppend { + vec_len: 3000, + element_len: 1, + index: 100, + repeats: 1000, + }, + EntryPoints::VectorSplitOffAppend { + vec_len: 3000, + element_len: 1, + index: 2990, + repeats: 1000, + }, + EntryPoints::VectorRemoveInsert { + vec_len: 3000, + element_len: 1, + index: 100, + repeats: 1000, + }, + EntryPoints::VectorRemoveInsert { + vec_len: 3000, + element_len: 1, + index: 2998, + repeats: 1000, + }, + EntryPoints::VectorRangeMove { + vec_len: 3000, + element_len: 1, + index: 1000, + move_len: 500, + repeats: 1000, + }, + // vectors with large elements + EntryPoints::VectorSplitOffAppend { + // baseline, only vector creation + vec_len: 100, + element_len: 100, + index: 0, + repeats: 0, + }, + EntryPoints::VectorSplitOffAppend { + vec_len: 100, + element_len: 100, + index: 10, + repeats: 1000, + }, + EntryPoints::VectorRangeMove { + vec_len: 100, + element_len: 100, + index: 50, + move_len: 10, + repeats: 1000, + }, ]; let mut failures = Vec::new(); let mut json_lines = Vec::new(); println!( - "{:>15} {:>15} {:>15} entry point", - "wall time (us)", "expected (us)", "diff(- is impr)" + "{:>13} {:>13} {:>13}{:>13} {:>13} {:>13} entry point", + "walltime(us)", "expected(us)", "dif(- is impr)", "gas/s", "exe gas", "io gas", ); for (index, entry_point) in entry_points.into_iter().enumerate() { @@ -214,7 +355,6 @@ fn main() { 0, package.publish_transaction_payload(), ); - println!("Published package: {:?}", entry_point.package_name()); if let Some(init_entry_point) = entry_point.initialize_entry_point() { execute_txn( &mut executor, @@ -226,13 +366,9 @@ fn main() { Some(publisher.address()), ), ); - println!( - "Executed init entry point: {:?}", - entry_point.initialize_entry_point() - ); } - let elapsed_micros = execute_and_time_entry_point( + let measurement = execute_and_time_entry_point( &entry_point, &package, publisher.address(), @@ -245,33 +381,44 @@ fn main() { 100 }, ); - let diff = (elapsed_micros as f32 - expected_time) / expected_time * 100.0; + let diff = (measurement.elapsed_micros as f32 - expected_time as f32) + / (expected_time as f32) + * 100.0; println!( - "{:15} {:15.1} {:14.1}% {:?}", - elapsed_micros, expected_time, diff, entry_point + "{:13} {:13.1} {:12.1}% {:13} {:13} {:13} {:?}", + measurement.elapsed_micros, + expected_time, + diff, + (measurement.execution_gas + measurement.io_gas) as u128 / measurement.elapsed_micros, + measurement.execution_gas, + measurement.io_gas, + entry_point ); json_lines.push(json!({ "grep": "grep_json_aptos_move_vm_perf", "transaction_type": entry_point_name, - "wall_time_us": elapsed_micros, + "wall_time_us": measurement.elapsed_micros, + "gps": (measurement.execution_gas + measurement.io_gas) as u128 / measurement.elapsed_micros, + "execution_gas": measurement.execution_gas, + "io_gas": measurement.io_gas, "expected_wall_time_us": expected_time, "test_index": index, })); - if elapsed_micros as f32 + if measurement.elapsed_micros as f32 > expected_time as f32 * (1.0 + ALLOWED_REGRESSION) + ABSOLUTE_BUFFER_US { failures.push(format!( "Performance regression detected: {}us, expected: {}us, diff: {}%, for {:?}", - elapsed_micros, expected_time, diff, entry_point + measurement.elapsed_micros, expected_time, diff, entry_point )); - } else if elapsed_micros as f32 + ABSOLUTE_BUFFER_US + } else if measurement.elapsed_micros as f32 + ABSOLUTE_BUFFER_US < expected_time as f32 * (1.0 - ALLOWED_IMPROVEMENT) { failures.push(format!( "Performance improvement detected: {}us, expected {}us, diff: {}%, for {:?}. You need to adjust expected time!", - elapsed_micros, expected_time, diff, entry_point + measurement.elapsed_micros, expected_time, diff, entry_point )); } } diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index a6245c5508500..dadfd08b4b263 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -20,7 +20,7 @@ use aptos_block_executor::{ use aptos_crypto::HashValue; use aptos_framework::ReleaseBundle; use aptos_gas_algebra::DynamicExpression; -use aptos_gas_meter::{StandardGasAlgebra, StandardGasMeter}; +use aptos_gas_meter::{AptosGasMeter, GasAlgebra, StandardGasAlgebra, StandardGasMeter}; use aptos_gas_profiling::{GasProfiler, TransactionGasLog}; use aptos_keygen::KeyGen; use aptos_types::{ @@ -143,6 +143,13 @@ pub enum GasMeterType { UnmeteredGasMeter, } +#[derive(Clone)] +pub struct TimeAndGas { + pub elapsed_micros: u128, + pub execution_gas: u64, + pub io_gas: u64, +} + pub enum ExecFuncTimerDynamicArgs { NoArgs, DistinctSigners, @@ -970,7 +977,7 @@ impl FakeExecutor { iterations: u64, dynamic_args: ExecFuncTimerDynamicArgs, gas_meter_type: GasMeterType, - ) -> u128 { + ) -> TimeAndGas { let mut extra_accounts = match &dynamic_args { ExecFuncTimerDynamicArgs::DistinctSigners | ExecFuncTimerDynamicArgs::DistinctSignersAndFixed(_) => (0..iterations) @@ -1059,21 +1066,36 @@ impl FakeExecutor { let elapsed = start.elapsed(); if let Err(err) = result { if !should_error { - println!("Shouldn't error, but ignoring for now... {}", err); + println!( + "Entry function under measurement failed with an error. Continuing, but measurements are probably not what is expected. Error: {}", + err + ); } } - times.push(elapsed.as_micros()); + times.push(TimeAndGas { + elapsed_micros: elapsed.as_micros(), + execution_gas: regular + .as_ref() + .map_or(0, |gas| gas.algebra().execution_gas_used().into()), + io_gas: regular + .as_ref() + .map_or(0, |gas| gas.algebra().io_gas_used().into()), + }); i += 1; } // take median of all running time iterations as a more robust measurement - times.sort(); + times.sort_by_key(|v| v.elapsed_micros); let length = times.len(); let mid = length / 2; - let mut running_time = times[mid]; + let mut running_time = times[mid].clone(); if length % 2 == 0 { - running_time = (times[mid - 1] + times[mid]) / 2; + running_time = TimeAndGas { + elapsed_micros: (times[mid - 1].elapsed_micros + times[mid].elapsed_micros) / 2, + execution_gas: (times[mid - 1].execution_gas + times[mid].execution_gas) / 2, + io_gas: (times[mid - 1].io_gas + times[mid].io_gas) / 2, + }; } running_time diff --git a/aptos-move/framework/aptos-stdlib/doc/big_vector.md b/aptos-move/framework/aptos-stdlib/doc/big_vector.md index 7d785a5b730a1..da978bc07ff9e 100644 --- a/aptos-move/framework/aptos-stdlib/doc/big_vector.md +++ b/aptos-move/framework/aptos-stdlib/doc/big_vector.md @@ -502,7 +502,7 @@ Aborts if i is out of bounds. if (self.end_index == i) { return last_val }; - // because the lack of mem::swap, here we swap remove the requested value from the bucket + // because the lack of mem::swap, here we swap remove the requested value from the bucket // and append the last_val to the bucket then swap the last bucket val back let bucket = table_with_length::borrow_mut(&mut self.buckets, i / self.bucket_size); let bucket_len = vector::length(bucket); diff --git a/aptos-move/framework/move-stdlib/doc/features.md b/aptos-move/framework/move-stdlib/doc/features.md index 3919625f4ff9c..e5604063b6071 100644 --- a/aptos-move/framework/move-stdlib/doc/features.md +++ b/aptos-move/framework/move-stdlib/doc/features.md @@ -133,6 +133,8 @@ return true. - [Function `transaction_simulation_enhancement_enabled`](#0x1_features_transaction_simulation_enhancement_enabled) - [Function `get_collection_owner_feature`](#0x1_features_get_collection_owner_feature) - [Function `is_collection_owner_enabled`](#0x1_features_is_collection_owner_enabled) +- [Function `get_native_memory_operations_feature`](#0x1_features_get_native_memory_operations_feature) +- [Function `is_native_memory_operations_enabled`](#0x1_features_is_native_memory_operations_enabled) - [Function `change_feature_flags`](#0x1_features_change_feature_flags) - [Function `change_feature_flags_internal`](#0x1_features_change_feature_flags_internal) - [Function `change_feature_flags_for_next_epoch`](#0x1_features_change_feature_flags_for_next_epoch) @@ -671,6 +673,15 @@ Lifetime: transient + + + + +
const NATIVE_MEMORY_OPERATIONS: u64 = 80;
+
+ + + Lifetime: transient @@ -3274,6 +3285,52 @@ Deprecated feature + + + + +## Function `get_native_memory_operations_feature` + + + +
public fun get_native_memory_operations_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_native_memory_operations_feature(): u64 { NATIVE_MEMORY_OPERATIONS }
+
+ + + +
+ + + +## Function `is_native_memory_operations_enabled` + + + +
public fun is_native_memory_operations_enabled(): bool
+
+ + + +
+Implementation + + +
public fun is_native_memory_operations_enabled(): bool acquires Features {
+    is_enabled(NATIVE_MEMORY_OPERATIONS)
+}
+
+ + +
diff --git a/aptos-move/framework/move-stdlib/doc/vector.md b/aptos-move/framework/move-stdlib/doc/vector.md index b56160dbaf27e..8e9411e10f129 100644 --- a/aptos-move/framework/move-stdlib/doc/vector.md +++ b/aptos-move/framework/move-stdlib/doc/vector.md @@ -40,6 +40,7 @@ the return on investment didn't seem worth it for these simple functions. - [Function `remove`](#0x1_vector_remove) - [Function `remove_value`](#0x1_vector_remove_value) - [Function `swap_remove`](#0x1_vector_swap_remove) +- [Function `replace`](#0x1_vector_replace) - [Function `for_each`](#0x1_vector_for_each) - [Function `for_each_reverse`](#0x1_vector_for_each_reverse) - [Function `for_each_ref`](#0x1_vector_for_each_ref) @@ -87,7 +88,8 @@ the return on investment didn't seem worth it for these simple functions. - [Function `rotate_slice`](#@Specification_1_rotate_slice) -
+
use 0x1::mem;
+
@@ -146,6 +148,18 @@ The length of the vectors are not equal. + + +Whether to utilize native vector::move_range +Vector module cannot call features module, due to cyclic dependency, +so this is a constant. + + +
const USE_MOVE_RANGE: bool = true;
+
+ + + ## Function `empty` @@ -358,7 +372,7 @@ Move prevents from having two mutable references to the same value, so fro vectors are always distinct. -
public(friend) fun move_range<T>(from: &mut vector<T>, removal_position: u64, length: u64, to: &mut vector<T>, insert_position: u64)
+
public fun move_range<T>(from: &mut vector<T>, removal_position: u64, length: u64, to: &mut vector<T>, insert_position: u64)
 
@@ -367,7 +381,7 @@ vectors are always distinct. Implementation -
native public(friend) fun move_range<T>(
+
native public fun move_range<T>(
     from: &mut vector<T>,
     removal_position: u64,
     length: u64,
@@ -482,8 +496,15 @@ Pushes all of the elements of the other vector into the self<
 
 
 
public fun append<Element>(self: &mut vector<Element>, other: vector<Element>) {
-    reverse(&mut other);
-    reverse_append(self, other);
+    if (USE_MOVE_RANGE) {
+        let self_length = length(self);
+        let other_length = length(&other);
+        move_range(&mut other, 0, other_length, self, self_length);
+        destroy_empty(other);
+    } else {
+        reverse(&mut other);
+        reverse_append(self, other);
+    }
 }
 
@@ -525,7 +546,11 @@ Pushes all of the elements of the other vector into the self< ## Function `trim` -Trim a vector to a smaller size, returning the evicted elements in order +Splits (trims) the collection into two at the given index. +Returns a newly allocated vector containing the elements in the range [new_len, len). +After the call, the original vector will be left containing the elements [0, new_len) +with its previous capacity unchanged. +In many languages this is also called split_off.
public fun trim<Element>(self: &mut vector<Element>, new_len: u64): vector<Element>
@@ -538,9 +563,21 @@ Trim a vector to a smaller size, returning the evicted elements in order
 
 
 
public fun trim<Element>(self: &mut vector<Element>, new_len: u64): vector<Element> {
-    let res = trim_reverse(self, new_len);
-    reverse(&mut res);
-    res
+    let len = length(self);
+    assert!(new_len <= len, EINDEX_OUT_OF_BOUNDS);
+
+    let other = empty();
+    if (USE_MOVE_RANGE) {
+        move_range(self, new_len, len - new_len, &mut other, 0);
+    } else {
+        while (len > new_len) {
+            push_back(&mut other, pop_back(self));
+            len = len - 1;
+        };
+        reverse(&mut other);
+    };
+
+    other
 }
 
@@ -728,10 +765,27 @@ Aborts if out of bounds.
public fun insert<Element>(self: &mut vector<Element>, i: u64, e: Element) {
     let len = length(self);
     assert!(i <= len, EINDEX_OUT_OF_BOUNDS);
-    push_back(self, e);
-    while (i < len) {
-        swap(self, i, len);
-        i = i + 1;
+
+    if (USE_MOVE_RANGE) {
+        if (i + 2 >= len) {
+            // When we are close to the end, it is cheaper to not create
+            // a temporary vector, and swap directly
+            push_back(self, e);
+            while (i < len) {
+                swap(self, i, len);
+                i = i + 1;
+            };
+        } else {
+            let other = singleton(e);
+            move_range(&mut other, 0, 1, self, i);
+            destroy_empty(other);
+        }
+    } else {
+        push_back(self, e);
+        while (i < len) {
+            swap(self, i, len);
+            i = i + 1;
+        };
     };
 }
 
@@ -763,9 +817,25 @@ Aborts if i is out of bounds. // i out of bounds; abort if (i >= len) abort EINDEX_OUT_OF_BOUNDS; - len = len - 1; - while (i < len) swap(self, i, { i = i + 1; i }); - pop_back(self) + if (USE_MOVE_RANGE) { + // When we are close to the end, it is cheaper to not create + // a temporary vector, and swap directly + if (i + 3 >= len) { + len = len - 1; + while (i < len) swap(self, i, { i = i + 1; i }); + pop_back(self) + } else { + let other = empty(); + move_range(self, i, 1, &mut other, 0); + let result = pop_back(&mut other); + destroy_empty(other); + result + } + } else { + len = len - 1; + while (i < len) swap(self, i, { i = i + 1; i }); + pop_back(self) + } }
@@ -838,6 +908,41 @@ Aborts if i is out of bounds. + + + + +## Function `replace` + +Replace the ith element of the vector self with the given value, and return +to the caller the value that was there before. +Aborts if i is out of bounds. + + +
public fun replace<Element>(self: &mut vector<Element>, i: u64, val: Element): Element
+
+ + + +
+Implementation + + +
public fun replace<Element>(self: &mut vector<Element>, i: u64, val: Element): Element {
+    let last_idx = length(self);
+    assert!(i < last_idx, EINDEX_OUT_OF_BOUNDS);
+    if (USE_MOVE_RANGE) {
+        mem::replace(borrow_mut(self, i), val)
+    } else {
+        push_back(self, val);
+        swap(self, i, last_idx);
+        pop_back(self)
+    }
+}
+
+ + +
diff --git a/aptos-move/framework/move-stdlib/doc/vector_ext.md b/aptos-move/framework/move-stdlib/doc/vector_ext.md new file mode 100644 index 0000000000000..1fa207f777813 --- /dev/null +++ b/aptos-move/framework/move-stdlib/doc/vector_ext.md @@ -0,0 +1,201 @@ + + + +# Module `0x1::vector_ext` + + + +- [Constants](#@Constants_0) +- [Function `range_move`](#0x1_vector_ext_range_move) +- [Function `split_off`](#0x1_vector_ext_split_off) +- [Function `append`](#0x1_vector_ext_append) +- [Function `insert`](#0x1_vector_ext_insert) +- [Function `remove`](#0x1_vector_ext_remove) + + +
use 0x1::vector;
+
+ + + + + +## Constants + + + + +The index into the vector is out of bounds + + +
const EINDEX_OUT_OF_BOUNDS: u64 = 131072;
+
+ + + + + +## Function `range_move` + + + +
public fun range_move<T>(from: &mut vector<T>, removal_position: u64, length: u64, to: &mut vector<T>, insert_position: u64)
+
+ + + +
+Implementation + + +
public native fun range_move<T>(from: &mut vector<T>, removal_position: u64, length: u64, to: &mut vector<T>, insert_position: u64);
+
+ + + +
+ + + +## Function `split_off` + +Splits the collection into two at the given index. +Returns a newly allocated vector containing the elements in the range [at, len). +After the call, the original vector will be left containing the elements [0, at) +with its previous capacity unchanged. + + +
public fun split_off<Element>(self: &mut vector<Element>, at: u64): vector<Element>
+
+ + + +
+Implementation + + +
public fun split_off<Element>(self: &mut vector<Element>, at: u64): vector<Element> {
+    let len = vector::length(self);
+    assert!(at <= len, EINDEX_OUT_OF_BOUNDS);
+
+    let other = vector::empty();
+    range_move(self, at, len - at, &mut other, 0);
+
+    // let other = empty();
+    // while (len > at) {
+    //     push_back(&mut other, pop_back(self));
+    //     len = len - 1;
+    // };
+    // reverse(&mut other);
+    other
+}
+
+ + + +
+ + + +## Function `append` + +Pushes all of the elements of the other vector into the self vector. + + +
public fun append<Element>(self: &mut vector<Element>, other: vector<Element>)
+
+ + + +
+Implementation + + +
public fun append<Element>(self: &mut vector<Element>, other: vector<Element>) {
+    let self_length = self.length();
+    let other_length = other.length();
+    range_move(&mut other, 0, other_length, self, self_length);
+    other.destroy_empty();
+    // reverse(&mut other);
+    // reverse_append(self, other);
+}
+
+ + + +
+ + + +## Function `insert` + + + +
public fun insert<Element>(self: &mut vector<Element>, i: u64, e: Element)
+
+ + + +
+Implementation + + +
public fun insert<Element>(self: &mut vector<Element>, i: u64, e: Element) {
+    let len = self.length();
+    assert!(i <= len, EINDEX_OUT_OF_BOUNDS);
+
+    if (i == len) {
+        self.push_back(e);
+    } else {
+        let other = vector::singleton(e);
+        range_move(&mut other, 0, 1, self, i);
+        other.destroy_empty();
+    }
+}
+
+ + + +
+ + + +## Function `remove` + +Remove the ith element of the vector self, shifting all subsequent elements. +This is O(n) and preserves ordering of elements in the vector. +Aborts if i is out of bounds. + + +
public fun remove<Element>(self: &mut vector<Element>, i: u64): Element
+
+ + + +
+Implementation + + +
public fun remove<Element>(self: &mut vector<Element>, i: u64): Element {
+    let len = self.length();
+    // i out of bounds; abort
+    if (i >= len) abort EINDEX_OUT_OF_BOUNDS;
+
+    if (i + 1 == len) {
+        self.pop_back()
+    } else {
+        let other = vector::empty();
+        range_move(self, i, 1, &mut other, 0);
+        let result = other.pop_back();
+        other.destroy_empty();
+        result
+    }
+}
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/move-stdlib/sources/configs/features.move b/aptos-move/framework/move-stdlib/sources/configs/features.move index 2bdba4056eaae..2b3a5291c600d 100644 --- a/aptos-move/framework/move-stdlib/sources/configs/features.move +++ b/aptos-move/framework/move-stdlib/sources/configs/features.move @@ -607,6 +607,14 @@ module std::features { is_enabled(COLLECTION_OWNER) } + const NATIVE_MEMORY_OPERATIONS: u64 = 80; + + public fun get_native_memory_operations_feature(): u64 { NATIVE_MEMORY_OPERATIONS } + + public fun is_native_memory_operations_enabled(): bool acquires Features { + is_enabled(NATIVE_MEMORY_OPERATIONS) + } + // ============================================================================================ // Feature Flag Implementation diff --git a/aptos-move/framework/move-stdlib/sources/mem.move b/aptos-move/framework/move-stdlib/sources/mem.move index 424766f4a2124..e96db063db6c0 100644 --- a/aptos-move/framework/move-stdlib/sources/mem.move +++ b/aptos-move/framework/move-stdlib/sources/mem.move @@ -2,6 +2,7 @@ module std::mem { // TODO - functions here are `public(friend)` here for one release, // and to be changed to `public` one release later. + friend std::vector; #[test_only] friend std::mem_tests; diff --git a/aptos-move/framework/move-stdlib/sources/vector.move b/aptos-move/framework/move-stdlib/sources/vector.move index 2d67042ef4fef..a4408db3f2a7b 100644 --- a/aptos-move/framework/move-stdlib/sources/vector.move +++ b/aptos-move/framework/move-stdlib/sources/vector.move @@ -9,6 +9,8 @@ /// Move functions here because many have loops, requiring loop invariants to prove, and /// the return on investment didn't seem worth it for these simple functions. module std::vector { + use std::mem; + /// The index into the vector is out of bounds const EINDEX_OUT_OF_BOUNDS: u64 = 0x20000; @@ -24,6 +26,11 @@ module std::vector { /// The range in `slice` is invalid. const EINVALID_SLICE_RANGE: u64 = 0x20004; + /// Whether to utilize native vector::move_range + /// Vector module cannot call features module, due to cyclic dependency, + /// so this is a constant. + const USE_MOVE_RANGE: bool = true; + #[bytecode_instruction] /// Create an empty vector. native public fun empty(): vector; @@ -61,11 +68,6 @@ module std::vector { /// Aborts if `i` or `j` is out of bounds. native public fun swap(self: &mut vector, i: u64, j: u64); - // TODO - function `move_range` here is `public(friend)` for one release, - // and to be changed to `public` one release later. - #[test_only] - friend std::vector_tests; - /// Moves range of elements `[removal_position, removal_position + length)` from vector `from`, /// to vector `to`, inserting them starting at the `insert_position`. /// In the `from` vector, elements after the selected range are moved left to fill the hole @@ -75,7 +77,7 @@ module std::vector { /// elements is kept). /// Move prevents from having two mutable references to the same value, so `from` and `to` /// vectors are always distinct. - native public(friend) fun move_range( + native public fun move_range( from: &mut vector, removal_position: u64, length: u64, @@ -121,8 +123,15 @@ module std::vector { /// Pushes all of the elements of the `other` vector into the `self` vector. public fun append(self: &mut vector, other: vector) { - reverse(&mut other); - reverse_append(self, other); + if (USE_MOVE_RANGE) { + let self_length = length(self); + let other_length = length(&other); + move_range(&mut other, 0, other_length, self, self_length); + destroy_empty(other); + } else { + reverse(&mut other); + reverse_append(self, other); + } } spec append { pragma intrinsic = true; @@ -144,11 +153,27 @@ module std::vector { pragma intrinsic = true; } - /// Trim a vector to a smaller size, returning the evicted elements in order + /// Splits (trims) the collection into two at the given index. + /// Returns a newly allocated vector containing the elements in the range [new_len, len). + /// After the call, the original vector will be left containing the elements [0, new_len) + /// with its previous capacity unchanged. + /// In many languages this is also called `split_off`. public fun trim(self: &mut vector, new_len: u64): vector { - let res = trim_reverse(self, new_len); - reverse(&mut res); - res + let len = length(self); + assert!(new_len <= len, EINDEX_OUT_OF_BOUNDS); + + let other = empty(); + if (USE_MOVE_RANGE) { + move_range(self, new_len, len - new_len, &mut other, 0); + } else { + while (len > new_len) { + push_back(&mut other, pop_back(self)); + len = len - 1; + }; + reverse(&mut other); + }; + + other } spec trim { pragma intrinsic = true; @@ -229,10 +254,27 @@ module std::vector { public fun insert(self: &mut vector, i: u64, e: Element) { let len = length(self); assert!(i <= len, EINDEX_OUT_OF_BOUNDS); - push_back(self, e); - while (i < len) { - swap(self, i, len); - i = i + 1; + + if (USE_MOVE_RANGE) { + if (i + 2 >= len) { + // When we are close to the end, it is cheaper to not create + // a temporary vector, and swap directly + push_back(self, e); + while (i < len) { + swap(self, i, len); + i = i + 1; + }; + } else { + let other = singleton(e); + move_range(&mut other, 0, 1, self, i); + destroy_empty(other); + } + } else { + push_back(self, e); + while (i < len) { + swap(self, i, len); + i = i + 1; + }; }; } spec insert { @@ -247,9 +289,25 @@ module std::vector { // i out of bounds; abort if (i >= len) abort EINDEX_OUT_OF_BOUNDS; - len = len - 1; - while (i < len) swap(self, i, { i = i + 1; i }); - pop_back(self) + if (USE_MOVE_RANGE) { + // When we are close to the end, it is cheaper to not create + // a temporary vector, and swap directly + if (i + 3 >= len) { + len = len - 1; + while (i < len) swap(self, i, { i = i + 1; i }); + pop_back(self) + } else { + let other = empty(); + move_range(self, i, 1, &mut other, 0); + let result = pop_back(&mut other); + destroy_empty(other); + result + } + } else { + len = len - 1; + while (i < len) swap(self, i, { i = i + 1; i }); + pop_back(self) + } } spec remove { pragma intrinsic = true; @@ -288,6 +346,21 @@ module std::vector { pragma intrinsic = true; } + /// Replace the `i`th element of the vector `self` with the given value, and return + /// to the caller the value that was there before. + /// Aborts if `i` is out of bounds. + public fun replace(self: &mut vector, i: u64, val: Element): Element { + let last_idx = length(self); + assert!(i < last_idx, EINDEX_OUT_OF_BOUNDS); + if (USE_MOVE_RANGE) { + mem::replace(borrow_mut(self, i), val) + } else { + push_back(self, val); + swap(self, i, last_idx); + pop_back(self) + } + } + /// Apply the function to each element in the vector, consuming it. public inline fun for_each(self: vector, f: |Element|) { reverse(&mut self); // We need to reverse the vector to consume it efficiently diff --git a/aptos-move/framework/move-stdlib/tests/vector_tests.move b/aptos-move/framework/move-stdlib/tests/vector_tests.move index ce558bc3e9cfc..da2bc17dee7c9 100644 --- a/aptos-move/framework/move-stdlib/tests/vector_tests.move +++ b/aptos-move/framework/move-stdlib/tests/vector_tests.move @@ -105,7 +105,18 @@ module std::vector_tests { let v = vector[1, 2]; assert!(&V::trim(&mut v, 0) == &vector[1, 2], 3); }; + { + let v = vector[1, 2, 3, 4, 5, 6]; + let other = V::trim(&mut v, 4); + assert!(v == vector[1, 2, 3, 4], 4); + assert!(other == vector[5, 6], 5); + + let other_empty = V::trim(&mut v, 4); + assert!(v == vector[1, 2, 3, 4], 6); + assert!(other_empty == vector[], 7); + }; } + #[test] #[expected_failure(abort_code = V::EINDEX_OUT_OF_BOUNDS)] fun test_trim_fail() { @@ -113,6 +124,13 @@ module std::vector_tests { V::trim(&mut v, 2); } + #[test] + #[expected_failure(abort_code = V::EINDEX_OUT_OF_BOUNDS)] + fun test_trim_fail_2() { + let v = vector[1, 2, 3]; + V::trim(&mut v, 4); + } + #[test] #[expected_failure(vector_error, minor_status = 1, location = Self)] fun borrow_out_of_range() { @@ -952,7 +970,7 @@ module std::vector_tests { #[test] fun test_destroy() { let v = vector[MoveOnly {}]; - vector::destroy(v, |m| { let MoveOnly {} = m; }) + V::destroy(v, |m| { let MoveOnly {} = m; }) } #[test] @@ -964,4 +982,19 @@ module std::vector_tests { assert!(&v == &vector[3, 6], 0); assert!(&w == &vector[1, 4, 5, 2], 0); } + + #[test] + #[expected_failure(abort_code = V::EINDEX_OUT_OF_BOUNDS)] + fun test_replace_empty_abort() { + let v = vector[]; + let MoveOnly {} = V::replace(&mut v, 0, MoveOnly {}); + V::destroy_empty(v); + } + + #[test] + fun test_replace() { + let v = vector[1, 2, 3, 4]; + V::replace(&mut v, 1, 17); + assert!(v == vector[1, 17, 3, 4], 0); + } } diff --git a/crates/transaction-generator-lib/src/args.rs b/crates/transaction-generator-lib/src/args.rs index b19bf2651e8b4..e29da0a80fc87 100644 --- a/crates/transaction-generator-lib/src/args.rs +++ b/crates/transaction-generator-lib/src/args.rs @@ -44,6 +44,8 @@ pub enum TransactionTypeArg { CreateObjects100, CreateObjects100WithPayload10k, CreateObjectsConflict100WithPayload10k, + VectorTrimAppendLen3000Size1, + VectorRemoveInsertLen3000Size1, ResourceGroupsGlobalWriteTag1KB, ResourceGroupsGlobalWriteAndReadTag1KB, ResourceGroupsSenderWriteTag1KB, @@ -216,6 +218,22 @@ impl TransactionTypeArg { object_payload_size: 10 * 1024, }) }, + TransactionTypeArg::VectorTrimAppendLen3000Size1 => { + call_custom_module(EntryPoints::VectorTrimAppend { + vec_len: 3000, + element_len: 1, + index: 100, + repeats: 1000, + }) + }, + TransactionTypeArg::VectorRemoveInsertLen3000Size1 => { + call_custom_module(EntryPoints::VectorRemoveInsert { + vec_len: 3000, + element_len: 1, + index: 100, + repeats: 1000, + }) + }, TransactionTypeArg::ResourceGroupsGlobalWriteTag1KB => { call_custom_module(EntryPoints::ResourceGroupsGlobalWriteTag { string_length: 1024, diff --git a/crates/transaction-generator-lib/src/publishing/module_simple.rs b/crates/transaction-generator-lib/src/publishing/module_simple.rs index 0bc7b959fb408..aef670d039003 100644 --- a/crates/transaction-generator-lib/src/publishing/module_simple.rs +++ b/crates/transaction-generator-lib/src/publishing/module_simple.rs @@ -227,6 +227,25 @@ pub enum EntryPoints { num_objects: u64, object_payload_size: u64, }, + VectorTrimAppend { + vec_len: u64, + element_len: u64, + index: u64, + repeats: u64, + }, + VectorRemoveInsert { + vec_len: u64, + element_len: u64, + index: u64, + repeats: u64, + }, + VectorRangeMove { + vec_len: u64, + element_len: u64, + index: u64, + move_len: u64, + repeats: u64, + }, /// Initialize Token V1 NFT collection TokenV1InitializeCollection, /// Mint an NFT token. Should be called only after InitializeCollection is called @@ -303,6 +322,9 @@ impl EntryPoints { | EntryPoints::ModifyGlobalBoundedAggV2 { .. } | EntryPoints::CreateObjects { .. } | EntryPoints::CreateObjectsConflict { .. } + | EntryPoints::VectorTrimAppend { .. } + | EntryPoints::VectorRemoveInsert { .. } + | EntryPoints::VectorRangeMove { .. } | EntryPoints::TokenV1InitializeCollection | EntryPoints::TokenV1MintAndStoreNFTParallel | EntryPoints::TokenV1MintAndStoreNFTSequential @@ -361,6 +383,9 @@ impl EntryPoints { EntryPoints::CreateObjects { .. } | EntryPoints::CreateObjectsConflict { .. } => { "objects" }, + EntryPoints::VectorTrimAppend { .. } + | EntryPoints::VectorRemoveInsert { .. } + | EntryPoints::VectorRangeMove { .. } => "vector_example", EntryPoints::TokenV1InitializeCollection | EntryPoints::TokenV1MintAndStoreNFTParallel | EntryPoints::TokenV1MintAndStoreNFTSequential @@ -543,6 +568,51 @@ impl EntryPoints { bcs::to_bytes(other.expect("Must provide other")).unwrap(), ], ), + EntryPoints::VectorTrimAppend { + vec_len, + element_len, + index, + repeats, + } + | EntryPoints::VectorRemoveInsert { + vec_len, + element_len, + index, + repeats, + } => get_payload( + module_id, + ident_str!( + if let EntryPoints::VectorTrimAppend { .. } = self { + "test_trim_append" + } else { + "test_remove_insert" + } + ) + .to_owned(), + vec![ + bcs::to_bytes(vec_len).unwrap(), + bcs::to_bytes(element_len).unwrap(), + bcs::to_bytes(index).unwrap(), + bcs::to_bytes(repeats).unwrap(), + ], + ), + EntryPoints::VectorRangeMove { + vec_len, + element_len, + index, + move_len, + repeats, + } => get_payload( + module_id, + ident_str!("test_middle_range_move").to_owned(), + vec![ + bcs::to_bytes(vec_len).unwrap(), + bcs::to_bytes(element_len).unwrap(), + bcs::to_bytes(index).unwrap(), + bcs::to_bytes(move_len).unwrap(), + bcs::to_bytes(repeats).unwrap(), + ], + ), EntryPoints::TokenV1InitializeCollection => get_payload_void( module_id, ident_str!("token_v1_initialize_collection").to_owned(), @@ -810,6 +880,9 @@ impl EntryPoints { EntryPoints::CreateObjects { .. } | EntryPoints::CreateObjectsConflict { .. } => { AutomaticArgs::Signer }, + EntryPoints::VectorTrimAppend { .. } + | EntryPoints::VectorRemoveInsert { .. } + | EntryPoints::VectorRangeMove { .. } => AutomaticArgs::None, EntryPoints::TokenV1InitializeCollection | EntryPoints::TokenV1MintAndStoreNFTParallel | EntryPoints::TokenV1MintAndStoreNFTSequential diff --git a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs index 4deb1a72d1709..7bc806e4c36b0 100644 --- a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs +++ b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs @@ -739,10 +739,10 @@ pub static MODULES_COMPLEX: Lazy>> = Lazy::new(|| { vec![ pub static PACKAGE_SIMPLE_METADATA: Lazy> = Lazy::new(|| { vec![ 13, 71, 101, 110, 101, 114, 105, 99, 77, 111, 100, 117, 108, 101, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 64, 69, 53, 53, 57, 68, 57, 51, 68, 67, 55, 70, 65, - 56, 70, 70, 66, 70, 53, 70, 65, 57, 48, 49, 52, 57, 69, 49, 65, 56, 48, - 56, 55, 57, 67, 65, 52, 56, 50, 66, 67, 52, 67, 48, 50, 48, 51, 51, 50, - 53, 53, 52, 67, 50, 67, 48, 52, 49, 56, 67, 54, 56, 56, 53, 69, 132, 1, + 0, 0, 0, 0, 0, 64, 68, 48, 69, 53, 68, 55, 70, 65, 50, 66, 65, 54, + 68, 50, 65, 48, 57, 55, 55, 56, 51, 49, 51, 67, 57, 68, 69, 51, 56, 67, + 69, 69, 68, 49, 49, 49, 68, 65, 70, 49, 67, 66, 53, 53, 56, 54, 52, 65, + 67, 65, 52, 55, 56, 49, 53, 67, 65, 52, 53, 57, 66, 49, 66, 66, 132, 1, 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 77, 139, 59, 14, 194, 48, 16, 68, 251, 61, 133, 229, 30, 135, 11, 80, 208, 64, 197, 9, 162, 20, 43, 123, 64, 86, 156, 93, 203, 134, 80, 32, 238, 142, 45, 1, 138, 102, 154, 249, 188, 49, 179, 159, @@ -984,11 +984,11 @@ pub static MODULES_SIMPLE: Lazy>> = Lazy::new(|| { vec![ pub static PACKAGE_FRAMEWORK_USECASES_METADATA: Lazy> = Lazy::new(|| { vec![ 17, 70, 114, 97, 109, 101, 119, 111, 114, 107, 85, 115, 101, 99, 97, 115, 101, 115, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, 55, 49, 50, 55, 50, 50, 66, 65, - 65, 50, 67, 49, 53, 66, 70, 54, 65, 70, 53, 70, 55, 52, 65, 67, 69, 56, - 51, 68, 53, 66, 66, 54, 66, 67, 56, 56, 49, 69, 66, 67, 68, 66, 66, 57, - 52, 48, 49, 54, 66, 66, 53, 66, 67, 48, 49, 51, 56, 49, 49, 50, 51, 53, - 66, 50, 215, 1, 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 165, 144, 187, 142, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, 66, 67, 69, 48, 54, 67, 49, 52, + 57, 67, 52, 51, 66, 56, 50, 53, 55, 53, 48, 54, 67, 65, 65, 57, 66, 66, + 70, 65, 51, 52, 51, 66, 69, 55, 56, 57, 57, 55, 67, 50, 56, 52, 70, 53, + 49, 56, 67, 70, 65, 55, 66, 57, 49, 54, 67, 50, 53, 69, 55, 56, 68, 55, + 55, 69, 215, 1, 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 165, 144, 187, 142, 194, 64, 12, 69, 251, 249, 10, 107, 182, 38, 236, 15, 108, 193, 238, 138, 150, 6, 170, 8, 33, 51, 49, 33, 100, 176, 163, 241, 240, 144, 16, 255, 78, 44, 30, 130, 22, 100, 23, 215, 246, 189, 167, 112, 217, 97, 104, 177, 166, 185, 99, 220, 18, 252, @@ -1000,13 +1000,14 @@ pub static PACKAGE_FRAMEWORK_USECASES_METADATA: Lazy> = Lazy::new(|| { 134, 107, 160, 99, 88, 35, 215, 38, 101, 5, 65, 88, 51, 114, 6, 172, 170, 68, 170, 96, 20, 5, 236, 5, 197, 88, 184, 242, 182, 183, 231, 117, 187, 101, 108, 116, 77, 105, 113, 55, 219, 163, 143, 163, 223, 191, 127, 239, 46, 112, 10, 188, 112, 161, - 1, 0, 0, 6, 18, 97, 103, 103, 114, 101, 103, 97, 116, 111, 114, 95, 101, 120, + 1, 0, 0, 7, 18, 97, 103, 103, 114, 101, 103, 97, 116, 111, 114, 95, 101, 120, 97, 109, 112, 108, 101, 0, 0, 0, 12, 99, 111, 105, 110, 95, 101, 120, 97, 109, 112, 108, 101, 0, 0, 0, 22, 102, 117, 110, 103, 105, 98, 108, 101, 95, 97, 115, 115, 101, 116, 95, 101, 120, 97, 109, 112, 108, 101, 0, 0, 0, 7, 111, 98, 106, 101, 99, 116, 115, 0, 0, 0, 23, 114, 101, 115, 111, 117, 114, 99, 101, 95, 103, 114, 111, 117, 112, 115, 95, 101, 120, 97, 109, 112, 108, 101, 0, 0, 0, 8, 116, - 111, 107, 101, 110, 95, 118, 49, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 111, 107, 101, 110, 95, 118, 49, 0, 0, 0, 14, 118, 101, 99, 116, 111, 114, 95, + 101, 120, 97, 109, 112, 108, 101, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 65, 112, 116, 111, 115, 70, 114, 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1586,6 +1587,63 @@ pub static MODULE_FRAMEWORK_USECASES_TOKEN_V1: Lazy> = Lazy::new(|| { ] }); +#[rustfmt::skip] +pub static MODULE_FRAMEWORK_USECASES_VECTOR_EXAMPLE: Lazy> = Lazy::new(|| { + vec![ + 161, 28, 235, 11, 7, 0, 0, 10, 8, 1, 0, 4, 3, 4, 66, 4, 70, 12, + 5, 82, 113, 7, 195, 1, 139, 1, 8, 206, 2, 64, 16, 142, 3, 31, 12, 173, + 3, 188, 3, 0, 0, 1, 2, 0, 1, 0, 1, 0, 1, 1, 3, 4, 5, 1, + 0, 1, 0, 4, 7, 8, 0, 1, 1, 5, 9, 8, 1, 0, 1, 0, 6, 11, + 8, 0, 1, 1, 7, 12, 5, 1, 0, 1, 1, 8, 4, 8, 1, 0, 1, 0, + 9, 11, 8, 0, 1, 1, 10, 12, 14, 1, 0, 1, 1, 11, 15, 8, 1, 0, + 1, 1, 2, 3, 3, 5, 3, 6, 3, 8, 3, 9, 3, 2, 3, 3, 1, 10, + 10, 3, 1, 3, 1, 10, 3, 3, 7, 10, 9, 0, 3, 9, 0, 1, 9, 0, + 10, 10, 3, 3, 1, 3, 10, 10, 3, 1, 3, 3, 10, 3, 10, 10, 3, 5, + 3, 3, 3, 3, 3, 0, 5, 7, 10, 9, 0, 3, 3, 7, 10, 9, 0, 3, + 5, 10, 10, 3, 10, 10, 3, 1, 7, 10, 10, 3, 7, 10, 10, 3, 4, 3, + 3, 3, 3, 2, 7, 10, 9, 0, 3, 3, 10, 10, 3, 1, 10, 3, 1, 10, + 9, 0, 2, 7, 10, 9, 0, 10, 9, 0, 3, 10, 10, 3, 1, 10, 10, 3, + 14, 118, 101, 99, 116, 111, 114, 95, 101, 120, 97, 109, 112, 108, 101, 12, 103, 101, + 110, 101, 114, 97, 116, 101, 95, 118, 101, 99, 6, 118, 101, 99, 116, 111, 114, 7, + 114, 101, 112, 108, 97, 99, 101, 22, 116, 101, 115, 116, 95, 109, 105, 100, 100, 108, + 101, 95, 114, 97, 110, 103, 101, 95, 109, 111, 118, 101, 10, 109, 111, 118, 101, 95, + 114, 97, 110, 103, 101, 18, 116, 101, 115, 116, 95, 114, 101, 109, 111, 118, 101, 95, + 105, 110, 115, 101, 114, 116, 6, 114, 101, 109, 111, 118, 101, 6, 105, 110, 115, 101, + 114, 116, 16, 116, 101, 115, 116, 95, 116, 114, 105, 109, 95, 97, 112, 112, 101, 110, + 100, 4, 116, 114, 105, 109, 6, 97, 112, 112, 101, 110, 100, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 171, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 20, 99, 111, 109, 112, 105, 108, 97, 116, 105, 111, 110, 95, + 109, 101, 116, 97, 100, 97, 116, 97, 9, 0, 3, 50, 46, 48, 3, 50, 46, 49, + 0, 0, 0, 0, 6, 63, 64, 2, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, 3, 9, 12, 4, 5, 8, 5, 23, + 10, 4, 4, 60, 11, 3, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 3, + 10, 3, 10, 1, 35, 3, 19, 5, 23, 13, 2, 10, 3, 68, 2, 5, 6, 64, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 12, 6, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 5, 9, 12, 7, 11, 0, 12, 8, 5, 33, 5, 55, 10, 7, 4, + 57, 11, 5, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 5, 10, 5, 10, + 8, 35, 3, 44, 5, 55, 10, 2, 12, 10, 13, 10, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 5, 56, 0, 1, 13, 6, 11, 10, 68, 3, 5, 31, 11, 6, + 2, 8, 12, 7, 5, 39, 8, 12, 4, 5, 14, 2, 1, 4, 0, 10, 46, 10, + 0, 10, 1, 17, 0, 12, 5, 11, 0, 11, 1, 17, 0, 12, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 12, 0, 9, 12, 7, 5, 14, 5, 42, 10, 7, 4, + 43, 11, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 0, 10, 0, 10, + 4, 35, 3, 25, 5, 42, 13, 5, 13, 6, 12, 8, 10, 2, 10, 3, 11, 8, + 10, 2, 56, 1, 13, 6, 13, 5, 12, 8, 10, 2, 10, 3, 11, 8, 10, 2, + 56, 1, 5, 12, 2, 8, 12, 7, 5, 20, 4, 1, 4, 0, 13, 34, 11, 0, + 11, 1, 17, 0, 12, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 9, + 12, 5, 5, 10, 5, 30, 10, 5, 4, 31, 11, 0, 6, 1, 0, 0, 0, 0, + 0, 0, 0, 22, 12, 0, 10, 0, 10, 3, 35, 3, 21, 5, 30, 13, 4, 10, + 2, 56, 2, 12, 6, 13, 4, 10, 2, 11, 6, 56, 3, 5, 8, 2, 8, 12, + 5, 5, 16, 7, 1, 4, 0, 16, 33, 11, 0, 11, 1, 17, 0, 12, 4, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 9, 12, 5, 5, 10, 5, 29, 10, + 5, 4, 30, 11, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 0, 10, + 0, 10, 3, 35, 3, 21, 5, 29, 13, 4, 10, 2, 56, 4, 12, 6, 13, 4, + 11, 6, 56, 5, 5, 8, 2, 8, 12, 5, 5, 16, 0, + ] +}); + #[rustfmt::skip] pub static MODULES_FRAMEWORK_USECASES: Lazy>> = Lazy::new(|| { vec![ MODULE_FRAMEWORK_USECASES_AGGREGATOR_EXAMPLE.to_vec(), @@ -1594,39 +1652,42 @@ pub static MODULES_FRAMEWORK_USECASES: Lazy>> = Lazy::new(|| { vec![ MODULE_FRAMEWORK_USECASES_OBJECTS.to_vec(), MODULE_FRAMEWORK_USECASES_RESOURCE_GROUPS_EXAMPLE.to_vec(), MODULE_FRAMEWORK_USECASES_TOKEN_V1.to_vec(), + MODULE_FRAMEWORK_USECASES_VECTOR_EXAMPLE.to_vec(), ]}); #[rustfmt::skip] pub static PACKAGE_AMBASSADOR_TOKEN_METADATA: Lazy> = Lazy::new(|| { vec![ 10, 97, 109, 98, 97, 115, 115, 97, 100, 111, 114, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 64, 56, 66, 56, 55, 50, 65, 65, 53, 50, 53, 54, 53, 67, 66, 55, - 48, 65, 65, 57, 48, 48, 55, 51, 48, 56, 67, 67, 49, 50, 51, 57, 50, 66, - 54, 57, 53, 52, 56, 51, 67, 51, 48, 54, 54, 54, 70, 69, 69, 51, 56, 52, - 55, 66, 50, 51, 49, 54, 53, 50, 52, 54, 67, 51, 65, 219, 1, 31, 139, 8, - 0, 0, 0, 0, 0, 2, 255, 141, 141, 61, 110, 195, 48, 12, 70, 119, 157, 130, - 80, 7, 47, 181, 227, 30, 160, 67, 80, 52, 107, 151, 110, 70, 80, 208, 34, 227, - 184, 182, 73, 67, 84, 218, 2, 69, 239, 94, 11, 206, 207, 26, 64, 139, 136, 239, - 189, 215, 204, 24, 6, 236, 120, 239, 4, 39, 134, 103, 40, 112, 106, 209, 12, 73, - 99, 225, 190, 56, 90, 175, 146, 207, 79, 85, 93, 213, 133, 115, 15, 64, 10, 162, - 9, 194, 17, 165, 99, 72, 10, 254, 195, 63, 66, 80, 9, 145, 19, 3, 18, 69, - 54, 3, 97, 38, 38, 56, 104, 132, 73, 233, 52, 114, 57, 159, 218, 177, 183, 35, - 36, 182, 212, 75, 7, 135, 184, 36, 191, 53, 14, 174, 57, 67, 108, 123, 119, 235, - 47, 89, 95, 255, 188, 108, 119, 175, 222, 185, 134, 120, 102, 33, 150, 208, 231, 213, - 118, 78, 106, 187, 139, 96, 89, 254, 194, 168, 1, 199, 204, 84, 213, 102, 125, 215, - 192, 6, 243, 188, 188, 254, 61, 252, 173, 134, 119, 29, 88, 222, 218, 79, 14, 201, - 238, 148, 164, 140, 148, 186, 50, 89, 244, 15, 202, 171, 40, 201, 67, 1, 0, 0, - 1, 10, 97, 109, 98, 97, 115, 115, 97, 100, 111, 114, 0, 0, 0, 4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 65, 112, 116, 111, 115, - 70, 114, 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 64, 68, 70, 50, 57, 50, 70, 53, 53, 56, 50, 66, 48, 57, 50, 65, + 51, 54, 55, 65, 53, 69, 55, 69, 57, 65, 48, 48, 69, 66, 51, 68, 57, 52, + 48, 55, 56, 67, 49, 54, 69, 65, 66, 65, 48, 50, 52, 69, 65, 65, 50, 52, + 57, 52, 49, 55, 70, 54, 50, 51, 52, 53, 67, 50, 48, 253, 1, 31, 139, 8, + 0, 0, 0, 0, 0, 2, 255, 173, 142, 63, 79, 195, 64, 12, 197, 247, 251, 20, + 86, 24, 186, 144, 63, 172, 72, 12, 21, 162, 43, 11, 91, 84, 161, 203, 157, 155, + 28, 73, 236, 232, 236, 20, 36, 196, 119, 231, 142, 22, 144, 16, 99, 55, 219, 239, + 249, 253, 94, 187, 88, 55, 218, 30, 247, 134, 236, 140, 112, 7, 27, 59, 119, 86, + 196, 122, 142, 27, 115, 196, 40, 129, 41, 159, 111, 170, 166, 106, 54, 198, 92, 129, + 103, 32, 86, 112, 131, 165, 30, 65, 25, 138, 231, 226, 26, 28, 147, 139, 168, 8, + 214, 251, 136, 34, 64, 136, 30, 61, 28, 56, 194, 204, 126, 157, 176, 92, 214, 110, + 10, 50, 128, 162, 104, 160, 30, 14, 49, 33, 95, 57, 142, 166, 61, 63, 161, 236, + 205, 47, 63, 97, 139, 230, 237, 126, 187, 123, 40, 140, 105, 61, 46, 72, 30, 201, + 133, 236, 218, 46, 202, 178, 251, 14, 72, 206, 119, 232, 131, 230, 143, 65, 117, 145, + 219, 186, 78, 235, 176, 118, 149, 227, 185, 182, 217, 92, 78, 182, 147, 243, 248, 67, + 174, 146, 43, 149, 151, 181, 243, 225, 139, 247, 71, 79, 90, 196, 99, 22, 102, 27, + 136, 80, 11, 248, 56, 177, 159, 120, 68, 122, 236, 94, 208, 169, 92, 26, 175, 57, + 187, 228, 83, 248, 191, 21, 62, 1, 7, 30, 19, 174, 183, 1, 0, 0, 1, 10, + 97, 109, 98, 97, 115, 115, 97, 100, 111, 114, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, 108, 105, 98, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 65, 112, 116, 111, 115, 70, 114, + 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 77, 111, 118, 101, - 83, 116, 100, 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4, 17, 65, 112, 116, 111, 115, 84, 111, 107, 101, 110, 79, 98, 106, 101, 99, - 116, 115, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 77, 111, 118, 101, 83, 116, + 100, 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 17, 65, 112, 116, 111, 115, 84, 111, 107, 101, 110, 79, 98, 106, 101, 99, 116, 115, + 0, ] }); @@ -1843,29 +1904,31 @@ pub static MODULES_AMBASSADOR_TOKEN: Lazy>> = Lazy::new(|| { vec![ pub static PACKAGE_AGGREGATOR_EXAMPLES_METADATA: Lazy> = Lazy::new(|| { vec![ 19, 65, 103, 103, 114, 101, 103, 97, 116, 111, 114, 32, 101, 120, 97, 109, 112, 108, - 101, 115, 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, 68, 67, 55, 51, 49, 57, - 51, 57, 49, 54, 57, 50, 56, 54, 56, 57, 49, 55, 68, 67, 56, 51, 68, 70, - 52, 70, 65, 55, 66, 50, 65, 51, 67, 68, 52, 55, 55, 49, 49, 54, 69, 57, - 52, 70, 50, 54, 51, 52, 67, 65, 51, 48, 53, 56, 53, 48, 52, 65, 56, 69, - 69, 53, 51, 70, 162, 1, 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 141, 142, - 65, 10, 195, 32, 16, 69, 247, 158, 66, 220, 215, 244, 2, 93, 72, 105, 46, 208, - 101, 8, 101, 170, 83, 145, 24, 21, 71, 218, 64, 233, 221, 171, 41, 201, 186, 204, - 108, 62, 255, 61, 248, 67, 2, 61, 129, 197, 145, 5, 152, 145, 159, 184, 80, 214, - 102, 180, 80, 98, 230, 184, 192, 156, 60, 146, 96, 79, 204, 228, 98, 104, 253, 81, - 214, 19, 140, 13, 96, 76, 70, 34, 164, 145, 193, 238, 220, 54, 103, 69, 151, 179, - 234, 47, 141, 53, 152, 48, 24, 12, 218, 53, 92, 165, 18, 233, 90, 140, 119, 247, - 138, 189, 185, 143, 26, 124, 19, 164, 236, 234, 63, 114, 157, 242, 138, 121, 234, 160, - 129, 7, 90, 73, 193, 63, 63, 177, 223, 234, 127, 220, 61, 55, 253, 11, 194, 232, - 76, 11, 237, 0, 0, 0, 1, 22, 99, 111, 117, 110, 116, 101, 114, 95, 119, 105, - 116, 104, 95, 109, 105, 108, 101, 115, 116, 111, 110, 101, 0, 0, 0, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 65, 112, 116, 111, 115, - 70, 114, 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 101, 115, 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, 52, 57, 67, 52, 52, 65, + 65, 49, 54, 53, 57, 66, 66, 51, 68, 68, 49, 65, 69, 56, 49, 56, 49, 52, + 53, 53, 68, 48, 69, 57, 57, 56, 56, 50, 48, 53, 50, 52, 51, 57, 70, 48, + 67, 55, 69, 69, 55, 55, 68, 57, 66, 67, 67, 52, 70, 57, 48, 51, 68, 54, + 54, 48, 53, 67, 200, 1, 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 142, + 193, 14, 130, 48, 12, 134, 239, 123, 138, 101, 103, 5, 207, 38, 30, 136, 209, 23, + 240, 104, 140, 41, 172, 142, 5, 216, 150, 117, 32, 137, 241, 221, 221, 64, 56, 121, + 52, 189, 180, 253, 191, 191, 127, 175, 14, 170, 6, 20, 222, 152, 129, 14, 249, 129, + 139, 66, 41, 143, 10, 130, 245, 28, 71, 232, 92, 139, 36, 216, 128, 158, 180, 53, + 73, 223, 101, 177, 4, 99, 87, 144, 210, 35, 17, 210, 141, 193, 234, 185, 47, 158, + 9, 29, 143, 197, 249, 148, 88, 137, 14, 141, 68, 83, 233, 132, 23, 46, 88, 186, + 4, 217, 234, 50, 98, 47, 174, 116, 72, 120, 29, 130, 163, 125, 158, 199, 177, 238, + 203, 172, 178, 93, 14, 137, 220, 182, 80, 210, 183, 125, 248, 248, 230, 211, 250, 38, + 139, 148, 216, 112, 234, 75, 169, 125, 114, 207, 58, 77, 87, 163, 224, 113, 72, 219, + 14, 180, 49, 24, 4, 127, 207, 169, 231, 197, 255, 239, 224, 85, 255, 153, 253, 1, + 1, 44, 12, 141, 103, 1, 0, 0, 1, 22, 99, 111, 117, 110, 116, 101, 114, 95, + 119, 105, 116, 104, 95, 109, 105, 108, 101, 115, 116, 111, 110, 101, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, 108, 105, 98, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 65, 112, 116, + 111, 115, 70, 114, 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 77, 111, 118, 101, - 83, 116, 100, 108, 105, 98, 0, + 0, 0, 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, 108, 105, + 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 77, 111, + 118, 101, 83, 116, 100, 108, 105, 98, 0, ] }); @@ -1936,24 +1999,26 @@ pub static MODULES_AGGREGATOR_EXAMPLES: Lazy>> = Lazy::new(|| { vec! pub static PACKAGE_BCS_STREAM_METADATA: Lazy> = Lazy::new(|| { vec![ 9, 66, 67, 83, 83, 116, 114, 101, 97, 109, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 64, 51, 53, 54, 53, 51, 54, 51, 69, 56, 68, 49, 69, 50, 52, 56, 51, - 69, 55, 69, 53, 50, 70, 69, 49, 53, 50, 55, 68, 56, 55, 50, 69, 65, 67, - 54, 53, 55, 51, 48, 57, 66, 68, 53, 69, 50, 53, 48, 55, 70, 57, 70, 55, - 50, 67, 50, 48, 56, 67, 49, 54, 66, 66, 54, 57, 145, 1, 31, 139, 8, 0, - 0, 0, 0, 0, 2, 255, 29, 205, 65, 10, 195, 32, 16, 5, 208, 253, 156, 66, - 220, 215, 244, 2, 93, 164, 161, 189, 128, 203, 16, 202, 68, 167, 69, 98, 84, 28, - 105, 11, 165, 119, 143, 202, 204, 234, 243, 62, 127, 78, 104, 54, 124, 209, 2, 1, - 119, 18, 23, 33, 175, 147, 214, 37, 19, 238, 18, 222, 148, 217, 197, 208, 210, 179, - 170, 39, 1, 102, 180, 54, 19, 51, 241, 2, 171, 225, 7, 119, 218, 197, 119, 26, - 239, 183, 70, 44, 37, 10, 150, 130, 113, 77, 141, 169, 68, 214, 197, 122, 183, 86, - 246, 19, 62, 26, 244, 173, 160, 212, 80, 255, 153, 235, 238, 39, 230, 109, 192, 6, - 79, 220, 165, 20, 127, 56, 0, 149, 1, 61, 109, 155, 0, 0, 0, 1, 10, 98, - 99, 115, 95, 115, 116, 114, 101, 97, 109, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 64, 66, 48, 65, 50, 57, 67, 53, 52, 66, 51, 55, 54, 67, 69, 56, 69, + 66, 55, 69, 49, 53, 68, 70, 57, 67, 54, 52, 66, 53, 68, 51, 53, 68, 52, + 65, 68, 67, 51, 50, 65, 57, 52, 65, 69, 57, 66, 56, 49, 50, 48, 57, 57, + 68, 48, 53, 56, 51, 67, 49, 66, 55, 49, 48, 54, 179, 1, 31, 139, 8, 0, + 0, 0, 0, 0, 2, 255, 45, 206, 205, 10, 194, 48, 12, 0, 224, 123, 159, 162, + 244, 172, 155, 103, 193, 131, 14, 125, 129, 29, 199, 144, 180, 141, 91, 217, 250, 67, + 211, 77, 65, 124, 119, 219, 41, 185, 228, 231, 75, 72, 23, 64, 77, 48, 96, 207, + 28, 88, 228, 39, 46, 46, 77, 219, 166, 136, 96, 5, 91, 49, 146, 241, 174, 116, + 15, 85, 14, 193, 88, 7, 90, 71, 36, 66, 234, 153, 84, 116, 167, 141, 110, 226, + 213, 156, 111, 215, 66, 52, 6, 116, 26, 157, 50, 69, 157, 67, 242, 212, 38, 61, + 27, 153, 217, 155, 15, 38, 21, 62, 166, 20, 232, 88, 215, 185, 28, 23, 89, 41, + 111, 107, 40, 114, 63, 131, 164, 127, 250, 136, 249, 167, 167, 143, 83, 149, 149, 216, + 113, 90, 164, 54, 177, 108, 255, 230, 180, 93, 205, 131, 136, 107, 233, 90, 48, 206, + 97, 18, 252, 195, 190, 12, 3, 21, 8, 216, 0, 0, 0, 1, 10, 98, 99, 115, + 95, 115, 116, 114, 101, 97, 109, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, - 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, - 77, 111, 118, 101, 83, 116, 100, 108, 105, 98, 0, + 0, 0, 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, 108, 105, + 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 77, 111, + 118, 101, 83, 116, 100, 108, 105, 98, 0, ] }); diff --git a/testsuite/module-publish/src/packages/framework_usecases/sources/vector_example.move b/testsuite/module-publish/src/packages/framework_usecases/sources/vector_example.move new file mode 100644 index 0000000000000..81fc72256c09a --- /dev/null +++ b/testsuite/module-publish/src/packages/framework_usecases/sources/vector_example.move @@ -0,0 +1,47 @@ + +/// test speed of vector operations +module 0xABCD::vector_example { + use std::vector; + + fun generate_vec(vec_len: u64, element_len: u64): vector> { + let elem = vector::empty(); + for (i in 0..element_len) { + vector::push_back(&mut elem, i); + }; + let vec = vector::empty(); + for (i in 0..vec_len) { + let cur = elem; + vector::replace(&mut cur, 0, i); + vector::push_back(&mut vec, cur); + }; + vec + } + + public entry fun test_trim_append(vec_len: u64, element_len: u64, index: u64, repeats: u64) { + let vec = generate_vec(vec_len, element_len); + + for (i in 0..repeats) { + let part = vector::trim(&mut vec, index); + vector::append(&mut vec, part); + }; + } + + public entry fun test_remove_insert(vec_len: u64, element_len: u64, index: u64, repeats: u64) { + let vec = generate_vec(vec_len, element_len); + + for (i in 0..repeats) { + let part = vector::remove(&mut vec, index); + vector::insert(&mut vec, index, part); + }; + } + + public entry fun test_middle_range_move(vec_len: u64, element_len: u64, index: u64, move_len: u64, repeats: u64) { + let vec1 = generate_vec(vec_len, element_len); + let vec2 = generate_vec(vec_len, element_len); + + for (i in 0..repeats) { + vector::move_range(&mut vec1, index, move_len, &mut vec2, index); + vector::move_range(&mut vec2, index, move_len, &mut vec1, index); + }; + } +} diff --git a/testsuite/single_node_performance.py b/testsuite/single_node_performance.py index 1208b7629d85e..dc069877890be 100755 --- a/testsuite/single_node_performance.py +++ b/testsuite/single_node_performance.py @@ -288,6 +288,9 @@ class RunGroupConfig: RunGroupConfig(key=RunGroupKey("no-op-fee-payer", module_working_set_size=DEFAULT_MODULE_WORKING_SET_SIZE), included_in=Flow.CONTINUOUS), RunGroupConfig(key=RunGroupKey("simple-script"), included_in=LAND_BLOCKING_AND_C, waived=True), + RunGroupConfig(expected_tps=394, key=RunGroupKey("vector-trim-append-len3000-size1"), included_in=Flow.CONTINUOUS, waived=True), + RunGroupConfig(expected_tps=398, key=RunGroupKey("vector-remove-insert-len3000-size1"), included_in=Flow.CONTINUOUS, waived=True), + RunGroupConfig(expected_tps=50000, key=RunGroupKey("coin_transfer_connected_components", executor_type="sharded"), key_extra=RunGroupKeyExtra(sharding_traffic_flags="--connected-tx-grps 5000", transaction_type_override=""), included_in=Flow.REPRESENTATIVE, waived=True), RunGroupConfig(expected_tps=50000, key=RunGroupKey("coin_transfer_hotspot", executor_type="sharded"), key_extra=RunGroupKeyExtra(sharding_traffic_flags="--hotspot-probability 0.8", transaction_type_override=""), included_in=Flow.REPRESENTATIVE, waived=True),