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 { fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents {
if let Some(device) = self.node.read().inner.as_device() { if !self.typ.is_device() {
device.poll(mask, poller) // Fast path: bypassing the read lock on `self.node`
} else { // results in a 5x speed improvement for lmbench-select-file.
let events = IoEvents::IN | IoEvents::OUT; return (IoEvents::IN | IoEvents::OUT) & mask;
events & 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> { fn fs(&self) -> Arc<dyn FileSystem> {

View File

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

View File

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

View File

@ -102,7 +102,7 @@ fn do_select(
) -> Result<usize> { ) -> Result<usize> {
// Convert the FdSet to an array of PollFd // Convert the FdSet to an array of PollFd
let poll_fds = { let poll_fds = {
let mut poll_fds = Vec::new(); let mut poll_fds = Vec::with_capacity(nfds as usize);
for fd in 0..nfds { for fd in 0..nfds {
let events = { let events = {
let readable = readfds.as_ref().map_or(false, |fds| fds.is_set(fd)); 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. /// Return `None` if `idx` is out of bounds or the item is not exist.
pub fn get(&self, idx: usize) -> Option<&T> { pub fn get(&self, idx: usize) -> Option<&T> {
if idx >= self.slots.len() { self.slots.get(idx)?.as_ref()
return None;
}
self.slots[idx].as_ref()
} }
/// Put an item into the vector. /// Put an item into the vector.