style: apply rustfmt across bench and core crates
CI / ci (ubuntu-latest) (push) Has been cancelled
CI / ci (windows-latest) (push) Has been cancelled
CI / ci (ubuntu-latest) (push) Has been cancelled
CI / ci (windows-latest) (push) Has been cancelled
Pure formatting pass - no semantic changes. Mostly long-line reflow,
import statement reordering (alphabetical), and trailing-newline fixes
that had been accumulating in the working tree.
Affected files:
* crates/bench/src/{data_gen,main,mmap_reader,pread_reader,report,runner}.rs
* crates/bench/src/suites/{concurrent,growth,jump,memory,render,rotation,startup}.rs
* crates/core/src/io/{file_reader,index_cache,read_cache}.rs
* crates/core/src/{types.rs, watcher/file_watcher.rs}
This commit is contained in:
@@ -84,10 +84,8 @@ pub fn generate_growable_file(dir: &Path) -> std::io::Result<PathBuf> {
|
|||||||
/// Append `count` lines to the file
|
/// Append `count` lines to the file
|
||||||
pub fn append_lines(path: &Path, count: usize) -> std::io::Result<()> {
|
pub fn append_lines(path: &Path, count: usize) -> std::io::Result<()> {
|
||||||
let existing_lines = count_existing_lines(path)?;
|
let existing_lines = count_existing_lines(path)?;
|
||||||
let mut file = BufWriter::with_capacity(
|
let mut file =
|
||||||
64 * 1024,
|
BufWriter::with_capacity(64 * 1024, fs::OpenOptions::new().append(true).open(path)?);
|
||||||
fs::OpenOptions::new().append(true).open(path)?,
|
|
||||||
);
|
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
writeln!(
|
writeln!(
|
||||||
file,
|
file,
|
||||||
|
|||||||
@@ -27,8 +27,10 @@ fn main() {
|
|||||||
|
|
||||||
let suites = match args.suites {
|
let suites = match args.suites {
|
||||||
Some(names) => {
|
Some(names) => {
|
||||||
let parsed: Result<Vec<_>, _> =
|
let parsed: Result<Vec<_>, _> = names
|
||||||
names.iter().map(|s| s.parse::<log_viewer_bench::runner::Suite>()).collect();
|
.iter()
|
||||||
|
.map(|s| s.parse::<log_viewer_bench::runner::Suite>())
|
||||||
|
.collect();
|
||||||
match parsed {
|
match parsed {
|
||||||
Ok(s) => Some(s),
|
Ok(s) => Some(s),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicU8, Ordering};
|
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicU8, Ordering};
|
||||||
|
|
||||||
use memmap2::{Advice, Mmap, MmapOptions, RemapOptions};
|
use memmap2::{Advice, Mmap, MmapOptions, RemapOptions};
|
||||||
use nix::sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal};
|
use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction};
|
||||||
|
|
||||||
use crate::line_index::LineIndex;
|
|
||||||
use crate::FileReaderBackend;
|
use crate::FileReaderBackend;
|
||||||
|
use crate::line_index::LineIndex;
|
||||||
|
|
||||||
// ─── SIGBUS Handler ──────────────────────────────────────────────────────────
|
// ─── SIGBUS Handler ──────────────────────────────────────────────────────────
|
||||||
//
|
//
|
||||||
@@ -35,7 +35,10 @@ const HANDLER_NONE: u8 = 0;
|
|||||||
const HANDLER_DEFAULT: u8 = 1;
|
const HANDLER_DEFAULT: u8 = 1;
|
||||||
const HANDLER_IGNORE: u8 = 2;
|
const HANDLER_IGNORE: u8 = 2;
|
||||||
const HANDLER_PLAIN: u8 = 3; // extern "C" fn(c_int)
|
const HANDLER_PLAIN: u8 = 3; // extern "C" fn(c_int)
|
||||||
#[allow(clippy::unseparated_literal_suffix, reason = "clarity: this is the SA_SIGACTION variant")]
|
#[allow(
|
||||||
|
clippy::unseparated_literal_suffix,
|
||||||
|
reason = "clarity: this is the SA_SIGACTION variant"
|
||||||
|
)]
|
||||||
const HANDLER_SIGACTION: u8 = 4; // extern "C" fn(c_int, *mut siginfo_t, *mut c_void)
|
const HANDLER_SIGACTION: u8 = 4; // extern "C" fn(c_int, *mut siginfo_t, *mut c_void)
|
||||||
|
|
||||||
/// Old SIGBUS handler type — raw atomic, async-signal-safe to read.
|
/// Old SIGBUS handler type — raw atomic, async-signal-safe to read.
|
||||||
@@ -107,11 +110,8 @@ extern "C" fn sigbus_handler(
|
|||||||
HANDLER_SIGACTION => {
|
HANDLER_SIGACTION => {
|
||||||
let ptr = OLD_HANDLER_PTR.load(Ordering::Acquire);
|
let ptr = OLD_HANDLER_PTR.load(Ordering::Acquire);
|
||||||
if !ptr.is_null() {
|
if !ptr.is_null() {
|
||||||
let f: extern "C" fn(
|
let f: extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut std::ffi::c_void) =
|
||||||
libc::c_int,
|
unsafe { std::mem::transmute(ptr) };
|
||||||
*mut libc::siginfo_t,
|
|
||||||
*mut std::ffi::c_void,
|
|
||||||
) = unsafe { std::mem::transmute(ptr) };
|
|
||||||
f(sig, info, ctx);
|
f(sig, info, ctx);
|
||||||
} else {
|
} else {
|
||||||
unsafe { libc::_exit(128 + sig) };
|
unsafe { libc::_exit(128 + sig) };
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ use std::os::unix::fs::FileExt;
|
|||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::line_index::LineIndex;
|
|
||||||
use crate::FileReaderBackend;
|
use crate::FileReaderBackend;
|
||||||
|
use crate::line_index::LineIndex;
|
||||||
|
|
||||||
const BLOCK_SIZE: usize = 256;
|
const BLOCK_SIZE: usize = 256;
|
||||||
const CACHE_CHUNK: usize = 4096;
|
const CACHE_CHUNK: usize = 4096;
|
||||||
@@ -478,12 +478,19 @@ mod tests {
|
|||||||
let mut reader = PreadReaderPlain::open(&path).unwrap();
|
let mut reader = PreadReaderPlain::open(&path).unwrap();
|
||||||
assert_eq!(reader.total_lines(), 3);
|
assert_eq!(reader.total_lines(), 3);
|
||||||
assert_eq!(reader.get_line(0), Some("alpha".to_owned()));
|
assert_eq!(reader.get_line(0), Some("alpha".to_owned()));
|
||||||
assert_eq!(reader.get_line(3), None, "should be out of bounds before append");
|
assert_eq!(
|
||||||
|
reader.get_line(3),
|
||||||
|
None,
|
||||||
|
"should be out of bounds before append"
|
||||||
|
);
|
||||||
|
|
||||||
// Phase 2: append 2 more lines
|
// Phase 2: append 2 more lines
|
||||||
{
|
{
|
||||||
use std::io::Write as _;
|
use std::io::Write as _;
|
||||||
let mut f = std::fs::OpenOptions::new().append(true).open(&path).unwrap();
|
let mut f = std::fs::OpenOptions::new()
|
||||||
|
.append(true)
|
||||||
|
.open(&path)
|
||||||
|
.unwrap();
|
||||||
f.write_all(b"delta\nepsilon\n").unwrap();
|
f.write_all(b"delta\nepsilon\n").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,8 +145,7 @@ pub fn format_report(results: &[BenchmarkResult]) -> String {
|
|||||||
|
|
||||||
let mut mem_rows: Vec<&BenchmarkResult> = category_results.to_vec();
|
let mut mem_rows: Vec<&BenchmarkResult> = category_results.to_vec();
|
||||||
mem_rows.sort_by(|a, b| {
|
mem_rows.sort_by(|a, b| {
|
||||||
(&a.test_name, &a.backend, &a.variant)
|
(&a.test_name, &a.backend, &a.variant).cmp(&(&b.test_name, &b.backend, &b.variant))
|
||||||
.cmp(&(&b.test_name, &b.backend, &b.variant))
|
|
||||||
});
|
});
|
||||||
for r in mem_rows {
|
for r in mem_rows {
|
||||||
let variant_label = format!("{} ({})", r.backend, r.variant);
|
let variant_label = format!("{} ({})", r.backend, r.variant);
|
||||||
@@ -243,21 +242,60 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn report_ordering_independent_of_input_order() {
|
fn report_ordering_independent_of_input_order() {
|
||||||
let set_a = vec![
|
let set_a = vec![
|
||||||
make_result("sequential", "read_1mb", "pread", "default", vec![100, 110, 105]),
|
make_result(
|
||||||
make_result("sequential", "read_1mb", "mmap", "default", vec![80, 85, 90]),
|
"sequential",
|
||||||
make_result("sequential", "read_4kb", "pread", "default", vec![10, 12, 11]),
|
"read_1mb",
|
||||||
|
"pread",
|
||||||
|
"default",
|
||||||
|
vec![100, 110, 105],
|
||||||
|
),
|
||||||
|
make_result(
|
||||||
|
"sequential",
|
||||||
|
"read_1mb",
|
||||||
|
"mmap",
|
||||||
|
"default",
|
||||||
|
vec![80, 85, 90],
|
||||||
|
),
|
||||||
|
make_result(
|
||||||
|
"sequential",
|
||||||
|
"read_4kb",
|
||||||
|
"pread",
|
||||||
|
"default",
|
||||||
|
vec![10, 12, 11],
|
||||||
|
),
|
||||||
make_result("sequential", "read_4kb", "mmap", "default", vec![8, 9, 7]),
|
make_result("sequential", "read_4kb", "mmap", "default", vec![8, 9, 7]),
|
||||||
];
|
];
|
||||||
|
|
||||||
let set_b = vec![
|
let set_b = vec![
|
||||||
make_result("sequential", "read_4kb", "mmap", "default", vec![8, 9, 7]),
|
make_result("sequential", "read_4kb", "mmap", "default", vec![8, 9, 7]),
|
||||||
make_result("sequential", "read_1mb", "mmap", "default", vec![80, 85, 90]),
|
make_result(
|
||||||
make_result("sequential", "read_4kb", "pread", "default", vec![10, 12, 11]),
|
"sequential",
|
||||||
make_result("sequential", "read_1mb", "pread", "default", vec![100, 110, 105]),
|
"read_1mb",
|
||||||
|
"mmap",
|
||||||
|
"default",
|
||||||
|
vec![80, 85, 90],
|
||||||
|
),
|
||||||
|
make_result(
|
||||||
|
"sequential",
|
||||||
|
"read_4kb",
|
||||||
|
"pread",
|
||||||
|
"default",
|
||||||
|
vec![10, 12, 11],
|
||||||
|
),
|
||||||
|
make_result(
|
||||||
|
"sequential",
|
||||||
|
"read_1mb",
|
||||||
|
"pread",
|
||||||
|
"default",
|
||||||
|
vec![100, 110, 105],
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
let report_a = format_report(&set_a);
|
let report_a = format_report(&set_a);
|
||||||
let report_b = format_report(&set_b);
|
let report_b = format_report(&set_b);
|
||||||
assert_eq!(report_a, report_b, "Reports must be identical regardless of input order");
|
assert_eq!(
|
||||||
|
report_a, report_b,
|
||||||
|
"Reports must be identical regardless of input order"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,7 +154,11 @@ mod tests {
|
|||||||
("concurrent", Suite::Concurrent),
|
("concurrent", Suite::Concurrent),
|
||||||
];
|
];
|
||||||
for (s, expected_suite) in expected {
|
for (s, expected_suite) in expected {
|
||||||
assert_eq!(Suite::from_str(s).unwrap(), expected_suite, "failed to parse '{s}'");
|
assert_eq!(
|
||||||
|
Suite::from_str(s).unwrap(),
|
||||||
|
expected_suite,
|
||||||
|
"failed to parse '{s}'"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::FileReaderBackend;
|
||||||
use crate::metrics::MetricsCollector;
|
use crate::metrics::MetricsCollector;
|
||||||
use crate::mmap_reader::{
|
use crate::mmap_reader::{
|
||||||
MmapReaderPhaseAware, MmapReaderPlain, MmapReaderPopulate, MmapReaderRandom,
|
MmapReaderPhaseAware, MmapReaderPlain, MmapReaderPopulate, MmapReaderRandom,
|
||||||
@@ -8,7 +9,6 @@ use crate::mmap_reader::{
|
|||||||
use crate::pread_reader::{PreadReaderPlain, PreadReaderRandom, PreadReaderSequential};
|
use crate::pread_reader::{PreadReaderPlain, PreadReaderRandom, PreadReaderSequential};
|
||||||
use crate::runner::BenchConfig;
|
use crate::runner::BenchConfig;
|
||||||
use crate::types::BenchmarkResult;
|
use crate::types::BenchmarkResult;
|
||||||
use crate::FileReaderBackend;
|
|
||||||
|
|
||||||
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::FileReaderBackend;
|
||||||
use crate::data_gen;
|
use crate::data_gen;
|
||||||
use crate::metrics::MetricsCollector;
|
use crate::metrics::MetricsCollector;
|
||||||
use crate::mmap_reader::MmapReaderPlain;
|
use crate::mmap_reader::MmapReaderPlain;
|
||||||
use crate::pread_reader::PreadReaderPlain;
|
use crate::pread_reader::PreadReaderPlain;
|
||||||
use crate::runner::BenchConfig;
|
use crate::runner::BenchConfig;
|
||||||
use crate::types::BenchmarkResult;
|
use crate::types::BenchmarkResult;
|
||||||
use crate::FileReaderBackend;
|
|
||||||
|
|
||||||
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use super::FRAME_LINES;
|
use super::FRAME_LINES;
|
||||||
|
use crate::FileReaderBackend;
|
||||||
use crate::metrics::MetricsCollector;
|
use crate::metrics::MetricsCollector;
|
||||||
use crate::mmap_reader::{
|
use crate::mmap_reader::{
|
||||||
MmapReaderPhaseAware, MmapReaderPlain, MmapReaderPopulate, MmapReaderRandom,
|
MmapReaderPhaseAware, MmapReaderPlain, MmapReaderPopulate, MmapReaderRandom,
|
||||||
@@ -9,7 +10,6 @@ use crate::mmap_reader::{
|
|||||||
use crate::pread_reader::{PreadReaderPlain, PreadReaderRandom, PreadReaderSequential};
|
use crate::pread_reader::{PreadReaderPlain, PreadReaderRandom, PreadReaderSequential};
|
||||||
use crate::runner::BenchConfig;
|
use crate::runner::BenchConfig;
|
||||||
use crate::types::BenchmarkResult;
|
use crate::types::BenchmarkResult;
|
||||||
use crate::FileReaderBackend;
|
|
||||||
|
|
||||||
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::FileReaderBackend;
|
||||||
use crate::metrics::MetricsCollector;
|
use crate::metrics::MetricsCollector;
|
||||||
use crate::mmap_reader::{
|
use crate::mmap_reader::{
|
||||||
MmapReaderPhaseAware, MmapReaderPlain, MmapReaderPopulate, MmapReaderRandom,
|
MmapReaderPhaseAware, MmapReaderPlain, MmapReaderPopulate, MmapReaderRandom,
|
||||||
@@ -8,7 +9,6 @@ use crate::mmap_reader::{
|
|||||||
use crate::pread_reader::{PreadReaderPlain, PreadReaderRandom, PreadReaderSequential};
|
use crate::pread_reader::{PreadReaderPlain, PreadReaderRandom, PreadReaderSequential};
|
||||||
use crate::runner::BenchConfig;
|
use crate::runner::BenchConfig;
|
||||||
use crate::types::BenchmarkResult;
|
use crate::types::BenchmarkResult;
|
||||||
use crate::FileReaderBackend;
|
|
||||||
|
|
||||||
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use super::FRAME_LINES;
|
use super::FRAME_LINES;
|
||||||
|
use crate::FileReaderBackend;
|
||||||
use crate::metrics::MetricsCollector;
|
use crate::metrics::MetricsCollector;
|
||||||
use crate::mmap_reader::{
|
use crate::mmap_reader::{
|
||||||
MmapReaderPhaseAware, MmapReaderPlain, MmapReaderPopulate, MmapReaderRandom,
|
MmapReaderPhaseAware, MmapReaderPlain, MmapReaderPopulate, MmapReaderRandom,
|
||||||
@@ -9,7 +10,6 @@ use crate::mmap_reader::{
|
|||||||
use crate::pread_reader::{PreadReaderPlain, PreadReaderRandom, PreadReaderSequential};
|
use crate::pread_reader::{PreadReaderPlain, PreadReaderRandom, PreadReaderSequential};
|
||||||
use crate::runner::BenchConfig;
|
use crate::runner::BenchConfig;
|
||||||
use crate::types::BenchmarkResult;
|
use crate::types::BenchmarkResult;
|
||||||
use crate::FileReaderBackend;
|
|
||||||
|
|
||||||
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
@@ -248,7 +248,11 @@ mod tests {
|
|||||||
assert!(
|
assert!(
|
||||||
!ranges_overlap(pos[i].1, pos[j].1),
|
!ranges_overlap(pos[i].1, pos[j].1),
|
||||||
"overlap: {:?} @ {} vs {:?} @ {} (total={})",
|
"overlap: {:?} @ {} vs {:?} @ {} (total={})",
|
||||||
pos[i].0, pos[i].1, pos[j].0, pos[j].1, total
|
pos[i].0,
|
||||||
|
pos[i].1,
|
||||||
|
pos[j].0,
|
||||||
|
pos[j].1,
|
||||||
|
total
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,7 +273,10 @@ mod tests {
|
|||||||
assert!(
|
assert!(
|
||||||
!ranges_overlap(pos[i].1, pos[j].1),
|
!ranges_overlap(pos[i].1, pos[j].1),
|
||||||
"overlap at total=104: {:?} @ {} vs {:?} @ {}",
|
"overlap at total=104: {:?} @ {} vs {:?} @ {}",
|
||||||
pos[i].0, pos[i].1, pos[j].0, pos[j].1
|
pos[i].0,
|
||||||
|
pos[i].1,
|
||||||
|
pos[j].0,
|
||||||
|
pos[j].1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,7 +290,10 @@ mod tests {
|
|||||||
assert!(
|
assert!(
|
||||||
!ranges_overlap(pos[i].1, pos[j].1),
|
!ranges_overlap(pos[i].1, pos[j].1),
|
||||||
"overlap at total=105: {:?} @ {} vs {:?} @ {}",
|
"overlap at total=105: {:?} @ {} vs {:?} @ {}",
|
||||||
pos[i].0, pos[i].1, pos[j].0, pos[j].1
|
pos[i].0,
|
||||||
|
pos[i].1,
|
||||||
|
pos[j].0,
|
||||||
|
pos[j].1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::FileReaderBackend;
|
||||||
use crate::data_gen;
|
use crate::data_gen;
|
||||||
use crate::metrics::MetricsCollector;
|
use crate::metrics::MetricsCollector;
|
||||||
use crate::mmap_reader::{self, MmapReaderPlain};
|
use crate::mmap_reader::{self, MmapReaderPlain};
|
||||||
use crate::pread_reader::PreadReaderPlain;
|
use crate::pread_reader::PreadReaderPlain;
|
||||||
use crate::runner::BenchConfig;
|
use crate::runner::BenchConfig;
|
||||||
use crate::types::BenchmarkResult;
|
use crate::types::BenchmarkResult;
|
||||||
use crate::FileReaderBackend;
|
|
||||||
|
|
||||||
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use crate::FileReaderBackend;
|
||||||
use crate::metrics::MetricsCollector;
|
use crate::metrics::MetricsCollector;
|
||||||
use crate::mmap_reader::{
|
use crate::mmap_reader::{
|
||||||
MmapReaderPhaseAware, MmapReaderPlain, MmapReaderPopulate, MmapReaderRandom,
|
MmapReaderPhaseAware, MmapReaderPlain, MmapReaderPopulate, MmapReaderRandom,
|
||||||
@@ -9,7 +10,6 @@ use crate::mmap_reader::{
|
|||||||
use crate::pread_reader::{PreadReaderPlain, PreadReaderRandom, PreadReaderSequential};
|
use crate::pread_reader::{PreadReaderPlain, PreadReaderRandom, PreadReaderSequential};
|
||||||
use crate::runner::BenchConfig;
|
use crate::runner::BenchConfig;
|
||||||
use crate::types::BenchmarkResult;
|
use crate::types::BenchmarkResult;
|
||||||
use crate::FileReaderBackend;
|
|
||||||
|
|
||||||
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
pub fn run(config: &BenchConfig) -> Vec<BenchmarkResult> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ impl FileReader {
|
|||||||
} else {
|
} else {
|
||||||
// SAFETY: 使用只读 Mmap(非 MmapMut),文件以只读方式打开。
|
// SAFETY: 使用只读 Mmap(非 MmapMut),文件以只读方式打开。
|
||||||
// memmap2 内部持有文件描述符,确保 mmap 期间文件不会被关闭。
|
// memmap2 内部持有文件描述符,确保 mmap 期间文件不会被关闭。
|
||||||
let m = unsafe { memmap2::Mmap::map(&file) }
|
let m =
|
||||||
.map_err(|e| CoreError::Mmap(e.to_string()))?;
|
unsafe { memmap2::Mmap::map(&file) }.map_err(|e| CoreError::Mmap(e.to_string()))?;
|
||||||
|
|
||||||
// Layer 3: mmap 后立即 stat 同一 fd,检测截断(TOCTOU 缓解,非安全证明)
|
// Layer 3: mmap 后立即 stat 同一 fd,检测截断(TOCTOU 缓解,非安全证明)
|
||||||
let current_size = file.metadata()?.len();
|
let current_size = file.metadata()?.len();
|
||||||
@@ -507,7 +507,11 @@ mod tests {
|
|||||||
reader.reload().unwrap();
|
reader.reload().unwrap();
|
||||||
assert_eq!(reader.line_count(), 1);
|
assert_eq!(reader.line_count(), 1);
|
||||||
assert_eq!(reader.get_line(0), Some("new"));
|
assert_eq!(reader.get_line(0), Some("new"));
|
||||||
assert_eq!(reader.get_line(1), None, "old line should not be accessible");
|
assert_eq!(
|
||||||
|
reader.get_line(1),
|
||||||
|
None,
|
||||||
|
"old line should not be accessible"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::io::{Read as _, Write as _};
|
use std::io::{Read as _, Write as _};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::io::cache_util::{cache_path, CACHE_VERSION};
|
use crate::io::cache_util::{CACHE_VERSION, cache_path};
|
||||||
use crate::io::line_index::LineIndex;
|
use crate::io::line_index::LineIndex;
|
||||||
|
|
||||||
pub struct IndexCache;
|
pub struct IndexCache;
|
||||||
@@ -47,11 +47,7 @@ impl IndexCache {
|
|||||||
///
|
///
|
||||||
/// The file hash is derived from `data` (the same byte slice used to build the index),
|
/// The file hash is derived from `data` (the same byte slice used to build the index),
|
||||||
/// avoiding TOCTOU issues from re-reading the file from disk.
|
/// avoiding TOCTOU issues from re-reading the file from disk.
|
||||||
pub fn save_with_hash(
|
pub fn save_with_hash(file_path: &Path, index: &LineIndex, data: &[u8]) -> std::io::Result<()> {
|
||||||
file_path: &Path,
|
|
||||||
index: &LineIndex,
|
|
||||||
data: &[u8],
|
|
||||||
) -> std::io::Result<()> {
|
|
||||||
let dest = cache_path(file_path).ok_or_else(|| {
|
let dest = cache_path(file_path).ok_or_else(|| {
|
||||||
std::io::Error::new(std::io::ErrorKind::NotFound, "cannot determine cache path")
|
std::io::Error::new(std::io::ErrorKind::NotFound, "cannot determine cache path")
|
||||||
})?;
|
})?;
|
||||||
@@ -382,6 +378,10 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let final_data = std::fs::read(&dest).expect("dest file should exist");
|
let final_data = std::fs::read(&dest).expect("dest file should exist");
|
||||||
assert_eq!(final_data.len(), 64 * 1024, "final file must be exactly one payload");
|
assert_eq!(
|
||||||
|
final_data.len(),
|
||||||
|
64 * 1024,
|
||||||
|
"final file must be exactly one payload"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -492,4 +492,4 @@ mod tests {
|
|||||||
let err = cache.get(&file, u64::MAX, 1).unwrap_err();
|
let err = cache.get(&file, u64::MAX, 1).unwrap_err();
|
||||||
assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
|
assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -324,10 +324,7 @@ mod tests {
|
|||||||
Ok(LogLevel::Unknown("CUSTOM".into()))
|
Ok(LogLevel::Unknown("CUSTOM".into()))
|
||||||
);
|
);
|
||||||
// Pure whitespace becomes Unknown("").
|
// Pure whitespace becomes Unknown("").
|
||||||
assert_eq!(
|
assert_eq!(" ".parse::<LogLevel>(), Ok(LogLevel::Unknown("".into())));
|
||||||
" ".parse::<LogLevel>(),
|
|
||||||
Ok(LogLevel::Unknown("".into()))
|
|
||||||
);
|
|
||||||
// Internal whitespace is NOT collapsed.
|
// Internal whitespace is NOT collapsed.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"W ARN".parse::<LogLevel>(),
|
"W ARN".parse::<LogLevel>(),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crossbeam_channel::{bounded, Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender, bounded};
|
||||||
use notify::{Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
|
use notify::{Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
|
|||||||
Reference in New Issue
Block a user