Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Memory allocation #40

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
628 changes: 187 additions & 441 deletions Cargo.lock

Large diffs are not rendered by default.

19 changes: 13 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,19 @@ edition = "2021"
publish = false

[workspace.dependencies]
gstd = "=1.7.0"
gclient = "=1.7.0"
gear-core = "=1.7.0"
sails-rs = "=0.7.1"
sails-idl-gen = "=0.7.1"
sails-client-gen = "=0.7.1"
gstd = { git = "https://github.com/gear-tech/gear", rev = "a967e294eb8f3b55c8cf4caa3b8036d155dfde23" }
gclient = { git = "https://github.com/gear-tech/gear", rev = "a967e294eb8f3b55c8cf4caa3b8036d155dfde23" }
gear-core = { git = "https://github.com/gear-tech/gear", rev = "a967e294eb8f3b55c8cf4caa3b8036d155dfde23" }

sails-rs = { path = "../sails/rs", package = "sails-rs" }
sails-idl-gen = { path = "../sails/rs/idl-gen", package = "sails-idl-gen" }
sails-client-gen = { path = "../sails/rs/client-gen", package = "sails-client-gen" }
# gstd = "=1.7.0"
# gclient = "=1.7.0"
# gear-core = "=1.7.0"
# sails-rs = "=0.7.1"
# sails-idl-gen = "=0.7.1"
# sails-client-gen = "=0.7.1"
log = "*"
env_logger = "*"
tokio = { version = "1.41", features = ["rt", "macros"] }
Expand Down
2 changes: 1 addition & 1 deletion extended-vft/app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ edition = "2021"

[dependencies]
sails-rs.workspace = true
gstd.workspace = true
gstd = { workspace = true, features = ["debug"] }
vft-service = { path = "../../vft-service" }
21 changes: 20 additions & 1 deletion extended-vft/app/src/services/extended_vft/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![allow(static_mut_refs)]
use gstd::msg;
use gstd::{debug, exec, msg};
use sails_rs::{collections::HashSet, gstd::service, prelude::*};
mod funcs;
use crate::services;
Expand Down Expand Up @@ -119,6 +119,17 @@ impl ExtendedService {
self.ensure_is_admin();
self.get_mut().burners.remove(&from);
}
pub fn reserve_capacity(
&mut self,
additionally_for_balances: u128,
additionally_for_allowances: u128,
) {
debug!("BEFORE: GAS = {:?}", exec::gas_available());
self.ensure_is_admin();
Storage::balances().reserve(additionally_for_balances as usize);
Storage::allowances().reserve(additionally_for_allowances as usize);
debug!("AFTER: GAS = {:?}", exec::gas_available());
}
pub fn minters(&self) -> Vec<ActorId> {
self.get().minters.clone().into_iter().collect()
}
Expand All @@ -130,6 +141,14 @@ impl ExtendedService {
pub fn admins(&self) -> Vec<ActorId> {
self.get().admins.clone().into_iter().collect()
}

pub fn balances_capacity(&self) -> u128 {
Storage::balances().capacity() as u128
}

pub fn allowances_capacity(&self) -> u128 {
Storage::allowances().capacity() as u128
}
}

