Optimize the latency of lmbench-select-file

This commit is contained in:
Jianfeng Jiang 2024-08-15 03:44:30 +00:00 committed by Tate, Hongliang Tian
parent 5b5f9cffd1
commit 0291b5dc6b
5 changed files with 21 additions and 14 deletions

View File

@ -1093,12 +1093,18 @@ impl Inode for RamInode {
}
fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents {
if let Some(device) = self.node.read().inner.as_device() {
device.poll(mask, poller)
} else {
let events = IoEvents::IN | IoEvents::OUT;
events & mask
if !self.typ.is_device() {
// Fast path: bypassing the read lock on `self.node`
// results in a 5x speed improvement for lmbench-select-file.
return (IoEvents::IN | IoEvents::OUT) & mask;
}
let node = self.node.read();
let device = node
.inner
.as_device()
.expect("[Internal error] self.typ is device, while self.node is not");
device.poll(mask, poller)
}
fn fs(&self) -> Arc<dyn FileSystem> {

View File

@ -51,6 +51,10 @@ impl InodeType {
pub fn is_directory(&self) -> bool {
*self == InodeType::Dir
}
pub fn is_device(&self) -> bool {
*self == InodeType::BlockDevice || *self == InodeType::CharDevice
}
}
impl From<DeviceType> for InodeType {

View File

@ -51,6 +51,7 @@ pub fn do_poll(poll_fds: &[PollFd], timeout: Option<Duration>, ctx: &Context) ->
loop {
let mut num_revents = 0;
let file_table = ctx.process.file_table().lock();
for poll_fd in poll_fds {
// Skip poll_fd if it is not given a fd
let fd = match poll_fd.fd() {
@ -59,10 +60,7 @@ pub fn do_poll(poll_fds: &[PollFd], timeout: Option<Duration>, ctx: &Context) ->
};
// Poll the file
let file = {
let file_table = ctx.process.file_table().lock();
file_table.get_file(fd)?.clone()
};
let file = file_table.get_file(fd)?;
let need_poller = if num_revents == 0 {
Some(&mut poller)
} else {
@ -75,6 +73,8 @@ pub fn do_poll(poll_fds: &[PollFd], timeout: Option<Duration>, ctx: &Context) ->
}
}
drop(file_table);
if num_revents > 0 {
return Ok(num_revents);
}

View File

@ -102,7 +102,7 @@ fn do_select(
) -> Result<usize> {
// Convert the FdSet to an array of PollFd
let poll_fds = {
let mut poll_fds = Vec::new();
let mut poll_fds = Vec::with_capacity(nfds as usize);
for fd in 0..nfds {
let events = {
let readable = readfds.as_ref().map_or(false, |fds| fds.is_set(fd));

View File

@ -49,10 +49,7 @@ impl<T> SlotVec<T> {
///
/// Return `None` if `idx` is out of bounds or the item is not exist.
pub fn get(&self, idx: usize) -> Option<&T> {
if idx >= self.slots.len() {
return None;
}
self.slots[idx].as_ref()
self.slots.get(idx)?.as_ref()
}
/// Put an item into the vector.