@@ -29,6 +29,8 @@ use std::env;
2929use std:: error:: Error ;
3030use std:: fs;
3131use std:: hint:: black_box;
32+ use std:: ptr;
33+ use std:: slice;
3234use std:: time:: Duration ;
3335
3436use criterion:: { Criterion , Throughput } ;
@@ -205,6 +207,177 @@ fn bench_generate_random(
205207 }
206208}
207209
210+ fn bench_memset (
211+ g : & mut criterion:: BenchmarkGroup < ' _ , criterion:: measurement:: WallTime > ,
212+ tokens : & mut [ & mut [ u8 ] ] ,
213+ ) {
214+ const FILL_VALUE : u8 = 0xAA ;
215+ let templates: Vec < Vec < u8 > > = tokens. iter ( ) . map ( |token| ( * * token) . to_vec ( ) ) . collect ( ) ;
216+ let total_bytes: usize = templates. iter ( ) . map ( |buf| buf. len ( ) ) . sum ( ) ;
217+ if total_bytes == 0 {
218+ return ;
219+ }
220+ g. throughput ( Throughput :: Bytes ( total_bytes as u64 ) ) ;
221+
222+ if should_run ( "memset/stringzilla::fill" ) {
223+ let mut buffers = templates. clone ( ) ;
224+ g. bench_function ( "stringzilla::fill" , |b| {
225+ b. iter ( || {
226+ for buffer in buffers. iter_mut ( ) {
227+ sz:: fill ( buffer, FILL_VALUE ) ;
228+ black_box ( & buffer) ;
229+ }
230+ } )
231+ } ) ;
232+ }
233+
234+ if should_run ( "memset/std::ptr::write_bytes" ) {
235+ let mut buffers = templates. clone ( ) ;
236+ g. bench_function ( "std::ptr::write_bytes" , |b| {
237+ b. iter ( || {
238+ for buffer in buffers. iter_mut ( ) {
239+ unsafe {
240+ ptr:: write_bytes ( buffer. as_mut_ptr ( ) , FILL_VALUE , buffer. len ( ) ) ;
241+ }
242+ black_box ( & buffer) ;
243+ }
244+ } )
245+ } ) ;
246+ }
247+
248+ if should_run ( "memset/slice::fill" ) {
249+ let mut buffers = templates. clone ( ) ;
250+ g. bench_function ( "slice::fill" , |b| {
251+ b. iter ( || {
252+ for buffer in buffers. iter_mut ( ) {
253+ buffer. fill ( FILL_VALUE ) ;
254+ black_box ( & buffer) ;
255+ }
256+ } )
257+ } ) ;
258+ }
259+ }
260+
261+ fn bench_memcpy (
262+ g : & mut criterion:: BenchmarkGroup < ' _ , criterion:: measurement:: WallTime > ,
263+ tokens : & mut [ & mut [ u8 ] ] ,
264+ ) {
265+ let sources: Vec < Vec < u8 > > = tokens. iter ( ) . map ( |token| ( * * token) . to_vec ( ) ) . collect ( ) ;
266+ let dest_template: Vec < Vec < u8 > > = sources. iter ( ) . map ( |src| vec ! [ 0u8 ; src. len( ) ] ) . collect ( ) ;
267+ let total_bytes: usize = sources. iter ( ) . map ( |buf| buf. len ( ) ) . sum ( ) ;
268+ if total_bytes == 0 {
269+ return ;
270+ }
271+ g. throughput ( Throughput :: Bytes ( total_bytes as u64 ) ) ;
272+
273+ if should_run ( "memcpy/stringzilla::copy" ) {
274+ let mut dests = dest_template. clone ( ) ;
275+ g. bench_function ( "stringzilla::copy" , |b| {
276+ b. iter ( || {
277+ for ( src, dst) in sources. iter ( ) . zip ( dests. iter_mut ( ) ) {
278+ sz:: copy ( dst, src) ;
279+ black_box ( & dst) ;
280+ }
281+ } )
282+ } ) ;
283+ }
284+
285+ if should_run ( "memcpy/slice::copy_from_slice" ) {
286+ let mut dests = dest_template. clone ( ) ;
287+ g. bench_function ( "slice::copy_from_slice" , |b| {
288+ b. iter ( || {
289+ for ( src, dst) in sources. iter ( ) . zip ( dests. iter_mut ( ) ) {
290+ dst. copy_from_slice ( src) ;
291+ black_box ( & dst) ;
292+ }
293+ } )
294+ } ) ;
295+ }
296+
297+ if should_run ( "memcpy/std::ptr::copy_nonoverlapping" ) {
298+ let mut dests = dest_template. clone ( ) ;
299+ g. bench_function ( "std::ptr::copy_nonoverlapping" , |b| {
300+ b. iter ( || {
301+ for ( src, dst) in sources. iter ( ) . zip ( dests. iter_mut ( ) ) {
302+ unsafe {
303+ ptr:: copy_nonoverlapping ( src. as_ptr ( ) , dst. as_mut_ptr ( ) , src. len ( ) ) ;
304+ }
305+ black_box ( & dst) ;
306+ }
307+ } )
308+ } ) ;
309+ }
310+ }
311+
312+ fn bench_memmove (
313+ g : & mut criterion:: BenchmarkGroup < ' _ , criterion:: measurement:: WallTime > ,
314+ tokens : & mut [ & mut [ u8 ] ] ,
315+ ) {
316+ const SHIFT : usize = 8 ;
317+ let templates: Vec < Vec < u8 > > = tokens
318+ . iter ( )
319+ . filter_map ( |token| {
320+ let slice = & * * token;
321+ if slice. len ( ) <= SHIFT {
322+ None
323+ } else {
324+ Some ( slice. to_vec ( ) )
325+ }
326+ } )
327+ . collect ( ) ;
328+ if templates. is_empty ( ) {
329+ return ;
330+ }
331+ let total_bytes: usize = templates. iter ( ) . map ( |buf| buf. len ( ) - SHIFT ) . sum ( ) ;
332+ g. throughput ( Throughput :: Bytes ( total_bytes as u64 ) ) ;
333+
334+ if should_run ( "memmove/stringzilla::move_" ) {
335+ let mut buffers = templates. clone ( ) ;
336+ g. bench_function ( "stringzilla::move_" , |b| {
337+ b. iter ( || {
338+ for buffer in buffers. iter_mut ( ) {
339+ let move_len = buffer. len ( ) - SHIFT ;
340+ unsafe {
341+ let src = slice:: from_raw_parts ( buffer. as_ptr ( ) , move_len) ;
342+ let dst =
343+ slice:: from_raw_parts_mut ( buffer. as_mut_ptr ( ) . add ( SHIFT ) , move_len) ;
344+ sz:: move_ ( dst, & src) ;
345+ }
346+ black_box ( & buffer) ;
347+ }
348+ } )
349+ } ) ;
350+ }
351+
352+ if should_run ( "memmove/std::ptr::copy" ) {
353+ let mut buffers = templates. clone ( ) ;
354+ g. bench_function ( "std::ptr::copy" , |b| {
355+ b. iter ( || {
356+ for buffer in buffers. iter_mut ( ) {
357+ let move_len = buffer. len ( ) - SHIFT ;
358+ unsafe {
359+ ptr:: copy ( buffer. as_ptr ( ) , buffer. as_mut_ptr ( ) . add ( SHIFT ) , move_len) ;
360+ }
361+ black_box ( & buffer) ;
362+ }
363+ } )
364+ } ) ;
365+ }
366+
367+ if should_run ( "memmove/slice::copy_within" ) {
368+ let mut buffers = templates. clone ( ) ;
369+ g. bench_function ( "slice::copy_within" , |b| {
370+ b. iter ( || {
371+ for buffer in buffers. iter_mut ( ) {
372+ let move_len = buffer. len ( ) - SHIFT ;
373+ buffer. copy_within ( 0 ..move_len, SHIFT ) ;
374+ black_box ( & buffer) ;
375+ }
376+ } )
377+ } ) ;
378+ }
379+ }
380+
208381fn main ( ) {
209382 log_stringzilla_metadata ( ) ;
210383
@@ -227,5 +400,20 @@ fn main() {
227400 bench_generate_random ( & mut group, & mut tokens[ ..] ) ;
228401 group. finish ( ) ;
229402
403+ // Benchmarks for memory fill operations
404+ let mut group = criterion. benchmark_group ( "memset" ) ;
405+ bench_memset ( & mut group, & mut tokens[ ..] ) ;
406+ group. finish ( ) ;
407+
408+ // Benchmarks for memory copy operations
409+ let mut group = criterion. benchmark_group ( "memcpy" ) ;
410+ bench_memcpy ( & mut group, & mut tokens[ ..] ) ;
411+ group. finish ( ) ;
412+
413+ // Benchmarks for memory move operations
414+ let mut group = criterion. benchmark_group ( "memmove" ) ;
415+ bench_memmove ( & mut group, & mut tokens[ ..] ) ;
416+ group. finish ( ) ;
417+
230418 criterion. final_summary ( ) ;
231419}
0 commit comments