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

refactor(core-code) Optimisation of read-write structures for code instrumentation #4274

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
13 changes: 4 additions & 9 deletions common/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use super::*;

use gear_core::{
ids::prelude::*,
pages::{WasmPage, WasmPagesAmount},
pages::WasmPage,
program::{MemoryInfix, ProgramState},
reservation::GasReservationMap,
};
Expand Down Expand Up @@ -117,21 +117,16 @@ pub fn generate_wasm(num_pages: WasmPage) -> Result<Vec<u8>, &'static str> {
Ok(code)
}

pub fn set_program<ProgramStorage, BlockNumber>(
program_id: ProgramId,
code: Vec<u8>,
static_pages: WasmPagesAmount,
) where
pub fn set_program<ProgramStorage, BlockNumber>(program_id: ProgramId, code: Vec<u8>)
where
ProgramStorage: super::ProgramStorage<BlockNumber = BlockNumber>,
BlockNumber: Zero + Copy + Saturating,
{
ProgramStorage::add_program(
program_id,
ActiveProgram {
allocations_tree_len: 0,
code_hash: CodeId::generate(&code).into_origin(),
code_exports: Default::default(),
static_pages,
code_id: CodeId::generate(&code),
state: ProgramState::Initialized,
gas_reservation_map: GasReservationMap::default(),
expiration_block: Zero::zero(),
Expand Down
50 changes: 27 additions & 23 deletions common/src/code_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use super::*;
use crate::storage::MapStorage;
use gear_core::code::{CodeAndId, InstrumentedCode, InstrumentedCodeAndId};
use gear_core::code::{CodeAndId, CodeAttribution, CodeMetadata, InstrumentedCode};

#[derive(Clone, Copy, Debug)]
pub enum Error {
Expand All @@ -29,44 +29,48 @@ pub enum Error {
/// Trait to work with program binary codes in a storage.
pub trait CodeStorage {
type InstrumentedCodeStorage: MapStorage<Key = CodeId, Value = InstrumentedCode>;
type InstrumentedLenStorage: MapStorage<Key = CodeId, Value = u32>;
type OriginalCodeStorage: MapStorage<Key = CodeId, Value = Vec<u8>>;
type MetadataStorage: MapStorage<Key = CodeId, Value = CodeMetadata>;
type CodeMetadataStorage: MapStorage<Key = CodeId, Value = CodeMetadata>;
type CodeAttributionStorage: MapStorage<Key = CodeId, Value = CodeAttribution>;

/// Attempt to remove all items from all the associated maps.
fn reset() {
Self::MetadataStorage::clear();
Self::CodeAttributionStorage::clear();
Self::CodeMetadataStorage::clear();
Self::OriginalCodeStorage::clear();
Self::InstrumentedLenStorage::clear();
Self::InstrumentedCodeStorage::clear();
}

fn add_code(code_and_id: CodeAndId, metadata: CodeMetadata) -> Result<(), Error> {
/// Add the code to the storage.
fn add_code(code_and_id: CodeAndId, code_attribution: CodeAttribution) -> Result<(), Error> {
let (code, code_id) = code_and_id.into_parts();
let (code, original_code) = code.into_parts();
let (instrumented_code, original_code, code_metadata) = code.into_parts();

Self::InstrumentedCodeStorage::mutate(code_id, |maybe| {
if maybe.is_some() {
return Err(CodeStorageError::DuplicateItem);
}

Self::InstrumentedLenStorage::insert(code_id, code.code().len() as u32);
Self::OriginalCodeStorage::insert(code_id, original_code);
Self::MetadataStorage::insert(code_id, metadata);
Self::CodeMetadataStorage::insert(code_id, code_metadata);
Self::CodeAttributionStorage::insert(code_id, code_attribution);

*maybe = Some(code);
*maybe = Some(instrumented_code);
Ok(())
})
}

/// Update the corresponding code in the storage.
fn update_code(code_and_id: InstrumentedCodeAndId) {
let (code, code_id) = code_and_id.into_parts();
fn update_instrumented_code(code_id: CodeId, instrumented_code: InstrumentedCode) {
Self::InstrumentedCodeStorage::insert(code_id, instrumented_code);
}

Self::InstrumentedLenStorage::insert(code_id, code.code().len() as u32);
Self::InstrumentedCodeStorage::insert(code_id, code);
/// Update the corresponding metadata in the storage.
fn update_code_metadata(code_id: CodeId, metadata: CodeMetadata) {
Self::CodeMetadataStorage::insert(code_id, metadata);
}

/// Returns true if the code associated with given id exists.
fn exists(code_id: CodeId) -> bool {
Self::InstrumentedCodeStorage::contains_key(&code_id)
}
Expand All @@ -80,28 +84,28 @@ pub trait CodeStorage {
return false;
}

Self::InstrumentedLenStorage::remove(code_id);
Self::OriginalCodeStorage::remove(code_id);
Self::MetadataStorage::remove(code_id);
Self::CodeMetadataStorage::remove(code_id);
Self::CodeAttributionStorage::remove(code_id);

*maybe = None;
true
})
}

fn get_code(code_id: CodeId) -> Option<InstrumentedCode> {
fn get_instrumented_code(code_id: CodeId) -> Option<InstrumentedCode> {
Self::InstrumentedCodeStorage::get(&code_id)
}

fn get_code_len(code_id: CodeId) -> Option<u32> {
Self::InstrumentedLenStorage::get(&code_id)
}

fn get_original_code(code_id: CodeId) -> Option<Vec<u8>> {
Self::OriginalCodeStorage::get(&code_id)
}

fn get_metadata(code_id: CodeId) -> Option<CodeMetadata> {
Self::MetadataStorage::get(&code_id)
fn get_code_metadata(code_id: CodeId) -> Option<CodeMetadata> {
Self::CodeMetadataStorage::get(&code_id)
}

fn get_code_attribution(code_id: CodeId) -> Option<CodeAttribution> {
Self::CodeAttributionStorage::get(&code_id)
}
}
18 changes: 0 additions & 18 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,24 +231,6 @@ pub trait BlockLimiter {
type GasAllowance: storage::Limiter<Value = Self::Balance>;
}

#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq, TypeInfo)]
#[codec(crate = codec)]
#[scale_info(crate = scale_info)]
pub struct CodeMetadata {
pub author: H256,
#[codec(compact)]
pub block_number: u32,
}

impl CodeMetadata {
pub fn new(author: H256, block_number: u32) -> Self {
CodeMetadata {
author,
block_number,
}
}
}

/// A trait whose purpose is to extract the `Call` variant of an extrinsic
pub trait ExtractCall<Call> {
fn extract_call(&self) -> Call;
Expand Down
22 changes: 21 additions & 1 deletion core-processor/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use alloc::{
vec::Vec,
};
use gear_core::{
code::InstrumentedCode,
code::{CodeMetadata, InstrumentedCode},
gas::{GasAllowanceCounter, GasAmount, GasCounter},
ids::{CodeId, MessageId, ProgramId, ReservationId},
memory::{MemoryError, MemorySetupError, PageBuf},
Expand Down Expand Up @@ -57,6 +57,15 @@ pub enum DispatchResultKind {
GasAllowanceExceed,
}

/// Possible variants of the [`DispatchResult`] if the latter contains value.
#[allow(missing_docs)]
#[derive(Debug)]
pub enum SuccessfulDispatchResultKind {
Exit(ProgramId),
Wait(Option<u32>, MessageWaitedType),
Success,
}

/// Result of the specific dispatch.
pub struct DispatchResult {
/// Kind of the dispatch.
Expand Down Expand Up @@ -534,6 +543,15 @@ pub struct ExecutableActorData {
pub gas_reservation_map: GasReservationMap,
}

/// Executable allocations data.
#[derive(Clone, Debug)]
pub struct ExecutableAllocationsData {
/// Amount of reservations can exist for 1 program.
pub max_reservations: u64,
/// Size of wasm memory buffer which must be created in execution environment
pub memory_size: WasmPagesAmount,
}

/// Program.
#[derive(Clone, Debug)]
pub(crate) struct Program {
Expand All @@ -543,6 +561,8 @@ pub(crate) struct Program {
pub memory_infix: MemoryInfix,
/// Instrumented code.
pub code: InstrumentedCode,
/// Code metadata.
pub code_metadata: CodeMetadata,
/// Allocations.
pub allocations: IntervalsTree<WasmPage>,
}
Expand Down
141 changes: 38 additions & 103 deletions core-processor/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@

//! Module contains context-structures for processing.

use crate::common::{ExecutableActorData, Program};
use crate::{
common::Program,
precharge::{ContextCharged, ForModuleInstantiation},
};
use gear_core::{
code::InstrumentedCode,
code::{CodeMetadata, InstrumentedCode},
gas::{GasAllowanceCounter, GasCounter},
ids::ProgramId,
message::IncomingDispatch,
Expand All @@ -29,88 +32,6 @@ use gear_core::{
reservation::GasReserver,
};

/// Struct with dispatch and counters charged for program data.
#[derive(Debug)]
pub struct ContextChargedForProgram {
pub(crate) dispatch: IncomingDispatch,
pub(crate) destination_id: ProgramId,
pub(crate) gas_counter: GasCounter,
pub(crate) gas_allowance_counter: GasAllowanceCounter,
}

impl ContextChargedForProgram {
/// Unwraps into inner data.
#[cfg(feature = "gtest")]
pub fn into_inner(self) -> (IncomingDispatch, ProgramId, GasCounter) {
(self.dispatch, self.destination_id, self.gas_counter)
}
}

pub struct ContextChargedForAllocations(pub(crate) ContextChargedForProgram);

pub(crate) struct ContextData {
pub(crate) gas_counter: GasCounter,
pub(crate) gas_allowance_counter: GasAllowanceCounter,
pub(crate) dispatch: IncomingDispatch,
pub(crate) destination_id: ProgramId,
pub(crate) actor_data: ExecutableActorData,
}

pub struct ContextChargedForCodeLength {
pub(crate) data: ContextData,
}

impl ContextChargedForCodeLength {
/// Returns reference to the ExecutableActorData.
pub fn actor_data(&self) -> &ExecutableActorData {
&self.data.actor_data
}
}

/// The instance returned by `precharge_for_code`.
/// Existence of the instance means that corresponding counters were
/// successfully charged for fetching the binary code from storage.
pub struct ContextChargedForCode {
pub(crate) data: ContextData,
}

impl From<ContextChargedForCodeLength> for ContextChargedForCode {
fn from(context: ContextChargedForCodeLength) -> Self {
Self { data: context.data }
}
}

/// The instance returned by `precharge_for_instrumentation`.
/// Existence of the instance means that corresponding counters were
/// successfully charged for reinstrumentation of the code.
pub struct ContextChargedForInstrumentation {
pub(crate) data: ContextData,
}

impl From<ContextChargedForCode> for ContextChargedForInstrumentation {
fn from(context: ContextChargedForCode) -> Self {
Self { data: context.data }
}
}

pub struct ContextChargedForMemory {
pub(crate) data: ContextData,
pub(crate) max_reservations: u64,
pub(crate) memory_size: WasmPagesAmount,
}

impl ContextChargedForMemory {
/// Returns reference to the ExecutableActorData.
pub fn actor_data(&self) -> &ExecutableActorData {
&self.data.actor_data
}

/// Returns reference to the GasCounter.
pub fn gas_counter(&self) -> &GasCounter {
&self.data.gas_counter
}
}

/// Checked parameters for message execution across processing runs.
pub struct ProcessExecutionContext {
pub(crate) gas_counter: GasCounter,
Expand All @@ -134,33 +55,47 @@ impl ProcessExecutionContext {
}
}

impl From<(ContextChargedForMemory, InstrumentedCode, u128)> for ProcessExecutionContext {
fn from(args: (ContextChargedForMemory, InstrumentedCode, u128)) -> Self {
let (context, code, balance) = args;

let ContextChargedForMemory {
data:
ContextData {
gas_counter,
gas_allowance_counter,
dispatch,
destination_id,
actor_data,
},
max_reservations,
memory_size,
} = context;
impl
From<(
ContextCharged<ForModuleInstantiation>,
InstrumentedCode,
CodeMetadata,
u128,
)> for ProcessExecutionContext
{
fn from(
args: (
ContextCharged<ForModuleInstantiation>,
InstrumentedCode,
CodeMetadata,
u128,
),
) -> Self {
let (context, code, code_metadata, balance) = args;

let (
destination_id,
dispatch,
gas_counter,
gas_allowance_counter,
actor_data,
allocations_data,
) = context.into_final_parts();

let program = Program {
id: destination_id,
memory_infix: actor_data.memory_infix,
code,
code_metadata,
allocations: actor_data.allocations,
};

// Must be created once per taken from the queue dispatch by program.
let gas_reserver =
GasReserver::new(&dispatch, actor_data.gas_reservation_map, max_reservations);
let gas_reserver = GasReserver::new(
&dispatch,
actor_data.gas_reservation_map,
allocations_data.max_reservations,
);

Self {
gas_counter,
Expand All @@ -169,7 +104,7 @@ impl From<(ContextChargedForMemory, InstrumentedCode, u128)> for ProcessExecutio
dispatch,
balance,
program,
memory_size,
memory_size: allocations_data.memory_size,
}
}
}
Expand Down
Loading
Loading