1+ //! Benchmark comparing compile-time optimizations vs runtime optimizations
2+ //!
3+ //! This benchmark measures the performance impact of compile-time pattern analysis
4+ //! and optimization compared to runtime decision-making.
5+
6+ #![ allow( missing_docs ) ]
7+
8+ use criterion:: { black_box, criterion_group, criterion_main, BenchmarkId , Criterion , Throughput } ;
9+ use std:: time:: Instant ;
10+
11+ use strs_tools:: string:: split;
12+ use strs_tools:: string:: zero_copy:: ZeroCopyStringExt ;
13+
14+ #[ cfg( feature = "compile_time_optimizations" ) ]
15+ use strs_tools:: { optimize_split, optimize_match } ;
16+
17+ /// Generate test data for benchmarking
18+ fn generate_benchmark_data ( size : usize , pattern : & str ) -> String {
19+ match pattern {
20+ "csv" => "field1,field2,field3,field4,field5,field6,field7,field8" . repeat ( size / 50 + 1 ) ,
21+ "structured" => "key1:value1;key2:value2,key3:value3|key4:value4" . repeat ( size / 60 + 1 ) ,
22+ "urls" => "https://example.com,http://test.org,ftp://files.net" . repeat ( size / 50 + 1 ) ,
23+ _ => "a,b,c" . repeat ( size / 5 + 1 ) ,
24+ }
25+ }
26+
27+ /// Benchmark single delimiter splitting
28+ fn bench_single_delimiter_split ( c : & mut Criterion ) {
29+ let mut group = c. benchmark_group ( "single_delimiter_split" ) ;
30+
31+ let test_cases = [
32+ ( "small_1kb" , 1024 ) ,
33+ ( "medium_10kb" , 10240 ) ,
34+ ( "large_100kb" , 102400 ) ,
35+ ] ;
36+
37+ for ( name, size ) in test_cases {
38+ let csv_data = generate_benchmark_data ( size, "csv" ) ;
39+ group. throughput ( Throughput :: Bytes ( csv_data. len ( ) as u64 ) ) ;
40+
41+ // Runtime optimization (standard library split)
42+ group. bench_with_input (
43+ BenchmarkId :: new ( "stdlib_split" , name ) ,
44+ & csv_data,
45+ |b, data| {
46+ b. iter ( || {
47+ let result: Vec < & str > = data. split ( ',' ) . collect ( ) ;
48+ black_box ( result )
49+ } ) ;
50+ } ,
51+ ) ;
52+
53+ // Runtime optimization (zero-copy)
54+ group. bench_with_input (
55+ BenchmarkId :: new ( "zero_copy_runtime" , name ) ,
56+ & csv_data,
57+ |b, data| {
58+ b. iter ( || {
59+ let result: Vec < _ > = data. zero_copy_split ( & [ "," ] ) . collect ( ) ;
60+ black_box ( result )
61+ } ) ;
62+ } ,
63+ ) ;
64+
65+ // Compile-time optimization
66+ #[ cfg( feature = "compile_time_optimizations" ) ]
67+ group. bench_with_input (
68+ BenchmarkId :: new ( "compile_time_optimized" , name ) ,
69+ & csv_data,
70+ |b, data| {
71+ b. iter ( || {
72+ let result: Vec < _ > = optimize_split ! ( black_box( data ) , "," ) . collect ( ) ;
73+ black_box ( result )
74+ } ) ;
75+ } ,
76+ ) ;
77+ }
78+
79+ group. finish ( ) ;
80+ }
81+
82+ /// Benchmark multiple delimiter splitting
83+ fn bench_multiple_delimiter_split ( c : & mut Criterion ) {
84+ let mut group = c. benchmark_group ( "multiple_delimiter_split" ) ;
85+
86+ let test_cases = [
87+ ( "small_1kb" , 1024 ) ,
88+ ( "medium_10kb" , 10240 ) ,
89+ ( "large_100kb" , 102400 ) ,
90+ ] ;
91+
92+ for ( name, size ) in test_cases {
93+ let structured_data = generate_benchmark_data ( size, "structured" ) ;
94+ group. throughput ( Throughput :: Bytes ( structured_data. len ( ) as u64 ) ) ;
95+
96+ // Runtime optimization (traditional)
97+ group. bench_with_input (
98+ BenchmarkId :: new ( "traditional_runtime" , name ) ,
99+ & structured_data,
100+ |b, data| {
101+ b. iter ( || {
102+ let result: Vec < String > = split ( )
103+ . src ( black_box ( data ) )
104+ . delimeter ( vec ! [ ":" , ";" , "," , "|" ] )
105+ . perform ( )
106+ . map ( |split| split. string . into_owned ( ) )
107+ . collect ( ) ;
108+ black_box ( result )
109+ } ) ;
110+ } ,
111+ ) ;
112+
113+ // Runtime optimization (zero-copy)
114+ group. bench_with_input (
115+ BenchmarkId :: new ( "zero_copy_runtime" , name ) ,
116+ & structured_data,
117+ |b, data| {
118+ b. iter ( || {
119+ let result: Vec < _ > = data. zero_copy_split ( & [ ":" , ";" , "," , "|" ] ) . collect ( ) ;
120+ black_box ( result )
121+ } ) ;
122+ } ,
123+ ) ;
124+
125+ // Compile-time optimization
126+ #[ cfg( feature = "compile_time_optimizations" ) ]
127+ group. bench_with_input (
128+ BenchmarkId :: new ( "compile_time_optimized" , name ) ,
129+ & structured_data,
130+ |b, data| {
131+ b. iter ( || {
132+ let result: Vec < _ > = optimize_split ! (
133+ black_box( data ) ,
134+ [ ":" , ";" , "," , "|" ]
135+ ) . collect ( ) ;
136+ black_box ( result )
137+ } ) ;
138+ } ,
139+ ) ;
140+ }
141+
142+ group. finish ( ) ;
143+ }
144+
145+ /// Benchmark pattern matching
146+ fn bench_pattern_matching ( c : & mut Criterion ) {
147+ let mut group = c. benchmark_group ( "pattern_matching" ) ;
148+
149+ let url_data = generate_benchmark_data ( 50000 , "urls" ) ;
150+ group. throughput ( Throughput :: Bytes ( url_data. len ( ) as u64 ) ) ;
151+
152+ // Runtime pattern matching
153+ group. bench_function ( "runtime_pattern_matching" , |b| {
154+ b. iter ( || {
155+ let mut matches = Vec :: new ( ) ;
156+ let data = black_box ( & url_data ) ;
157+
158+ if let Some ( pos ) = data. find ( "https://" ) {
159+ matches. push ( pos ) ;
160+ }
161+ if let Some ( pos ) = data. find ( "http://" ) {
162+ matches. push ( pos ) ;
163+ }
164+ if let Some ( pos ) = data. find ( "ftp://" ) {
165+ matches. push ( pos ) ;
166+ }
167+
168+ black_box ( matches )
169+ } ) ;
170+ } ) ;
171+
172+ // Compile-time optimized pattern matching
173+ #[ cfg( feature = "compile_time_optimizations" ) ]
174+ group. bench_function ( "compile_time_pattern_matching" , |b| {
175+ b. iter ( || {
176+ let result = optimize_match ! (
177+ black_box( & url_data ) ,
178+ [ "https://" , "http://" , "ftp://" ] ,
179+ strategy = "first_match"
180+ ) ;
181+ black_box ( result )
182+ } ) ;
183+ } ) ;
184+
185+ group. finish ( ) ;
186+ }
187+
188+ /// Benchmark delimiter preservation
189+ fn bench_delimiter_preservation ( c : & mut Criterion ) {
190+ let mut group = c. benchmark_group ( "delimiter_preservation" ) ;
191+
192+ let test_data = "key1:value1;key2:value2,key3:value3" . repeat ( 500 ) ;
193+ group. throughput ( Throughput :: Bytes ( test_data. len ( ) as u64 ) ) ;
194+
195+ // Runtime delimiter preservation
196+ group. bench_function ( "runtime_preserve_delimiters" , |b| {
197+ b. iter ( || {
198+ let result: Vec < _ > = test_data. zero_copy_split_preserve ( & [ ":" , ";" , "," ] ) . collect ( ) ;
199+ black_box ( result )
200+ } ) ;
201+ } ) ;
202+
203+ // Compile-time optimized delimiter preservation
204+ #[ cfg( feature = "compile_time_optimizations" ) ]
205+ group. bench_function ( "compile_time_preserve_delimiters" , |b| {
206+ b. iter ( || {
207+ let result: Vec < _ > = optimize_split ! (
208+ & test_data,
209+ [ ":" , ";" , "," ] ,
210+ preserve_delimiters = true
211+ ) . collect ( ) ;
212+ black_box ( result )
213+ } ) ;
214+ } ) ;
215+
216+ group. finish ( ) ;
217+ }
218+
219+ /// Benchmark counting operations (no allocation)
220+ fn bench_counting_operations ( c : & mut Criterion ) {
221+ let mut group = c. benchmark_group ( "counting_operations" ) ;
222+
223+ let large_data = "item1,item2,item3,item4,item5" . repeat ( 10000 ) ;
224+ group. throughput ( Throughput :: Bytes ( large_data. len ( ) as u64 ) ) ;
225+
226+ // Runtime counting
227+ group. bench_function ( "runtime_count" , |b| {
228+ b. iter ( || {
229+ let count = large_data. count_segments ( & [ "," ] ) ;
230+ black_box ( count )
231+ } ) ;
232+ } ) ;
233+
234+ // Compile-time optimized counting
235+ #[ cfg( feature = "compile_time_optimizations" ) ]
236+ group. bench_function ( "compile_time_count" , |b| {
237+ b. iter ( || {
238+ let count = optimize_split ! ( & large_data, "," ) . count ( ) ;
239+ black_box ( count )
240+ } ) ;
241+ } ) ;
242+
243+ group. finish ( ) ;
244+ }
245+
246+ /// Memory usage comparison benchmark
247+ fn bench_memory_usage_patterns ( c : & mut Criterion ) {
248+ let mut group = c. benchmark_group ( "memory_usage_patterns" ) ;
249+ group. sample_size ( 20 ) ;
250+
251+ let test_data = generate_benchmark_data ( 100000 , "csv" ) ;
252+ group. throughput ( Throughput :: Bytes ( test_data. len ( ) as u64 ) ) ;
253+
254+ // Runtime memory pattern
255+ group. bench_function ( "runtime_memory_pattern" , |b| {
256+ b. iter_custom ( |iters| {
257+ let start_time = Instant :: now ( ) ;
258+
259+ for _ in 0 ..iters {
260+ let result: Vec < _ > = test_data. zero_copy_split ( & [ "," ] ) . collect ( ) ;
261+ black_box ( result ) ;
262+ }
263+
264+ start_time. elapsed ( )
265+ } ) ;
266+ } ) ;
267+
268+ // Compile-time optimized memory pattern
269+ #[ cfg( feature = "compile_time_optimizations" ) ]
270+ group. bench_function ( "compile_time_memory_pattern" , |b| {
271+ b. iter_custom ( |iters| {
272+ let start_time = Instant :: now ( ) ;
273+
274+ for _ in 0 ..iters {
275+ let result: Vec < _ > = optimize_split ! ( & test_data, "," ) . collect ( ) ;
276+ black_box ( result ) ;
277+ }
278+
279+ start_time. elapsed ( )
280+ } ) ;
281+ } ) ;
282+
283+ group. finish ( ) ;
284+ }
285+
286+ /// Complex pattern optimization benchmark
287+ #[ cfg( feature = "compile_time_optimizations" ) ]
288+ fn bench_complex_pattern_optimization ( c : & mut Criterion ) {
289+ let mut group = c. benchmark_group ( "complex_pattern_optimization" ) ;
290+
291+ let complex_data = "prefix1::item1->value1|prefix2::item2->value2|prefix3::item3->value3" . repeat ( 1000 ) ;
292+ group. throughput ( Throughput :: Bytes ( complex_data. len ( ) as u64 ) ) ;
293+
294+ // Runtime complex pattern handling
295+ group. bench_function ( "runtime_complex_patterns" , |b| {
296+ b. iter ( || {
297+ let result: Vec < _ > = complex_data. zero_copy_split ( & [ "::" , "->" , "|" ] ) . collect ( ) ;
298+ black_box ( result )
299+ } ) ;
300+ } ) ;
301+
302+ // Compile-time optimized complex patterns
303+ group. bench_function ( "compile_time_complex_patterns" , |b| {
304+ b. iter ( || {
305+ let result: Vec < _ > = optimize_split ! (
306+ & complex_data,
307+ [ "::" , "->" , "|" ] ,
308+ use_simd = true
309+ ) . collect ( ) ;
310+ black_box ( result )
311+ } ) ;
312+ } ) ;
313+
314+ group. finish ( ) ;
315+ }
316+
317+ criterion_group ! (
318+ compile_time_benches,
319+ bench_single_delimiter_split,
320+ bench_multiple_delimiter_split,
321+ bench_pattern_matching,
322+ bench_delimiter_preservation,
323+ bench_counting_operations,
324+ bench_memory_usage_patterns,
325+ ) ;
326+
327+ #[ cfg( feature = "compile_time_optimizations" ) ]
328+ criterion_group ! (
329+ compile_time_advanced_benches,
330+ bench_complex_pattern_optimization,
331+ ) ;
332+
333+ #[ cfg( feature = "compile_time_optimizations" ) ]
334+ criterion_main ! ( compile_time_benches, compile_time_advanced_benches ) ;
335+
336+ #[ cfg( not( feature = "compile_time_optimizations" ) ) ]
337+ criterion_main ! ( compile_time_benches ) ;
0 commit comments