Skip to content

Commit a925bbc

Browse files
Use of the Arc<Box<[u8]>> for the CompressedBytecode. (#4418)
## Motivation We are using the `Vec<u8>` in the `CompressedBytecode`. But the vector is never modified so this makes a copy that is not needed. ## Proposal The compressed bytecode is now a `Arc<Box<[u8]>>`. An alternative could have been to use `BlobContent`. However, we would need to track the `BlobType`, which would be hard. ## Test Plan The CI. ## Release Plan - Nothing to do / These changes follow the usual release cycle. ## Links None.
1 parent 79c7b33 commit a925bbc

File tree

4 files changed

+40
-27
lines changed

4 files changed

+40
-27
lines changed

linera-base/src/data_types.rs

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use async_graphql::{InputObject, SimpleObject};
2323
use custom_debug_derive::Debug;
2424
use linera_witty::{WitLoad, WitStore, WitType};
2525
use serde::{Deserialize, Deserializer, Serialize, Serializer};
26+
use serde_with::{serde_as, Bytes};
2627
use thiserror::Error;
2728

2829
#[cfg(with_metrics)]
@@ -1124,10 +1125,12 @@ impl Bytecode {
11241125
pub fn compress(&self) -> CompressedBytecode {
11251126
#[cfg(with_metrics)]
11261127
let _compression_latency = metrics::BYTECODE_COMPRESSION_LATENCY.measure_latency();
1127-
let compressed_bytes = zstd::stream::encode_all(&*self.bytes, 19)
1128+
let compressed_bytes_vec = zstd::stream::encode_all(&*self.bytes, 19)
11281129
.expect("Compressing bytes in memory should not fail");
11291130

1130-
CompressedBytecode { compressed_bytes }
1131+
CompressedBytecode {
1132+
compressed_bytes: Arc::new(compressed_bytes_vec.into_boxed_slice()),
1133+
}
11311134
}
11321135

11331136
/// Compresses the [`Bytecode`] into a [`CompressedBytecode`].
@@ -1138,13 +1141,15 @@ impl Bytecode {
11381141
#[cfg(with_metrics)]
11391142
let _compression_latency = metrics::BYTECODE_COMPRESSION_LATENCY.measure_latency();
11401143

1141-
let mut compressed_bytes = Vec::new();
1144+
let mut compressed_bytes_vec = Vec::new();
11421145
let mut compressor = FrameCompressor::new(CompressionLevel::Fastest);
11431146
compressor.set_source(&*self.bytes);
1144-
compressor.set_drain(&mut compressed_bytes);
1147+
compressor.set_drain(&mut compressed_bytes_vec);
11451148
compressor.compress();
11461149

1147-
CompressedBytecode { compressed_bytes }
1150+
CompressedBytecode {
1151+
compressed_bytes: Arc::new(compressed_bytes_vec.into_boxed_slice()),
1152+
}
11481153
}
11491154
}
11501155

@@ -1163,13 +1168,14 @@ pub enum DecompressionError {
11631168
}
11641169

11651170
/// A compressed module bytecode (WebAssembly or EVM).
1171+
#[serde_as]
11661172
#[derive(Clone, Debug, Deserialize, Hash, Serialize, WitType, WitStore)]
11671173
#[cfg_attr(with_testing, derive(Eq, PartialEq))]
11681174
pub struct CompressedBytecode {
11691175
/// Compressed bytes of the bytecode.
1170-
#[serde(with = "serde_bytes")]
1171-
#[debug(with = "hex_debug")]
1172-
pub compressed_bytes: Vec<u8>,
1176+
#[serde_as(as = "Arc<Bytes>")]
1177+
#[debug(skip)]
1178+
pub compressed_bytes: Arc<Box<[u8]>>,
11731179
}
11741180

11751181
#[cfg(not(target_arch = "wasm32"))]
@@ -1195,7 +1201,7 @@ impl CompressedBytecode {
11951201
pub fn decompress(&self) -> Result<Bytecode, DecompressionError> {
11961202
#[cfg(with_metrics)]
11971203
let _decompression_latency = metrics::BYTECODE_DECOMPRESSION_LATENCY.measure_latency();
1198-
let bytes = zstd::stream::decode_all(&*self.compressed_bytes)?;
1204+
let bytes = zstd::stream::decode_all(&**self.compressed_bytes)?;
11991205

12001206
Ok(Bytecode { bytes })
12011207
}
@@ -1232,7 +1238,7 @@ impl CompressedBytecode {
12321238

12331239
let compressed_bytes = &*self.compressed_bytes;
12341240
let mut bytes = Vec::new();
1235-
let mut decoder = StreamingDecoder::new(compressed_bytes).map_err(io::Error::other)?;
1241+
let mut decoder = StreamingDecoder::new(&**compressed_bytes).map_err(io::Error::other)?;
12361242

12371243
// TODO(#2710): Decode multiple frames, if present
12381244
while !decoder.get_ref().is_empty() {
@@ -1247,8 +1253,6 @@ impl CompressedBytecode {
12471253

12481254
impl BcsHashable<'_> for BlobContent {}
12491255

1250-
use serde_with::*;
1251-
12521256
/// A blob of binary data.
12531257
#[serde_as]
12541258
#[derive(Hash, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -1278,23 +1282,26 @@ impl BlobContent {
12781282

12791283
/// Creates a new contract bytecode [`BlobContent`] from the provided bytes.
12801284
pub fn new_contract_bytecode(compressed_bytecode: CompressedBytecode) -> Self {
1281-
BlobContent::new(
1282-
BlobType::ContractBytecode,
1283-
compressed_bytecode.compressed_bytes,
1284-
)
1285+
BlobContent {
1286+
blob_type: BlobType::ContractBytecode,
1287+
bytes: compressed_bytecode.compressed_bytes,
1288+
}
12851289
}
12861290

12871291
/// Creates a new contract bytecode [`BlobContent`] from the provided bytes.
12881292
pub fn new_evm_bytecode(compressed_bytecode: CompressedBytecode) -> Self {
1289-
BlobContent::new(BlobType::EvmBytecode, compressed_bytecode.compressed_bytes)
1293+
BlobContent {
1294+
blob_type: BlobType::EvmBytecode,
1295+
bytes: compressed_bytecode.compressed_bytes,
1296+
}
12901297
}
12911298

12921299
/// Creates a new service bytecode [`BlobContent`] from the provided bytes.
12931300
pub fn new_service_bytecode(compressed_bytecode: CompressedBytecode) -> Self {
1294-
BlobContent::new(
1295-
BlobType::ServiceBytecode,
1296-
compressed_bytecode.compressed_bytes,
1297-
)
1301+
BlobContent {
1302+
blob_type: BlobType::ServiceBytecode,
1303+
bytes: compressed_bytecode.compressed_bytes,
1304+
}
12981305
}
12991306

13001307
/// Creates a new application description [`BlobContent`] from a [`ApplicationDescription`].
@@ -1326,6 +1333,11 @@ impl BlobContent {
13261333
bytes.into_vec()
13271334
}
13281335

1336+
/// Get the Arc<Box<[u8]>> directly without cloning.
1337+
pub fn into_arc_bytes(self) -> Arc<Box<[u8]>> {
1338+
self.bytes
1339+
}
1340+
13291341
/// Returns the type of data represented by this blob's bytes.
13301342
pub fn blob_type(&self) -> BlobType {
13311343
self.blob_type

linera-execution/src/test_utils/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ pub fn create_dummy_user_application_description(
9090
contract_bytes.push(index as u8);
9191
service_bytes.push(index as u8);
9292
let contract_blob = Blob::new_contract_bytecode(CompressedBytecode {
93-
compressed_bytes: contract_bytes,
93+
compressed_bytes: Arc::new(contract_bytes.into_boxed_slice()),
9494
});
9595
let service_blob = Blob::new_service_bytecode(CompressedBytecode {
96-
compressed_bytes: service_bytes,
96+
compressed_bytes: Arc::new(service_bytes.into_boxed_slice()),
9797
});
9898

9999
let vm_runtime = VmRuntime::Wasm;

linera-execution/tests/contract_runtime_apis.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
use std::{
77
collections::{BTreeMap, BTreeSet},
8+
sync::Arc,
89
vec,
910
};
1011

@@ -672,15 +673,15 @@ impl TransferTestEndpoint {
672673
/// sender as an application.
673674
fn sender_application_contract_blob() -> Blob {
674675
Blob::new_contract_bytecode(CompressedBytecode {
675-
compressed_bytes: b"sender contract".to_vec(),
676+
compressed_bytes: Arc::new(b"sender contract".to_vec().into_boxed_slice()),
676677
})
677678
}
678679

679680
/// Returns the [`Blob`] that represents the service bytecode used when representing the sender
680681
/// as an application.
681682
fn sender_application_service_blob() -> Blob {
682683
Blob::new_service_bytecode(CompressedBytecode {
683-
compressed_bytes: b"sender service".to_vec(),
684+
compressed_bytes: Arc::new(b"sender service".to_vec().into_boxed_slice()),
684685
})
685686
}
686687

linera-storage/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ pub trait Storage: Sized {
276276
.into_content(),
277277
};
278278
let compressed_contract_bytecode = CompressedBytecode {
279-
compressed_bytes: content.into_vec_or_clone(),
279+
compressed_bytes: content.into_arc_bytes(),
280280
};
281281
#[cfg_attr(not(any(with_wasm_runtime, with_revm)), allow(unused_variables))]
282282
let contract_bytecode =
@@ -343,7 +343,7 @@ pub trait Storage: Sized {
343343
.into_content(),
344344
};
345345
let compressed_service_bytecode = CompressedBytecode {
346-
compressed_bytes: content.into_vec_or_clone(),
346+
compressed_bytes: content.into_arc_bytes(),
347347
};
348348
#[cfg_attr(not(any(with_wasm_runtime, with_revm)), allow(unused_variables))]
349349
let service_bytecode = linera_base::task::Blocking::<linera_base::task::NoInput, _>::spawn(

0 commit comments

Comments
 (0)