/* * Copyright 2025 The Dragonfly Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ use bytes::Bytes; use bytesize::ByteSize; use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; use dragonfly_client_config::dfdaemon::{Config, Storage}; use dragonfly_client_storage::{cache::Cache, metadata::Piece}; use std::sync::Arc; use tokio::io::AsyncReadExt; use tokio::runtime::Runtime; // Number of pieces to write/read in each benchmark. const PIECE_COUNT: usize = 100; fn create_config(capacity: ByteSize) -> Config { Config { storage: Storage { cache_capacity: capacity, ..Default::default() }, ..Default::default() } } fn create_piece(length: u64) -> Piece { Piece { number: 0, offset: 0, length, digest: String::new(), parent_id: None, uploading_count: 0, uploaded_count: 0, updated_at: chrono::Utc::now().naive_utc(), created_at: chrono::Utc::now().naive_utc(), finished_at: None, } } pub fn put_task(c: &mut Criterion) { let rt: Runtime = Runtime::new().unwrap(); let mut group = c.benchmark_group("Put Task"); group.bench_with_input( BenchmarkId::new("Put Task", "10MB"), &ByteSize::mb(10), |b, size| { b.iter_batched( || rt.block_on(async { Cache::new(Arc::new(create_config(ByteSize::gb(2)))) }), |mut cache| { rt.block_on(async { cache.put_task("task", black_box(size.as_u64())).await; }); }, criterion::BatchSize::SmallInput, ); }, ); group.bench_with_input( BenchmarkId::new("Put Task", "100MB"), &ByteSize::mb(100), |b, size| { b.iter_batched( || rt.block_on(async { Cache::new(Arc::new(create_config(ByteSize::gb(2)))) }), |mut cache| { rt.block_on(async { cache.put_task("task", black_box(size.as_u64())).await; }); }, criterion::BatchSize::SmallInput, ); }, ); group.bench_with_input( BenchmarkId::new("Put Task", "1GB"), &ByteSize::gb(1), |b, size| { b.iter_batched( || rt.block_on(async { Cache::new(Arc::new(create_config(ByteSize::gb(2)))) }), |mut cache| { rt.block_on(async { cache.put_task("task", black_box(size.as_u64())).await; }); }, criterion::BatchSize::SmallInput, ); }, ); group.finish(); } pub fn delete_task(c: &mut Criterion) { let rt: Runtime = Runtime::new().unwrap(); let mut group = c.benchmark_group("Delete Task"); group.bench_with_input( BenchmarkId::new("Delete Task", "10MB"), &ByteSize::mb(10), |b, size| { b.iter_batched( || { let mut cache = rt.block_on(async { Cache::new(Arc::new(create_config(ByteSize::gb(2)))) }); rt.block_on(async { cache.put_task("task", black_box(size.as_u64())).await; }); cache }, |mut cache| { rt.block_on(async { cache.delete_task("task").await.unwrap(); }); }, criterion::BatchSize::SmallInput, ); }, ); group.bench_with_input( BenchmarkId::new("Delete Task", "100MB"), &ByteSize::mb(100), |b, size| { b.iter_batched( || { let mut cache = rt.block_on(async { Cache::new(Arc::new(create_config(ByteSize::gb(2)))) }); rt.block_on(async { cache.put_task("task", black_box(size.as_u64())).await; }); cache }, |mut cache| { rt.block_on(async { cache.delete_task("task").await.unwrap(); }); }, criterion::BatchSize::SmallInput, ); }, ); group.bench_with_input( BenchmarkId::new("Delete Task", "1GB"), &ByteSize::gb(1), |b, size| { b.iter_batched( || { let mut cache = rt.block_on(async { Cache::new(Arc::new(create_config(ByteSize::gb(2)))) }); rt.block_on(async { cache.put_task("task", black_box(size.as_u64())).await; }); cache }, |mut cache| { rt.block_on(async { cache.delete_task("task").await.unwrap(); }); }, criterion::BatchSize::SmallInput, ); }, ); group.finish(); } pub fn write_piece(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let mut group = c.benchmark_group("Write Piece"); group.bench_with_input( BenchmarkId::new("Write Piece", "4MB"), &vec![1u8; ByteSize::mb(4).as_u64() as usize], |b, data| { b.iter_batched( || { let mut cache = rt.block_on(async { Cache::new(Arc::new(create_config( ByteSize::mb(4) * PIECE_COUNT as u64, ))) }); rt.block_on(async { cache .put_task("task", (ByteSize::mb(4) * PIECE_COUNT as u64).as_u64()) .await; }); cache }, |cache| { rt.block_on(async { for i in 0..PIECE_COUNT { cache .write_piece( "task", &format!("piece{}", i), Bytes::copy_from_slice(data), ) .await .unwrap(); } }); }, criterion::BatchSize::SmallInput, ); }, ); group.bench_with_input( BenchmarkId::new("Write Piece", "10MB"), &vec![1u8; ByteSize::mb(10).as_u64() as usize], |b, data| { b.iter_batched( || { let mut cache = rt.block_on(async { Cache::new(Arc::new(create_config( ByteSize::mb(10) * PIECE_COUNT as u64, ))) }); rt.block_on(async { cache .put_task("task", (ByteSize::mb(10) * PIECE_COUNT as u64).as_u64()) .await; }); cache }, |cache| { rt.block_on(async { for i in 0..PIECE_COUNT { cache .write_piece( "task", &format!("piece{}", i), Bytes::copy_from_slice(data), ) .await .unwrap(); } }); }, criterion::BatchSize::SmallInput, ); }, ); group.bench_with_input( BenchmarkId::new("Write Piece", "16MB"), &vec![1u8; ByteSize::mb(16).as_u64() as usize], |b, data| { b.iter_batched( || { let mut cache = rt.block_on(async { Cache::new(Arc::new(create_config( ByteSize::mb(16) * PIECE_COUNT as u64, ))) }); rt.block_on(async { cache .put_task("task", (ByteSize::mb(16) * PIECE_COUNT as u64).as_u64()) .await; }); cache }, |cache| { rt.block_on(async { for i in 0..PIECE_COUNT { cache .write_piece( "task", &format!("piece{}", i), Bytes::copy_from_slice(data), ) .await .unwrap(); } }); }, criterion::BatchSize::SmallInput, ); }, ); group.finish(); } pub fn read_piece(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let mut group = c.benchmark_group("Read Piece"); group.bench_with_input( BenchmarkId::new("Read Piece", "4MB"), &vec![1u8; ByteSize::mb(4).as_u64() as usize], |b, data| { b.iter_batched( || { let mut cache = rt.block_on(async { Cache::new(Arc::new(create_config( ByteSize::mb(4) * PIECE_COUNT as u64, ))) }); rt.block_on(async { cache .put_task("task", (ByteSize::mb(4) * PIECE_COUNT as u64).as_u64()) .await; for i in 0..PIECE_COUNT { cache .write_piece( "task", &format!("piece{}", i), Bytes::copy_from_slice(data), ) .await .unwrap(); } }); cache }, |cache| { rt.block_on(async { for i in 0..PIECE_COUNT { let mut reader = cache .read_piece( "task", &format!("piece{}", i), create_piece(data.len() as u64), None, ) .await .unwrap(); let mut buffer = Vec::new(); reader.read_to_end(&mut buffer).await.unwrap(); } }); }, criterion::BatchSize::SmallInput, ); }, ); group.bench_with_input( BenchmarkId::new("Read Piece", "10MB"), &vec![1u8; ByteSize::mb(10).as_u64() as usize], |b, data| { b.iter_batched( || { let mut cache = rt.block_on(async { Cache::new(Arc::new(create_config( ByteSize::mb(10) * PIECE_COUNT as u64, ))) }); rt.block_on(async { cache .put_task("task", (ByteSize::mb(10) * PIECE_COUNT as u64).as_u64()) .await; for i in 0..PIECE_COUNT { cache .write_piece( "task", &format!("piece{}", i), Bytes::copy_from_slice(data), ) .await .unwrap(); } }); cache }, |cache| { rt.block_on(async { for i in 0..PIECE_COUNT { let mut reader = cache .read_piece( "task", &format!("piece{}", i), create_piece(data.len() as u64), None, ) .await .unwrap(); let mut buffer = Vec::new(); reader.read_to_end(&mut buffer).await.unwrap(); } }); }, criterion::BatchSize::SmallInput, ); }, ); group.bench_with_input( BenchmarkId::new("Read Piece", "16MB"), &vec![1u8; ByteSize::mb(16).as_u64() as usize], |b, data| { b.iter_batched( || { let mut cache = rt.block_on(async { Cache::new(Arc::new(create_config( ByteSize::mb(16) * PIECE_COUNT as u64, ))) }); rt.block_on(async { cache .put_task("task", (ByteSize::mb(16) * PIECE_COUNT as u64).as_u64()) .await; for i in 0..PIECE_COUNT { cache .write_piece( "task", &format!("piece{}", i), Bytes::copy_from_slice(data), ) .await .unwrap(); } }); cache }, |cache| { rt.block_on(async { for i in 0..PIECE_COUNT { let mut reader = cache .read_piece( "task", &format!("piece{}", i), create_piece(data.len() as u64), None, ) .await .unwrap(); let mut buffer = Vec::new(); reader.read_to_end(&mut buffer).await.unwrap(); } }); }, criterion::BatchSize::SmallInput, ); }, ); group.finish(); } criterion_group!(benches, put_task, delete_task, write_piece, read_piece,); criterion_main!(benches);