impl ExtendedService {
Expand Down
85 changes: 85 additions & 0 deletions extended-vft/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use extended_vft_client::{
ExtendedVftFactory as Factory, Vft as VftClient,
};
use sails_rs::calls::*;
use sails_rs::collections::HashMap;
use sails_rs::gtest::{calls::*, System};
use sails_rs::{ActorId, U256};
use std::mem;

pub const ADMIN_ID: u64 = 10;
pub const USER_ID: [u64; 2] = [11, 12];
Expand Down Expand Up @@ -237,3 +240,85 @@ async fn test_grant_role() {
let burners = client.burners().recv(extended_vft_id).await.unwrap();
assert_eq!(burners, vec![ADMIN_ID.into()]);
}

#[tokio::test]
async fn test_memory_allocation() {
let system = System::new();
system.init_logger();
system.mint_to(ADMIN_ID, 1_000_000_000_000_000_000);

let program_space = GTestRemoting::new(system, ADMIN_ID.into());
let code_id = program_space
.system()
.submit_code_file("../target/wasm32-unknown-unknown/release/extended_vft.opt.wasm");

let extended_vft_factory = Factory::new(program_space.clone());
let extended_vft_id = extended_vft_factory
.new("name".to_string(), "symbol".to_string(), 10)
.send_recv(code_id, "123")
.await
.unwrap();

let mut client = VftClient::new(program_space.clone());

let mut user_id: u64 = 11;

let key_size = mem::size_of::<ActorId>();
let value_size = mem::size_of::<U256>();
let entry_size = key_size + value_size;

let mut balances_capacity = client
.balances_capacity()
.recv(extended_vft_id)
.await
.unwrap();

let balances_capacity_in_bytes = balances_capacity as usize * entry_size;

println!("Balances capacity (elements): {:?}", balances_capacity);
println!(
"Balances capacity (bytes): {:?}",
balances_capacity_in_bytes
);

loop {
client
.mint(user_id.into(), 10.into())
.send_recv(extended_vft_id)
.await
.unwrap();
if user_id % 25_000 == 0 {
println!("\nUSER ID {:?}", user_id);

if user_id as u128 + 30_000 > balances_capacity {
client
.reserve_capacity(100_000 as u128, 0)
.send_recv(extended_vft_id)
.await
.unwrap();

balances_capacity = client
.balances_capacity()
.recv(extended_vft_id)
.await
.unwrap();

let balances_capacity_in_bytes = balances_capacity as usize * entry_size;

println!("Balances capacity (elements): {:?}", balances_capacity);
println!(
"Balances capacity (bytes): {:?}",
balances_capacity_in_bytes
);
}
}
user_id += 1;
}
}

fn hash_map_memory_usage<K, V>(map: &HashMap<K, V>) -> usize {
let num_buckets = map.capacity();
let static_size = mem::size_of::<HashMap<K, V>>();
let bucket_size = mem::size_of::<(K, V)>() * num_buckets;
static_size + bucket_size
}
38 changes: 36 additions & 2 deletions extended-vmt/app/src/services/extended_vmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ impl ExtendedService {
let admin = msg::source();
unsafe {
EXTENDED_STORAGE = Some(ExtendedStorage {
token_metadata: HashMap::new(),
owners: HashMap::new(),
token_metadata: HashMap::with_capacity(u16::MAX as usize),
owners: HashMap::with_capacity(u16::MAX as usize),
admins: [admin].into(),
minters: [admin].into(),
burners: [admin].into(),
Expand Down Expand Up @@ -194,6 +194,24 @@ impl ExtendedService {
self.ensure_is_admin();
self.get_mut().burners.remove(&from);
}
pub fn reserve_capacity(
&mut self,
additionally_for_balances: u128,
additionally_for_allowances: u128,
additionally_for_token_metadata: u128,
additionally_for_owners: u128,
) {
self.ensure_is_admin();
Storage::balances().reserve(additionally_for_balances as usize);
Storage::allowances().reserve(additionally_for_allowances as usize);
self.get_mut()
.token_metadata
.reserve(additionally_for_token_metadata as usize);
self.get_mut()
.owners
.reserve(additionally_for_owners as usize);
}

pub fn minters(&self) -> Vec<ActorId> {
self.get().minters.clone().into_iter().collect()
}
Expand All @@ -205,6 +223,22 @@ impl ExtendedService {
pub fn admins(&self) -> Vec<ActorId> {
self.get().admins.clone().into_iter().collect()
}

pub fn balances_capacity(&self) -> u128 {
Storage::balances().capacity() as u128
}

pub fn allowances_capacity(&self) -> u128 {
Storage::allowances().capacity() as u128
}

pub fn token_metadata_capacity(&self) -> u128 {
self.get().token_metadata.capacity() as u128
}

pub fn owners_capacity(&self) -> u128 {
self.get().owners.capacity() as u128
}
}

impl ExtendedService {
Expand Down
28 changes: 28 additions & 0 deletions extended-vnft/app/src/services/extended_vnft/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ impl ExtendedService {
admins: [admin].into(),
minters: [admin].into(),
burners: [admin].into(),
token_metadata_by_id: HashMap::with_capacity(u16::MAX as usize),
..Default::default()
});
};
Expand Down Expand Up @@ -148,6 +149,21 @@ impl ExtendedService {
self.ensure_is_admin();
self.get_mut().burners.remove(&from);
}
pub fn reserve_capacity(
&mut self,
additionally_for_owner_by_id: u128,
additionally_for_tokens_for_owner: u128,
additionally_for_token_approvals: u128,
additionally_for_token_metadata_by_id: u128,
) {
self.ensure_is_admin();
Storage::owner_by_id().reserve(additionally_for_owner_by_id as usize);
Storage::tokens_for_owner().reserve(additionally_for_tokens_for_owner as usize);
Storage::token_approvals().reserve(additionally_for_token_approvals as usize);
self.get_mut()
.token_metadata_by_id
.reserve(additionally_for_token_metadata_by_id as usize);
}
pub fn minters(&self) -> Vec<ActorId> {
self.get().minters.clone().into_iter().collect()
}
Expand Down Expand Up @@ -176,6 +192,18 @@ impl ExtendedService {
})
.collect()
}
pub fn owner_by_id_capacity(&self) -> u128 {
Storage::owner_by_id().capacity() as u128
}
pub fn tokens_for_owner_capacity(&self) -> u128 {
Storage::tokens_for_owner().capacity() as u128
}
pub fn token_approvals_capacity(&self) -> u128 {
Storage::token_approvals().capacity() as u128
}
pub fn token_metadata_by_id_capacity(&self) -> u128 {
self.get().token_metadata_by_id.capacity() as u128
}
}

impl ExtendedService {
Expand Down
6 changes: 6 additions & 0 deletions vft-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ impl Storage {
let storage = unsafe { STORAGE.as_mut().expect("Storage is not initialized") };
&mut storage.balances
}
pub fn allowances() -> &'static mut HashMap<(ActorId, ActorId), U256> {
let storage = unsafe { STORAGE.as_mut().expect("Storage is not initialized") };
&mut storage.allowances
}
pub fn total_supply() -> &'static mut U256 {
let storage = unsafe { STORAGE.as_mut().expect("Storage is not initialized") };
&mut storage.total_supply
Expand Down Expand Up @@ -67,6 +71,8 @@ impl Service {
pub fn seed(name: String, symbol: String, decimals: u8) -> Self {
unsafe {
STORAGE = Some(Storage {
balances: HashMap::with_capacity(u16::MAX as usize),
allowances: HashMap::with_capacity(u16::MAX as usize),
meta: Metadata {
name,
symbol,
Expand Down
2 changes: 2 additions & 0 deletions vmt-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ impl Service {
pub fn seed(name: String, symbol: String, decimals: u8) -> Self {
unsafe {
STORAGE = Some(Storage {
balances: HashMap::with_capacity(u16::MAX as usize),
allowances: HashMap::with_capacity(u16::MAX as usize),
meta: Metadata {
name,
symbol,
Expand Down
4 changes: 3 additions & 1 deletion vnft-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ impl Service {
STORAGE = Some(Storage {
name,
symbol,
..Default::default()
owner_by_id: HashMap::with_capacity(u16::MAX as usize),
tokens_for_owner: HashMap::with_capacity(u16::MAX as usize),
token_approvals: HashMap::with_capacity(u16::MAX as usize),
});
}
Self()
Expand Down
Loading