perf: increase buffer size

This commit is contained in:
Tien Do Nam
2026-08-03 18:04:48 +02:00
parent 61b73b3641
commit 1538eccf61
4 changed files with 15 additions and 4 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ use sha2::{Digest, Sha256};
use tokio_util::sync::CancellationToken;
/// Buffer size used when hashing a file chunk by chunk.
const HASH_BUFFER_SIZE: usize = 64 * 1024;
const HASH_BUFFER_SIZE: usize = 512 * 1024;
#[derive(Debug, thiserror::Error)]
pub enum HashError {
+6 -1
View File
@@ -10,6 +10,10 @@ use tokio::sync::{mpsc, oneshot};
/// Channel capacity for file upload chunks (provides backpressure).
const UPLOAD_CHANNEL_CAPACITY: usize = 16;
/// Size of the write buffer that coalesces incoming body chunks (typically one
/// TLS record, ~16 KiB) into larger file writes.
const WRITE_BUFFER_SIZE: usize = 512 * 1024;
/// Where the content of an uploaded file should go, decided by the application.
#[derive(Debug)]
pub enum FileUploadTarget {
@@ -286,7 +290,7 @@ async fn write_file_from_receiver(
) -> Result<(), String> {
use tokio::io::AsyncWriteExt;
let mut file = open.await?;
let mut file = tokio::io::BufWriter::with_capacity(WRITE_BUFFER_SIZE, open.await?);
let mut written: u64 = 0;
while let Some(chunk) = rx.recv().await {
written += chunk.len() as u64;
@@ -306,6 +310,7 @@ async fn write_file_from_receiver(
file.flush()
.await
.map_err(|e| format!("Failed to flush file: {e}"))?;
let file = file.into_inner();
if written != expected_size {
return Err(format!(
+7 -1
View File
@@ -6,6 +6,9 @@ use tokio::sync::mpsc;
/// Channel capacity used when normalizing a file-backed [`FileContent`] into a stream.
const FILE_CHANNEL_CAPACITY: usize = 16;
/// Buffer size used when reading a file into chunks.
const READ_BUFFER_SIZE: usize = 512 * 1024;
/// The binary content of a file provided by the application for a transfer.
///
/// Shared by the HTTP client (upload) and server (download API) so both can
@@ -73,9 +76,12 @@ impl FileContent {
async fn read_file_into_sender(mut file: tokio::fs::File, tx: mpsc::Sender<Bytes>) {
use tokio::io::AsyncReadExt;
let mut buffer = bytes::BytesMut::with_capacity(64 * 1024);
let mut buffer = bytes::BytesMut::new();
let mut total: u64 = 0;
loop {
// Re-reserve every iteration: `split()` hands the filled part off, which
// can leave little spare capacity for the next read.
buffer.reserve(READ_BUFFER_SIZE);
match file.read_buf(&mut buffer).await {
Ok(0) => break,
Ok(n) => {
+1 -1
View File
@@ -28,7 +28,7 @@ async fn hash_file_from_path() {
/// reporting the cumulative progress after each of them.
#[tokio::test]
async fn hash_large_file_from_path() {
let content: Vec<u8> = (0..500_000).map(|i| (i % 251) as u8).collect();
let content: Vec<u8> = (0..2_000_000).map(|i| (i % 251) as u8).collect();
let path = std::env::temp_dir().join(format!("localsend-hash-{}", uuid::Uuid::new_v4()));
tokio::fs::write(&path, &content).await.unwrap();