Change GuestTracking to use a BTreeSet to remove performance bottleneck (#3112)
Co-authored-by: Your Name <you@example.com>
This commit is contained in:
parent
b67bd1792f
commit
36c748100e
@ -2,7 +2,7 @@
|
|||||||
//! This implementation performs guest memory tracking by use of a simple sorted
|
//! This implementation performs guest memory tracking by use of a simple sorted
|
||||||
//! list residing in the guest's user space. Hence no interaction with the host
|
//! list residing in the guest's user space. Hence no interaction with the host
|
||||||
//! is required.
|
//! is required.
|
||||||
use alloc::vec::Vec;
|
use alloc::collections::BTreeSet;
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
@ -44,7 +44,7 @@ impl Ord for Range {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ranges = Vec<Range>;
|
type Ranges = BTreeSet<Range>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GuestTracking {
|
pub struct GuestTracking {
|
||||||
@ -66,20 +66,8 @@ impl Tracking for GuestTracking {
|
|||||||
|
|
||||||
let item = Range { start, len };
|
let item = Range { start, len };
|
||||||
|
|
||||||
let pos = self.ranges.binary_search(&item);
|
if !self.ranges.insert(item) {
|
||||||
match pos {
|
Err(GuestTrackingError::TrackingConflict(start, len))?;
|
||||||
Ok(pos) => {
|
|
||||||
let conflict = &self.ranges[pos];
|
|
||||||
Err(GuestTrackingError::TrackingConflict(
|
|
||||||
conflict.start,
|
|
||||||
conflict.len,
|
|
||||||
item.start,
|
|
||||||
item.len,
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
Err(pos) => {
|
|
||||||
self.ranges.insert(pos, item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -87,20 +75,20 @@ impl Tracking for GuestTracking {
|
|||||||
|
|
||||||
fn untrack(&mut self, start: GuestAddr) -> Result<(), Self::Error> {
|
fn untrack(&mut self, start: GuestAddr) -> Result<(), Self::Error> {
|
||||||
debug!("dealloc - start: 0x{:x}", start);
|
debug!("dealloc - start: 0x{:x}", start);
|
||||||
let pos = self.ranges.binary_search_by(|item| item.start.cmp(&start));
|
let item = Range { start, len: 1 };
|
||||||
match pos {
|
|
||||||
Ok(pos) => {
|
if !self.ranges.remove(&item) {
|
||||||
self.ranges.remove(pos);
|
Err(GuestTrackingError::AllocationNotFound(start))?;
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Err(_pos) => Err(GuestTrackingError::AllocationNotFound(start)),
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuestTracking {
|
impl GuestTracking {
|
||||||
pub fn new() -> Result<Self, GuestTrackingError> {
|
pub fn new() -> Result<Self, GuestTrackingError> {
|
||||||
Ok(GuestTracking { ranges: Vec::new() })
|
Ok(GuestTracking {
|
||||||
|
ranges: BTreeSet::new(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_out_of_bounds(addr: GuestAddr, len: usize) -> bool {
|
pub fn is_out_of_bounds(addr: GuestAddr, len: usize) -> bool {
|
||||||
@ -118,8 +106,8 @@ pub enum GuestTrackingError {
|
|||||||
AddressRangeOverflow(GuestAddr, usize),
|
AddressRangeOverflow(GuestAddr, usize),
|
||||||
#[error("Allocation not found: {0:x}")]
|
#[error("Allocation not found: {0:x}")]
|
||||||
AllocationNotFound(GuestAddr),
|
AllocationNotFound(GuestAddr),
|
||||||
#[error("Tracking conflict")]
|
#[error("Tracking conflict: {0:x}, len: {1:x}")]
|
||||||
TrackingConflict(GuestAddr, usize, GuestAddr, usize),
|
TrackingConflict(GuestAddr, usize),
|
||||||
#[error("Zero Length")]
|
#[error("Zero Length")]
|
||||||
ZeroLength(GuestAddr),
|
ZeroLength(GuestAddr),
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,7 @@ mod tests {
|
|||||||
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tracking.track(0x1000, 0x1000),
|
tracking.track(0x1000, 0x1000),
|
||||||
Err(GuestTrackingError::TrackingConflict(
|
Err(GuestTrackingError::TrackingConflict(0x1000, 0x1000))
|
||||||
0x1000, 0x1000, 0x1000, 0x1000
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,9 +70,7 @@ mod tests {
|
|||||||
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tracking.track(0x0000, 0x1001),
|
tracking.track(0x0000, 0x1001),
|
||||||
Err(GuestTrackingError::TrackingConflict(
|
Err(GuestTrackingError::TrackingConflict(0x0000, 0x1001))
|
||||||
0x1000, 0x1000, 0x0000, 0x1001
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,9 +80,7 @@ mod tests {
|
|||||||
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
assert_eq!(tracking.track(0x1000, 0x1000), Ok(()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tracking.track(0x1fff, 0x1001),
|
tracking.track(0x1fff, 0x1001),
|
||||||
Err(GuestTrackingError::TrackingConflict(
|
Err(GuestTrackingError::TrackingConflict(0x1fff, 0x1001))
|
||||||
0x1000, 0x1000, 0x1fff, 0x1001
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,8 +94,6 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
tracking.track(0xffffffffb5b60107, 0xdb),
|
tracking.track(0xffffffffb5b60107, 0xdb),
|
||||||
Err(GuestTrackingError::TrackingConflict(
|
Err(GuestTrackingError::TrackingConflict(
|
||||||
0xffffffffb5b5ff21,
|
|
||||||
0x3ff,
|
|
||||||
0xffffffffb5b60107,
|
0xffffffffb5b60107,
|
||||||
0xdb
|
0xdb
|
||||||
))
|
))
|
||||||
|
@ -86,9 +86,7 @@ fuzz_target!(|data: Vec<GuestAddr>| {
|
|||||||
if overlaps {
|
if overlaps {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
test_result,
|
test_result,
|
||||||
Err(GuestTrackingError::TrackingConflict(
|
Err(GuestTrackingError::TrackingConflict(test_start, test_len))
|
||||||
start, len, test_start, test_len
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(test_result, Ok(()));
|
assert_eq!(test_result, Ok(()));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user