diff --git a/aptos-move/e2e-benchmark/src/main.rs b/aptos-move/e2e-benchmark/src/main.rs
index fd6365284d56d2..085935def8d230 100644
--- a/aptos-move/e2e-benchmark/src/main.rs
+++ b/aptos-move/e2e-benchmark/src/main.rs
@@ -85,6 +85,47 @@ const ALLOWED_REGRESSION: f64 = 0.15;
const ALLOWED_IMPROVEMENT: f64 = 0.15;
const ABSOLUTE_BUFFER_US: f64 = 2.0;
+<<<<<<< HEAD
+=======
+const CALIBRATION_VALUES: &str = "
+Loop { loop_count: Some(100000), loop_type: NoOp } 60 0.955 1.074 41893.7
+Loop { loop_count: Some(10000), loop_type: Arithmetic } 60 0.965 1.078 25915.0
+CreateObjects { num_objects: 10, object_payload_size: 0 } 60 0.924 1.082 158.1
+CreateObjects { num_objects: 10, object_payload_size: 10240 } 60 0.951 1.118 9356.2
+CreateObjects { num_objects: 100, object_payload_size: 0 } 60 0.926 1.082 1574.2
+CreateObjects { num_objects: 100, object_payload_size: 10240 } 60 0.952 1.092 11541.9
+InitializeVectorPicture { length: 128 } 10 0.965 1.038 163.3
+VectorPicture { length: 128 } 10 0.938 1.060 48.8
+VectorPictureRead { length: 128 } 10 0.977 1.077 46.4
+InitializeVectorPicture { length: 30720 } 60 0.948 1.123 27893.4
+VectorPicture { length: 30720 } 60 0.931 1.125 6923.1
+VectorPictureRead { length: 30720 } 60 0.934 1.102 6923.1
+SmartTablePicture { length: 30720, num_points_per_txn: 200 } 60 0.952 1.109 43594.7
+SmartTablePicture { length: 1048576, num_points_per_txn: 300 } 60 0.957 1.120 73865.4
+ResourceGroupsSenderWriteTag { string_length: 1024 } 60 0.934 1.134 15.0
+ResourceGroupsSenderMultiChange { string_length: 1024 } 60 0.929 1.122 32.3
+TokenV1MintAndTransferFT 60 0.958 1.093 385.2
+TokenV1MintAndTransferNFTSequential 60 0.973 1.139 588.1
+TokenV2AmbassadorMint { numbered: true } 60 0.960 1.141 512.5
+LiquidityPoolSwap { is_stable: true } 60 0.961 1.103 590.3
+LiquidityPoolSwap { is_stable: false } 60 0.954 1.134 552.2
+CoinInitAndMint 10 0.975 1.043 199.6
+FungibleAssetMint 10 0.954 1.038 236.3
+IncGlobalMilestoneAggV2 { milestone_every: 1 } 10 0.960 1.047 32.9
+IncGlobalMilestoneAggV2 { milestone_every: 2 } 10 0.971 1.066 18.1
+EmitEvents { count: 1000 } 10 0.969 1.052 8615.5
+VectorTrimAppend { vec_len: 3000, element_len: 1, index: 0, repeats: 0 } 6 0.925 1.001 22909
+VectorTrimAppend { vec_len: 3000, element_len: 1, index: 100, repeats: 1000 } 6 0.925 1.001 47073
+VectorTrimAppend { vec_len: 3000, element_len: 1, index: 2990, repeats: 1000 } 6 0.925 1.001 34788
+VectorRemoveInsert { vec_len: 3000, element_len: 1, index: 100, repeats: 1000 } 6 0.925 1.001 45273
+VectorRemoveInsert { vec_len: 3000, element_len: 1, index: 2998, repeats: 1000 } 6 0.925 1.001 36859
+VectorRangeMove { vec_len: 3000, element_len: 1, index: 1000, move_len: 500, repeats: 1000 } 6 0.925 1.001 65311
+VectorTrimAppend { vec_len: 100, element_len: 100, index: 0, repeats: 0 } 6 0.925 1.001 875
+VectorTrimAppend { vec_len: 100, element_len: 100, index: 10, repeats: 1000 } 6 0.925 1.001 13366
+VectorRangeMove { vec_len: 100, element_len: 100, index: 50, move_len: 10, repeats: 1000 } 6 0.925 1.001 7098
+";
+
+>>>>>>> cb36071f2f ([move][stdlib] Add vector::split_off and vector::remove library methods)
struct CalibrationInfo {
// count: usize,
expected_time_micros: f64,
@@ -176,6 +217,66 @@ fn main() {
EntryPoints::IncGlobalMilestoneAggV2 { milestone_every: 1 },
EntryPoints::IncGlobalMilestoneAggV2 { milestone_every: 2 },
EntryPoints::EmitEvents { count: 1000 },
+ // long vectors with small elements
+ EntryPoints::VectorTrimAppend {
+ // baseline, only vector creation
+ vec_len: 3000,
+ element_len: 1,
+ index: 0,
+ repeats: 0,
+ },
+ EntryPoints::VectorTrimAppend {
+ vec_len: 3000,
+ element_len: 1,
+ index: 100,
+ repeats: 1000,
+ },
+ EntryPoints::VectorTrimAppend {
+ 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::VectorTrimAppend {
+ // baseline, only vector creation
+ vec_len: 100,
+ element_len: 100,
+ index: 0,
+ repeats: 0,
+ },
+ EntryPoints::VectorTrimAppend {
+ 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();
diff --git a/aptos-move/framework/aptos-stdlib/doc/big_vector.md b/aptos-move/framework/aptos-stdlib/doc/big_vector.md
index 7d785a5b730a13..da978bc07ff9ec 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 3919625f4ff9cb..e5604063b60712 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
+
+
+
+
+public fun get_native_memory_operations_feature(): u64 { NATIVE_MEMORY_OPERATIONS }
+
+
+
+
+public fun is_native_memory_operations_enabled(): bool
+
+
+
+
+public fun is_native_memory_operations_enabled(): bool acquires Features {
+ is_enabled(NATIVE_MEMORY_OPERATIONS)
+}
+
+
+
+
+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 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<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 00000000000000..1fa207f777813b
--- /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 i
th 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 2bdba4056eaae8..2b3a5291c600d7 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 424766f4a2124e..e96db063db6c09 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 2d67042ef4fefc..a4408db3f2a7b3 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 ce558bc3e9cfc8..da2bc17dee7c99 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 fb0cc7779d4276..da2a5e5a5f3854 100644
--- a/crates/transaction-generator-lib/src/args.rs
+++ b/crates/transaction-generator-lib/src/args.rs
@@ -45,6 +45,8 @@ pub enum TransactionTypeArg {
CreateObjects100,
CreateObjects100WithPayload10k,
CreateObjectsConflict100WithPayload10k,
+ VectorTrimAppendLen3000Size1,
+ VectorRemoveInsertLen3000Size1,
ResourceGroupsGlobalWriteTag1KB,
ResourceGroupsGlobalWriteAndReadTag1KB,
ResourceGroupsSenderWriteTag1KB,
@@ -222,6 +224,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 f1b338bb23a164..de1ed2776c96a5 100644
--- a/crates/transaction-generator-lib/src/publishing/module_simple.rs
+++ b/crates/transaction-generator-lib/src/publishing/module_simple.rs
@@ -229,6 +229,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
@@ -306,6 +325,9 @@ impl EntryPoints {
| EntryPoints::ModifyGlobalBoundedAggV2 { .. }
| EntryPoints::CreateObjects { .. }
| EntryPoints::CreateObjectsConflict { .. }
+ | EntryPoints::VectorTrimAppend { .. }
+ | EntryPoints::VectorRemoveInsert { .. }
+ | EntryPoints::VectorRangeMove { .. }
| EntryPoints::TokenV1InitializeCollection
| EntryPoints::TokenV1MintAndStoreNFTParallel
| EntryPoints::TokenV1MintAndStoreNFTSequential
@@ -365,6 +387,9 @@ impl EntryPoints {
EntryPoints::CreateObjects { .. } | EntryPoints::CreateObjectsConflict { .. } => {
"objects"
},
+ EntryPoints::VectorTrimAppend { .. }
+ | EntryPoints::VectorRemoveInsert { .. }
+ | EntryPoints::VectorRangeMove { .. } => "vector_example",
EntryPoints::TokenV1InitializeCollection
| EntryPoints::TokenV1MintAndStoreNFTParallel
| EntryPoints::TokenV1MintAndStoreNFTSequential
@@ -556,6 +581,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(),
@@ -825,6 +895,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 195b894efff285..ba9b760d122aea 100644
--- a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs
+++ b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs
@@ -1000,11 +1000,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,
@@ -1016,13 +1016,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,
@@ -1602,6 +1603,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(),
@@ -1610,6 +1668,7 @@ 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(|| {
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 00000000000000..81fc72256c09a9
--- /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 69a571cbadbc68..8528cf41e7a905 100755
--- a/testsuite/single_node_performance.py
+++ b/testsuite/single_node_performance.py
@@ -253,6 +253,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),
+ 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),