Skip to content

Commit

Permalink
below: read_all_pids: Use byte iteration for pid walking
Browse files Browse the repository at this point in the history
Summary:
core::str::pattern::CharSearcher::next_match is very expensive (~2.5% CPU
instructions per iteration). This can be made much more efficient by using byte
iteration, and by avoiding having to check whether this is a pid dir twice.

This is more efficient for a few reasons:

1. We do not require a check that the filename is valid UTF-8
2. We do not require allocations (as .to_string_lossy() may)
3. We now avoid doing the work twice

Rudimentary testing with a small pid hierarchy shows around a 0.5% to 1%
reduction in CPU instructions per iteration.

Reviewed By: lnyng

Differential Revision: D58193111

fbshipit-source-id: cba2b6f72995fe38e0ba4e055e884c069392c01e
  • Loading branch information
cdown authored and facebook-github-bot committed Jun 5, 2024
1 parent 04c38fa commit 6341177
Showing 1 changed file with 18 additions and 18 deletions.
36 changes: 18 additions & 18 deletions below/procfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use std::io::BufRead;
use std::io::BufReader;
use std::io::ErrorKind;
use std::io::Read;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::path::PathBuf;
use std::str::FromStr;
Expand Down Expand Up @@ -782,6 +783,19 @@ impl ProcReader {
self.read_pid_exe_path_from_path(self.path.join(pid.to_string()))
}

fn ascii_digits_to_i32(digits: &[u8]) -> Option<i32> {
let mut result = 0i32;
for digit in digits {
let value = digit.wrapping_sub(b'0');
if value <= 9 {
result = result * 10 + value as i32;
} else {
return None;
}
}
Some(result)
}

pub fn read_all_pids(&mut self) -> Result<PidMap> {
let mut pidmap: PidMap = Default::default();
for entry in
Expand All @@ -805,16 +819,10 @@ impl ProcReader {
continue;
}

let mut is_pid = true;
for c in entry.file_name().to_string_lossy().chars() {
if !c.is_ascii_digit() {
is_pid = false;
break;
}
}
if !is_pid {
continue;
}
let pid = match Self::ascii_digits_to_i32(entry.file_name().as_bytes()) {
Some(pid) => pid,
None => continue,
};

let mut pidinfo: PidInfo = Default::default();

Expand Down Expand Up @@ -883,14 +891,6 @@ impl ProcReader {
pidinfo.exe_path = Some(s);
}

let file_name = entry.file_name();
let pid_str = file_name.to_string_lossy();
let pid = pid_str.parse::<i32>().map_err(|_| Error::ParseError {
line: String::new(),
item: pid_str.to_string(),
type_name: "pid".to_string(),
path: self.path.clone(),
})?;
pidmap.insert(pid, pidinfo);
}

Expand Down

0 comments on commit 6341177

Please sign in to comment.