Skip to content

Commit eed16ae

Browse files
inteonsunfishcode
authored andcommitted
improve buffer reuse and parameterize SMALL_PATH_BUFFER_SIZE
Signed-off-by: Inteon <[email protected]>
1 parent 25208fc commit eed16ae

File tree

5 files changed

+33
-15
lines changed

5 files changed

+33
-15
lines changed

src/fs/at.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::fs::CloneFlags;
1111
#[cfg(any(linux_raw, all(libc, any(target_os = "android", target_os = "linux"))))]
1212
use crate::fs::RenameFlags;
1313
use crate::io::{self, OwnedFd};
14+
use crate::path::SMALL_PATH_BUFFER_SIZE;
1415
#[cfg(not(target_os = "wasi"))]
1516
use crate::process::{Gid, Uid};
1617
use crate::{imp, path};
@@ -71,7 +72,8 @@ fn _readlinkat(dirfd: BorrowedFd<'_>, path: &ZStr, mut buffer: Vec<u8>) -> io::R
7172
// This code would benefit from having a better way to read into
7273
// uninitialized memory, but that requires `unsafe`.
7374
buffer.clear();
74-
buffer.resize(256, 0_u8);
75+
buffer.reserve(SMALL_PATH_BUFFER_SIZE);
76+
buffer.resize(buffer.capacity(), 0_u8);
7577

7678
loop {
7779
let nread = imp::syscalls::readlinkat(dirfd, path, &mut buffer)?;
@@ -82,7 +84,8 @@ fn _readlinkat(dirfd: BorrowedFd<'_>, path: &ZStr, mut buffer: Vec<u8>) -> io::R
8284
buffer.resize(nread, 0_u8);
8385
return Ok(ZString::new(buffer).unwrap());
8486
}
85-
buffer.resize(buffer.len() * 2, 0_u8);
87+
buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially
88+
buffer.resize(buffer.capacity(), 0_u8);
8689
}
8790
}
8891

src/io/tty.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ use imp::fd::AsFd;
1212
all(linux_raw, feature = "procfs"),
1313
all(libc, not(any(target_os = "fuchsia", target_os = "wasi")))
1414
))]
15-
use {crate::ffi::ZString, alloc::vec::Vec, imp::fd::BorrowedFd};
15+
use {
16+
crate::ffi::ZString, crate::path::SMALL_PATH_BUFFER_SIZE, alloc::vec::Vec, imp::fd::BorrowedFd,
17+
};
1618

1719
/// `isatty(fd)`—Tests whether a file descriptor refers to a terminal.
1820
///
@@ -57,13 +59,17 @@ fn _ttyname(dirfd: BorrowedFd<'_>, mut buffer: Vec<u8>) -> io::Result<ZString> {
5759
// This code would benefit from having a better way to read into
5860
// uninitialized memory, but that requires `unsafe`.
5961
buffer.clear();
60-
buffer.resize(256, 0_u8);
62+
buffer.reserve(SMALL_PATH_BUFFER_SIZE);
63+
buffer.resize(buffer.capacity(), 0_u8);
6164

6265
loop {
6366
match imp::syscalls::ttyname(dirfd, &mut buffer) {
64-
Err(imp::io::Error::RANGE) => buffer.resize(buffer.len() * 2, 0_u8),
67+
Err(imp::io::Error::RANGE) => {
68+
buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially
69+
buffer.resize(buffer.capacity(), 0_u8);
70+
}
6571
Ok(len) => {
66-
buffer.resize(len, 0);
72+
buffer.resize(len, 0_u8);
6773
return Ok(ZString::new(buffer).unwrap());
6874
}
6975
Err(errno) => return Err(errno),

src/path/arg.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::ffi::{ZStr, ZString};
22
use crate::io;
33
#[cfg(feature = "itoa")]
44
use crate::path::DecInt;
5+
use crate::path::SMALL_PATH_BUFFER_SIZE;
56
use alloc::borrow::Cow;
67
use alloc::string::String;
78
use alloc::vec::Vec;
@@ -952,16 +953,17 @@ fn with_z_str<T, F>(bytes: &[u8], f: F) -> io::Result<T>
952953
where
953954
F: FnOnce(&ZStr) -> io::Result<T>,
954955
{
955-
// Most paths are less than this long. The rest can go through the dynamic
956-
// allocation path. If you're opening many files in a directory with a long
957-
// path, consider opening the directory and using openat to open the files
958-
// under it, which will avoid this, and is often faster in the OS as well.
959-
const SIZE: usize = 256;
956+
// Most paths are less than `SMALL_PATH_BUFFER_SIZE` long. The rest can go through
957+
// the dynamic allocation path. If you're opening many files in a directory
958+
// with a long path, consider opening the directory and using `openat` to open
959+
// the files under it, which will avoid this, and is often faster in the OS
960+
// as well.
961+
960962
// Test with >= so that we have room for the trailing NUL.
961-
if bytes.len() >= SIZE {
963+
if bytes.len() >= SMALL_PATH_BUFFER_SIZE {
962964
return with_z_str_slow_path(bytes, f);
963965
}
964-
let mut buffer: [u8; SIZE] = [0_u8; SIZE];
966+
let mut buffer: [u8; SMALL_PATH_BUFFER_SIZE] = [0_u8; SMALL_PATH_BUFFER_SIZE];
965967
// Copy the bytes in; the buffer already has zeros for the trailing NUL.
966968
buffer[..bytes.len()].copy_from_slice(bytes);
967969
f(ZStr::from_bytes_with_nul(&buffer[..=bytes.len()]).map_err(|_cstr_err| io::Error::INVAL)?)

src/path/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ mod dec_int;
77
pub use arg::Arg;
88
#[cfg(feature = "itoa")]
99
pub use dec_int::DecInt;
10+
11+
pub(crate) const SMALL_PATH_BUFFER_SIZE: usize = 256;

src/process/chdir.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::ffi::ZString;
2+
use crate::path::SMALL_PATH_BUFFER_SIZE;
23
use crate::{imp, io, path};
34
use alloc::vec::Vec;
45
#[cfg(not(target_os = "fuchsia"))]
@@ -52,11 +53,15 @@ fn _getcwd(mut buffer: Vec<u8>) -> io::Result<ZString> {
5253
// This code would benefit from having a better way to read into
5354
// uninitialized memory, but that requires `unsafe`.
5455
buffer.clear();
55-
buffer.resize(256, 0_u8);
56+
buffer.reserve(SMALL_PATH_BUFFER_SIZE);
57+
buffer.resize(buffer.capacity(), 0_u8);
5658

5759
loop {
5860
match imp::syscalls::getcwd(&mut buffer) {
59-
Err(imp::io::Error::RANGE) => buffer.resize(buffer.len() * 2, 0_u8),
61+
Err(imp::io::Error::RANGE) => {
62+
buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially
63+
buffer.resize(buffer.capacity(), 0_u8);
64+
}
6065
Ok(_) => {
6166
let len = buffer.iter().position(|x| *x == b'\0').unwrap();
6267
buffer.resize(len, 0_u8);

0 commit comments

Comments
 (0)