Skip to content

Commit

Permalink
Add an example that does allocation using the SDK's alloc function.
Browse files Browse the repository at this point in the history
  • Loading branch information
jayz22 authored and graydon committed Aug 3, 2023
1 parent 9a108f5 commit 457d804
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 1 deletion.
30 changes: 29 additions & 1 deletion soroban-env-host/src/test/invocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use soroban_env_common::{
use crate::{
events::HostEvent, xdr::ScErrorType, ContractFunctionSet, Error, Host, HostError, Symbol, Tag,
};
use soroban_test_wasms::{ADD_I32, ERR, INVOKE_CONTRACT, VEC};
use soroban_test_wasms::{ADD_I32, ALLOC, ERR, INVOKE_CONTRACT, VEC};

#[test]
fn invoke_single_contract_function() -> Result<(), HostError> {
Expand All @@ -36,6 +36,34 @@ fn invoke_single_contract_function() -> Result<(), HostError> {
Ok(())
}

#[test]
fn invoke_alloc() -> Result<(), HostError> {
let host = Host::test_host_with_recording_footprint();
host.enable_debug()?;
let contract_id_obj = host.register_test_contract_wasm(ALLOC);
let res = host.call(
contract_id_obj,
Symbol::try_from_small_str("sum")?,
host.test_vec_obj::<u32>(&[128])?,
)?;
assert!(res.shallow_eq(&8128_u32.into()));
let used_bytes = host.budget_cloned().get_mem_bytes_consumed()?;
// The general pattern of memory growth in this contract will be a sequence
// of vector-doublings, but these are masked by the fact that we only see
// the calls that cause the backing vector of wasm linear memory to grow,
// which happens as the guest vector crosses 64k boundaries (and eventually
// starts growing in steps larger than 64k itself).
//
// So we wind up with a growth-sequence that's a bit irregular: +0x10000,
// +0x20000, +0x30000, +0x50000, +0x90000. Total is 1 + 2 + 3 + 5 + 9 = 20
// pages or about 1.3 MiB, plus the initial 17 pages (1.1MiB) plus some more
// slop from general host machinery allocations, we get around 2.5MiB. Call
// is "less than 3MiB".
assert!(used_bytes > (128 * 4096));
assert!(used_bytes < 0x30_0000);
Ok(())
}

fn invoke_cross_contract(diagnostics: bool) -> Result<(), HostError> {
let host = Host::test_host_with_recording_footprint();
if diagnostics {
Expand Down
1 change: 1 addition & 0 deletions soroban-test-wasms/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

pub const ADD_I32: &[u8] = include_bytes!("../wasm-workspace/opt/example_add_i32.wasm").as_slice();
pub const ADD_F32: &[u8] = include_bytes!("../wasm-workspace/opt/example_add_f32.wasm").as_slice();
pub const ALLOC: &[u8] = include_bytes!("../wasm-workspace/opt/example_alloc.wasm").as_slice();
pub const CREATE_CONTRACT: &[u8] =
include_bytes!("../wasm-workspace/opt/example_create_contract.wasm").as_slice();
pub const CONTRACT_STORAGE: &[u8] =
Expand Down
7 changes: 7 additions & 0 deletions soroban-test-wasms/wasm-workspace/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions soroban-test-wasms/wasm-workspace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ resolver = "2"
members = [
"add_i32",
"add_f32",
"alloc",
"auth",
"fib",
"contract_data",
Expand Down
15 changes: 15 additions & 0 deletions soroban-test-wasms/wasm-workspace/alloc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "example_alloc"
version = "0.0.0"
authors = ["Stellar Development Foundation <[email protected]>"]
license = "Apache-2.0"
edition = "2021"
publish = false
rust-version = "1.65"

[lib]
crate-type = ["cdylib", "rlib"]
doctest = false

[dependencies]
soroban-sdk = { workspace = true, features = ["alloc"] }
27 changes: 27 additions & 0 deletions soroban-test-wasms/wasm-workspace/alloc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#![no_std]
use soroban_sdk::{contract, contractimpl, Env};

extern crate alloc;

#[contract]
pub struct AllocContract;

struct Large {
x: u32,
space: [u8;4096]
}

#[contractimpl]
impl AllocContract {
/// Allocates a temporary vector holding values (0..count), then computes
/// and returns their sum. Also allocates these values in a "large"
/// structure (with a bunch of pointless padding) to ensure the contract
/// allocates lots of memory.
pub fn sum(_env: Env, count: u32) -> u32 {
let mut v1 = alloc::vec![];
for i in 0..count {
v1.push(Large{x: i, space: [0u8; 4096]})
}
v1.iter().map(|l| l.x + l.space[0] as u32).sum()
}
}
Binary file not shown.

0 comments on commit 457d804

Please sign in to comment.