summary refs log tree commit diff
path: root/ripple/fossil
diff options
context:
space:
mode:
authoredef <edef@unfathomable.blue>2022-05-02 01:23:08 +0000
committeredef <edef@unfathomable.blue>2022-05-02 01:23:08 +0000
commitb27d8f87d4689aea63834b59629cccee1410b859 (patch)
tree0d9012f4f4f64beb3e21af8e8f05ffcff484ee34 /ripple/fossil
parentb3366c335d978b1485c83784a350c17c0d02d9a3 (diff)
ripple/fossil/chunker: eliminate indexing and bounds checks
This improves performance by ~12%.

Change-Id: I5612b624da77b138fcfb44cbb439b0106580ed70
Diffstat (limited to 'ripple/fossil')
-rw-r--r--ripple/fossil/src/chunker/mod.rs33
1 files changed, 22 insertions, 11 deletions
diff --git a/ripple/fossil/src/chunker/mod.rs b/ripple/fossil/src/chunker/mod.rs
index 8dcf796..9172a15 100644
--- a/ripple/fossil/src/chunker/mod.rs
+++ b/ripple/fossil/src/chunker/mod.rs
@@ -38,27 +38,38 @@ impl<'a> Iterator for Chunker<'a> {
 			return Some(mem::take(&mut self.buffer));
 		}
 
-		let bytes = self
-			.buffer
-			.iter()
-			.cloned()
-			.enumerate()
-			.take(MAX_CHUNK_SIZE)
-			.skip(MIN_CHUNK_SIZE);
+		let bytes = self.buffer.iter().take(MAX_CHUNK_SIZE).skip(MIN_CHUNK_SIZE);
 
 		let mut hasher = buz::Rolling::<WINDOW_SIZE>::from_slice(&self.buffer[..MIN_CHUNK_SIZE]);
 		let chunk;
-		for (idx, byte) in bytes {
+		for byte in bytes {
 			let buz::Hash(x) = hasher.sum();
 			if x % DISCRIMINATOR == DISCRIMINATOR.wrapping_sub(1) {
 				// split point
-				(chunk, self.buffer) = self.buffer.split_at(idx);
+				(chunk, self.buffer) = unsafe {
+					// SAFETY: `byte` is in bounds of `self.buffer`, so
+					// computing `idx` is safe, and `idx` is in bounds
+					let origin = self.buffer.as_ptr();
+					let ptr = byte as *const u8;
+					let idx = ptr.offset_from(origin) as usize;
+					(
+						self.buffer.get_unchecked(..idx),
+						self.buffer.get_unchecked(idx..),
+					)
+				};
 				return Some(chunk);
 			}
-			hasher.push(byte);
+			hasher.push(*byte);
 		}
 
-		(chunk, self.buffer) = self.buffer.split_at(MAX_CHUNK_SIZE.min(self.buffer.len()));
+		(chunk, self.buffer) = unsafe {
+			// SAFETY: `mid` is clamped to `self.buffer.len()`
+			let mid = MAX_CHUNK_SIZE.min(self.buffer.len());
+			(
+				self.buffer.get_unchecked(..mid),
+				self.buffer.get_unchecked(mid..),
+			)
+		};
 		Some(chunk)
 	}