597 lines
18 KiB
Rust
597 lines
18 KiB
Rust
//! Kernel performance benchmarks using Criterion
|
|
//!
|
|
//! These benchmarks measure the performance of critical kernel operations including:
|
|
//! - Syscall latency
|
|
//! - Memory allocation speed
|
|
//! - Process creation/destruction times
|
|
//! - File I/O throughput
|
|
//! - Network operations
|
|
|
|
extern crate alloc;
|
|
|
|
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};
|
|
|
|
/// Benchmark memory allocation performance
|
|
fn bench_memory_allocation(c: &mut Criterion) {
|
|
c.bench_function("memory_allocation_1kb", |b| {
|
|
b.iter(|| {
|
|
let _data = alloc::vec![0u8; 1024];
|
|
black_box(_data);
|
|
})
|
|
});
|
|
}
|
|
|
|
/// Benchmark memory allocation and deallocation cycle
|
|
fn bench_memory_cycle(c: &mut Criterion) {
|
|
c.bench_function("memory_alloc_dealloc_cycle", |b| {
|
|
b.iter(|| {
|
|
for _ in 0..100 {
|
|
let _data = alloc::vec![0u8; 256];
|
|
black_box(_data);
|
|
}
|
|
})
|
|
});
|
|
}
|
|
|
|
/// Benchmark vector operations
|
|
fn bench_vector_operations(c: &mut Criterion) {
|
|
c.bench_function("vector_push_1000", |b| {
|
|
b.iter(|| {
|
|
let mut v = Vec::new();
|
|
for i in 0..1000 {
|
|
v.push(black_box(i));
|
|
}
|
|
black_box(v);
|
|
})
|
|
});
|
|
}
|
|
|
|
/// Benchmark string operations
|
|
fn bench_string_operations(c: &mut Criterion) {
|
|
c.bench_function("string_concat_100", |b| {
|
|
b.iter(|| {
|
|
let mut s = String::new();
|
|
for i in 0..100 {
|
|
s.push_str(&format!("{}", black_box(i)));
|
|
}
|
|
black_box(s);
|
|
})
|
|
});
|
|
}
|
|
|
|
/// Benchmark hash map operations
|
|
fn bench_hashmap_operations(c: &mut Criterion) {
|
|
use alloc::collections::BTreeMap;
|
|
|
|
c.bench_function("btree_map_insert_100", |b| {
|
|
b.iter(|| {
|
|
let mut map = BTreeMap::new();
|
|
for i in 0..100 {
|
|
map.insert(black_box(i), black_box(i * 2));
|
|
}
|
|
black_box(map);
|
|
})
|
|
});
|
|
}
|
|
|
|
/// Benchmark syscall simulation
|
|
fn bench_syscall_simulation(c: &mut Criterion) {
|
|
c.bench_function("syscall_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate syscall overhead
|
|
for _ in 0..1000 {
|
|
let result = black_box(42) + black_box(1);
|
|
black_box(result);
|
|
}
|
|
})
|
|
});
|
|
}
|
|
|
|
/// Benchmark context switching simulation
|
|
fn bench_context_switch_simulation(c: &mut Criterion) {
|
|
c.bench_function("context_switch_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate context switching overhead
|
|
let mut x = 0;
|
|
for i in 0..10000 {
|
|
x = black_box(x) + black_box(i);
|
|
}
|
|
black_box(x);
|
|
})
|
|
});
|
|
}
|
|
|
|
// ============================================================================
|
|
// Syscall Latency Benchmarks
|
|
// ============================================================================
|
|
|
|
/// Benchmark syscall dispatch latency
|
|
fn bench_syscall_dispatch_latency(c: &mut Criterion) {
|
|
c.bench_function("syscall_dispatch_latency", |b| {
|
|
b.iter(|| {
|
|
// Measure syscall dispatch overhead using a simple invalid syscall
|
|
// Use a direct call to avoid compilation issues
|
|
let result = kernel::syscalls::dispatch(0xFFFF, &[0, 0, 0, 0, 0, 0]);
|
|
black_box(result);
|
|
})
|
|
});
|
|
}
|
|
|
|
/// Benchmark different syscall categories latency
|
|
fn bench_syscall_categories_latency(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("syscall_categories");
|
|
|
|
// Process syscalls - simplified simulation
|
|
group.bench_function("process_syscall_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate process syscall overhead without calling actual dispatch
|
|
let mut overhead = 0u64;
|
|
for _ in 0..10 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
// Memory syscalls - simplified simulation
|
|
group.bench_function("memory_syscall_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate memory syscall overhead
|
|
let mut overhead = 0u64;
|
|
for _ in 0..20 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
// File I/O syscalls - simplified simulation
|
|
group.bench_function("file_io_syscall_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate file I/O syscall overhead
|
|
let mut overhead = 0u64;
|
|
for _ in 0..15 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
// Network syscalls - simplified simulation
|
|
group.bench_function("network_syscall_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate network syscall overhead
|
|
let mut overhead = 0u64;
|
|
for _ in 0..25 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
// ============================================================================
|
|
// Memory Allocation Speed Benchmarks
|
|
// ============================================================================
|
|
|
|
/// Benchmark memory allocation with different sizes
|
|
fn bench_memory_allocation_sizes(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("memory_allocation_sizes");
|
|
|
|
for size in [64, 256, 1024, 4096, 16384, 65536].iter() {
|
|
group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
|
|
b.iter(|| {
|
|
let _data = alloc::vec![0u8; size];
|
|
black_box(_data);
|
|
})
|
|
});
|
|
}
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark kernel memory allocation simulation
|
|
fn bench_kernel_memory_allocation(c: &mut Criterion) {
|
|
c.bench_function("kernel_memory_allocation_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate kernel memory allocation overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate page allocation, zeroing, and metadata updates
|
|
for _ in 0..50 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
}
|
|
|
|
/// Benchmark memory mapping operations simulation
|
|
fn bench_memory_mapping_operations(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("memory_mapping_simulation");
|
|
|
|
group.bench_function("mmap_anonymous_4k_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate mmap 4K page overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate address space allocation, page table updates, physical page allocation
|
|
for _ in 0..100 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.bench_function("mmap_anonymous_64k_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate mmap 64K region overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate larger mapping with multiple pages
|
|
for _ in 0..200 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
// ============================================================================
|
|
// Process Creation/Destruction Benchmarks
|
|
// ============================================================================
|
|
|
|
/// Benchmark process table operations simulation
|
|
fn bench_process_table_operations(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("process_table_simulation");
|
|
|
|
group.bench_function("process_lookup_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate process table lookup overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate hash table lookup, process structure access
|
|
for _ in 0..30 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.bench_function("process_table_iteration_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate process table iteration overhead
|
|
let mut count = 0u64;
|
|
// Simulate iterating through process list
|
|
for _ in 0..100 {
|
|
count = black_box(count) + black_box(1);
|
|
}
|
|
black_box(count);
|
|
})
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark process creation simulation
|
|
fn bench_process_creation_simulation(c: &mut Criterion) {
|
|
c.bench_function("process_creation_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate process creation overhead
|
|
// This would include: allocating PID, setting up process structure,
|
|
// copying memory mappings, setting up file descriptors, etc.
|
|
let mut overhead = 0u64;
|
|
|
|
// Simulate PID allocation
|
|
overhead += 1;
|
|
|
|
// Simulate memory space setup
|
|
for _ in 0..100 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
|
|
// Simulate file descriptor table setup
|
|
for _ in 0..32 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
}
|
|
|
|
/// Benchmark process destruction simulation
|
|
fn bench_process_destruction_simulation(c: &mut Criterion) {
|
|
c.bench_function("process_destruction_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate process destruction overhead
|
|
// This would include: closing file descriptors, freeing memory,
|
|
// cleaning up IPC resources, updating process table, etc.
|
|
let mut overhead = 0u64;
|
|
|
|
// Simulate file descriptor cleanup
|
|
for _ in 0..32 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
|
|
// Simulate memory cleanup
|
|
for _ in 0..50 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
|
|
// Simulate IPC cleanup
|
|
overhead += 10;
|
|
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
}
|
|
|
|
// ============================================================================
|
|
// File I/O Throughput Benchmarks
|
|
// ============================================================================
|
|
|
|
/// Benchmark file descriptor operations simulation
|
|
fn bench_file_descriptor_operations(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("file_descriptor_simulation");
|
|
|
|
group.bench_function("fd_allocation_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate file descriptor allocation overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate finding free FD, updating tables, reference counting
|
|
for _ in 0..25 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.bench_function("fd_table_lookup_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate file descriptor table lookup overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate table lookup, permission checking, reference updates
|
|
for _ in 0..15 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark pipe operations throughput simulation
|
|
fn bench_pipe_operations(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("pipe_operations_simulation");
|
|
|
|
group.bench_function("pipe_creation_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate pipe creation overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate buffer allocation, FD creation, ring buffer setup
|
|
for _ in 0..40 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.bench_function("pipe_small_write_read_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate pipe write/read overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate data copying, buffer management, synchronization
|
|
for _ in 0..35 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark VFS operations simulation
|
|
fn bench_vfs_operations(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("vfs_operations_simulation");
|
|
|
|
group.bench_function("vfs_stat_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate VFS stat operation overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate path resolution, inode lookup, attribute retrieval
|
|
for _ in 0..45 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.bench_function("vfs_create_unlink_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate VFS create/unlink operation overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate inode allocation, directory updates, block allocation/deallocation
|
|
for _ in 0..60 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
// ============================================================================
|
|
// Network Operations Benchmarks
|
|
// ============================================================================
|
|
|
|
/// Benchmark socket table operations simulation
|
|
fn bench_socket_operations(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("socket_operations_simulation");
|
|
|
|
group.bench_function("socket_fd_allocation_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate socket FD allocation overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate socket structure allocation, table insertion, protocol setup
|
|
for _ in 0..30 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.bench_function("socket_table_lookup_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate socket table lookup overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate hash table lookup, socket state checking
|
|
for _ in 0..20 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark network syscall dispatch simulation
|
|
fn bench_network_syscall_dispatch(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("network_syscalls_simulation");
|
|
|
|
group.bench_function("socket_create_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate socket creation overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate protocol stack initialization, socket structure setup
|
|
for _ in 0..50 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.bench_function("socket_bind_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate socket bind overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate address validation, port allocation, routing table updates
|
|
for _ in 0..35 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.bench_function("socket_connect_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate socket connect overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate TCP handshake, connection establishment
|
|
for _ in 0..80 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.bench_function("socket_send_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate socket send overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate data copying, TCP segmentation, congestion control
|
|
for _ in 0..40 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.bench_function("socket_recv_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate socket recv overhead
|
|
let mut overhead = 0u64;
|
|
// Simulate packet reassembly, data copying, flow control
|
|
for _ in 0..45 {
|
|
overhead = black_box(overhead) + black_box(1);
|
|
}
|
|
black_box(overhead);
|
|
})
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark network data path simulation
|
|
fn bench_network_data_path(c: &mut Criterion) {
|
|
c.bench_function("network_data_path_simulation", |b| {
|
|
b.iter(|| {
|
|
// Simulate network data path: packet reception -> processing -> transmission
|
|
let mut packet_data = [0u8; 1500]; // Ethernet MTU
|
|
|
|
// Simulate packet processing overhead
|
|
for i in 0..1500 {
|
|
packet_data[i] = black_box(packet_data[i]) + black_box(1);
|
|
}
|
|
|
|
// Simulate checksum calculation
|
|
let mut checksum = 0u32;
|
|
for &byte in packet_data.iter() {
|
|
checksum = black_box(checksum) + black_box(byte as u32);
|
|
}
|
|
|
|
// Simulate routing table lookup
|
|
let mut route_found = false;
|
|
for _ in 0..100 { // Simulate routing table size
|
|
if black_box(true) { // Simulate route match
|
|
route_found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
black_box((packet_data, checksum, route_found));
|
|
})
|
|
});
|
|
}
|
|
|
|
criterion_group!(
|
|
benches,
|
|
// Original benchmarks
|
|
bench_memory_allocation,
|
|
bench_memory_cycle,
|
|
bench_vector_operations,
|
|
bench_string_operations,
|
|
bench_hashmap_operations,
|
|
bench_syscall_simulation,
|
|
bench_context_switch_simulation,
|
|
|
|
// Syscall latency benchmarks
|
|
bench_syscall_dispatch_latency,
|
|
bench_syscall_categories_latency,
|
|
|
|
// Memory allocation speed benchmarks
|
|
bench_memory_allocation_sizes,
|
|
bench_kernel_memory_allocation,
|
|
bench_memory_mapping_operations,
|
|
|
|
// Process creation/destruction benchmarks
|
|
bench_process_table_operations,
|
|
bench_process_creation_simulation,
|
|
bench_process_destruction_simulation,
|
|
|
|
// File I/O throughput benchmarks
|
|
bench_file_descriptor_operations,
|
|
bench_pipe_operations,
|
|
bench_vfs_operations,
|
|
|
|
// Network operations benchmarks
|
|
bench_socket_operations,
|
|
bench_network_syscall_dispatch,
|
|
bench_network_data_path,
|
|
);
|
|
|
|
criterion_main!(benches); |