Skip to content

Commit 2128991

Browse files
simongdaviesludfjig
authored andcommitted
Add PageSnapshot struct for efficient memory snapshot management
Signed-off-by: Simon Davies <[email protected]>
1 parent 78934ae commit 2128991

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
Copyright 2025 The Hyperlight Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
use std::collections::HashMap;
18+
19+
use hyperlight_common::mem::PAGE_SIZE_USIZE;
20+
21+
/// A compact snapshot representation that stores pages in a contiguous buffer
22+
/// with an index for efficient lookup.
23+
///
24+
/// This struct is designed to efficiently store and retrieve memory snapshots
25+
/// by using a contiguous buffer for all page data combined with a HashMap index
26+
/// for page lookups. This approach reduces memory overhead
27+
/// compared to storing pages individually.
28+
///
29+
/// # Clone Derivation
30+
///
31+
/// This struct derives `Clone` because it's stored in `Vec<PageSnapshot>` within
32+
/// `SharedMemorySnapshotManager`, which itself derives `Clone`.
33+
#[derive(Clone)]
34+
pub(super) struct PageSnapshot {
35+
/// Maps page numbers to their offset within the buffer (in page units)
36+
page_index: HashMap<usize, usize>, // page_number -> buffer_offset_in_pages
37+
/// Contiguous buffer containing all the page data
38+
buffer: Vec<u8>,
39+
}
40+
41+
impl PageSnapshot {
42+
/// Create a new empty snapshot
43+
pub(super) fn new() -> Self {
44+
Self {
45+
page_index: HashMap::new(),
46+
buffer: Vec::new(),
47+
}
48+
}
49+
50+
/// Create a snapshot from a list of page numbers with pre-allocated buffer
51+
pub(super) fn with_pages_and_buffer(page_numbers: Vec<usize>, buffer: Vec<u8>) -> Self {
52+
let page_count = page_numbers.len();
53+
let mut page_index = HashMap::with_capacity(page_count);
54+
55+
// Map each page number to its offset in the buffer
56+
for (buffer_offset, page_num) in page_numbers.into_iter().enumerate() {
57+
page_index.insert(page_num, buffer_offset);
58+
}
59+
60+
Self { page_index, buffer }
61+
}
62+
63+
/// Get page data by page number, returns None if page is not in snapshot
64+
pub(super) fn get_page(&self, page_num: usize) -> Option<&[u8]> {
65+
self.page_index.get(&page_num).map(|&buffer_offset| {
66+
let start = buffer_offset * PAGE_SIZE_USIZE;
67+
let end = start + PAGE_SIZE_USIZE;
68+
&self.buffer[start..end]
69+
})
70+
}
71+
72+
/// Get an iterator over all page numbers in this snapshot
73+
pub(super) fn page_numbers(&self) -> impl Iterator<Item = usize> + '_ {
74+
self.page_index.keys().copied()
75+
}
76+
77+
/// Get the maximum page number in this snapshot, or None if empty
78+
pub(super) fn max_page(&self) -> Option<usize> {
79+
self.page_index.keys().max().copied()
80+
}
81+
}

0 commit comments

Comments
 (0)