From 0ab866d2b337e6ce8e5dda7f5c5eccea98d04305 Mon Sep 17 00:00:00 2001 From: Tom Dohrmann Date: Wed, 18 Mar 2026 07:49:12 +0100 Subject: [PATCH 1/2] merge reads for contiguous clusters Doing many small reads is much slower than doing fewer large reads. Let's try to read several clusters at once if they're contiguous. --- bios/stage-2/src/main.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/bios/stage-2/src/main.rs b/bios/stage-2/src/main.rs index 555b4d55..f3e25a69 100644 --- a/bios/stage-2/src/main.rs +++ b/bios/stage-2/src/main.rs @@ -198,10 +198,17 @@ fn try_load_file( let file_size = file.file_size().into(); let mut total_offset = 0; - for cluster in fs.file_clusters(&file) { - let cluster = cluster.unwrap(); + let mut file_clusters = fs.file_clusters(&file).map(Result::unwrap).peekable(); + while let Some(cluster) = file_clusters.next() { let cluster_start = cluster.start_offset; - let cluster_end = cluster_start + u64::from(cluster.len_bytes); + let mut cluster_end = cluster_start + u64::from(cluster.len_bytes); + + // Merge with the following clusters if they're contiguous. + while let Some(next_cluster) = + file_clusters.next_if(|next_cluster| next_cluster.start_offset == cluster_end) + { + cluster_end += u64::from(next_cluster.len_bytes); + } let mut offset = 0; loop { From 65f5385421b6e887a685a445f68ad278d07810dd Mon Sep 17 00:00:00 2001 From: Tom Dohrmann Date: Wed, 18 Mar 2026 07:51:43 +0100 Subject: [PATCH 2/2] skip reads if the data is already buffered read_exact_at is often called with a bunch of offsets in the same general area. In a lot of cases, the data needed is still in the buffer from the last call. Let's make use of that by remembering the last sector read and skip reading the same sector again. --- bios/stage-2/src/disk.rs | 13 ++++++++++++- bios/stage-2/src/main.rs | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/bios/stage-2/src/disk.rs b/bios/stage-2/src/disk.rs index 06a2e8fa..83ee614d 100644 --- a/bios/stage-2/src/disk.rs +++ b/bios/stage-2/src/disk.rs @@ -5,6 +5,9 @@ pub struct DiskAccess { pub disk_number: u16, pub base_offset: u64, pub current_offset: u64, + + /// The offset of the sector read in the last call to read_exact_at. + pub last_read_exact_at_offset: Option, } impl Read for DiskAccess { @@ -19,7 +22,15 @@ impl Read for DiskAccess { let buf = unsafe { &mut TMP_BUF }; assert!(current_sector_offset + len <= buf.buffer.len()); - self.read_exact_into(buf.buffer.len(), buf); + // Don't read the sector if we already read the same sector in the last + // call. + if self + .last_read_exact_at_offset + .is_none_or(|offset| offset != self.current_offset) + { + self.last_read_exact_at_offset = Some(self.current_offset); + self.read_exact_into(buf.buffer.len(), buf); + } &buf.buffer[current_sector_offset..][..len] } diff --git a/bios/stage-2/src/main.rs b/bios/stage-2/src/main.rs index f3e25a69..41520513 100644 --- a/bios/stage-2/src/main.rs +++ b/bios/stage-2/src/main.rs @@ -83,6 +83,7 @@ fn start(disk_number: u16, partition_table_start: *const u8) -> ! { disk_number, base_offset: u64::from(fat_partition.logical_block_address) * 512, current_offset: 0, + last_read_exact_at_offset: None, }; let mut fs = fat::FileSystem::parse(disk.clone());