1+ use criterion:: { criterion_group, criterion_main, BenchmarkId , Criterion , Throughput } ;
2+ use sonic_rs:: { Object , Value , from_str} ;
3+
4+ fn create_small_object ( size : usize ) -> Object {
5+ let mut obj = Object :: new ( ) ;
6+ for i in 0 ..size {
7+ obj. insert ( & format ! ( "key{:02}" , i) , Value :: from ( i) ) ;
8+ }
9+ obj
10+ }
11+
12+ fn create_medium_object ( size : usize ) -> Object {
13+ let mut obj = Object :: new ( ) ;
14+ for i in 0 ..size {
15+ // Use longer keys to benefit from SIMD optimization
16+ obj. insert ( & format ! ( "medium_key_name_{:03}" , i) , Value :: from ( i) ) ;
17+ }
18+ obj
19+ }
20+
21+ fn create_large_object ( size : usize ) -> Object {
22+ let mut obj = Object :: new ( ) ;
23+ for i in 0 ..size {
24+ obj. insert ( & format ! ( "large_object_key_{:04}" , i) , Value :: from ( i * 10 ) ) ;
25+ }
26+ obj
27+ }
28+
29+ fn bench_small_objects ( c : & mut Criterion ) {
30+ let core_ids = core_affinity:: get_core_ids ( ) . unwrap ( ) ;
31+ core_affinity:: set_for_current ( core_ids[ 0 ] ) ;
32+
33+ let mut group = c. benchmark_group ( "small_objects_1_to_7_keys" ) ;
34+
35+ for size in [ 1 , 3 , 5 , 7 ] {
36+ let obj = create_small_object ( size) ;
37+ let test_key = format ! ( "key{:02}" , size / 2 ) ; // middle key
38+
39+ group. throughput ( Throughput :: Elements ( 1 ) ) ;
40+ group. bench_with_input (
41+ BenchmarkId :: new ( "optimized_get" , size) ,
42+ & ( obj, test_key) ,
43+ |b, ( obj, key) | {
44+ b. iter ( || obj. get ( key) )
45+ }
46+ ) ;
47+ }
48+ group. finish ( ) ;
49+ }
50+
51+ fn bench_medium_objects ( c : & mut Criterion ) {
52+ let core_ids = core_affinity:: get_core_ids ( ) . unwrap ( ) ;
53+ core_affinity:: set_for_current ( core_ids[ 0 ] ) ;
54+
55+ let mut group = c. benchmark_group ( "medium_objects_8_to_31_keys" ) ;
56+
57+ for size in [ 8 , 15 , 20 , 31 ] {
58+ let obj = create_medium_object ( size) ;
59+ let test_key = format ! ( "medium_key_name_{:03}" , size / 2 ) ; // middle key
60+
61+ group. throughput ( Throughput :: Elements ( 1 ) ) ;
62+ group. bench_with_input (
63+ BenchmarkId :: new ( "simd_optimized_get" , size) ,
64+ & ( obj, test_key) ,
65+ |b, ( obj, key) | {
66+ b. iter ( || obj. get ( key) )
67+ }
68+ ) ;
69+ }
70+ group. finish ( ) ;
71+ }
72+
73+ fn bench_large_objects ( c : & mut Criterion ) {
74+ let core_ids = core_affinity:: get_core_ids ( ) . unwrap ( ) ;
75+ core_affinity:: set_for_current ( core_ids[ 0 ] ) ;
76+
77+ let mut group = c. benchmark_group ( "large_objects_32_plus_keys" ) ;
78+
79+ for size in [ 32 , 50 , 100 , 200 ] {
80+ let obj = create_large_object ( size) ;
81+ let test_key = format ! ( "large_object_key_{:04}" , size / 2 ) ; // middle key
82+
83+ group. throughput ( Throughput :: Elements ( 1 ) ) ;
84+ group. bench_with_input (
85+ BenchmarkId :: new ( "hash_index_get" , size) ,
86+ & ( obj, test_key) ,
87+ |b, ( obj, key) | {
88+ b. iter ( || obj. get ( key) )
89+ }
90+ ) ;
91+ }
92+ group. finish ( ) ;
93+ }
94+
95+ fn bench_different_key_positions ( c : & mut Criterion ) {
96+ let core_ids = core_affinity:: get_core_ids ( ) . unwrap ( ) ;
97+ core_affinity:: set_for_current ( core_ids[ 0 ] ) ;
98+
99+ let mut group = c. benchmark_group ( "key_position_impact" ) ;
100+
101+ let obj = create_large_object ( 100 ) ;
102+
103+ // Test first, middle, and last key positions
104+ let positions = [
105+ ( "first" , "large_object_key_0000" ) ,
106+ ( "middle" , "large_object_key_0050" ) ,
107+ ( "last" , "large_object_key_0099" ) ,
108+ ] ;
109+
110+ for ( pos_name, key) in positions {
111+ group. bench_with_input (
112+ BenchmarkId :: new ( "get_by_position" , pos_name) ,
113+ & key,
114+ |b, key| {
115+ b. iter ( || obj. get ( key) )
116+ }
117+ ) ;
118+ }
119+ group. finish ( ) ;
120+ }
121+
122+ fn bench_cache_behavior ( c : & mut Criterion ) {
123+ let core_ids = core_affinity:: get_core_ids ( ) . unwrap ( ) ;
124+ core_affinity:: set_for_current ( core_ids[ 0 ] ) ;
125+
126+ let mut group = c. benchmark_group ( "cache_behavior" ) ;
127+
128+ let obj = create_large_object ( 100 ) ;
129+ let test_key = "large_object_key_0050" ;
130+
131+ group. bench_function ( "repeated_lookups" , |b| {
132+ b. iter ( || {
133+ // Perform multiple lookups to test cache effectiveness
134+ for _ in 0 ..10 {
135+ obj. get ( & test_key) ;
136+ }
137+ } )
138+ } ) ;
139+
140+ group. finish ( ) ;
141+ }
142+
143+ fn bench_key_length_impact ( c : & mut Criterion ) {
144+ let core_ids = core_affinity:: get_core_ids ( ) . unwrap ( ) ;
145+ core_affinity:: set_for_current ( core_ids[ 0 ] ) ;
146+
147+ let mut group = c. benchmark_group ( "key_length_impact" ) ;
148+
149+ // Test with different key lengths to evaluate SIMD effectiveness
150+ let test_cases = [
151+ ( "short" , 4 , "k" ) ,
152+ ( "medium" , 16 , "medium_length_key" ) ,
153+ ( "long" , 32 , "very_long_key_name_that_should_benefit_from_simd" ) ,
154+ ] ;
155+
156+ for ( name, obj_size, key_prefix) in test_cases {
157+ let mut obj = Object :: new ( ) ;
158+ for i in 0 ..obj_size {
159+ let key = format ! ( "{}_{:03}" , key_prefix, i) ;
160+ obj. insert ( & key, Value :: from ( i) ) ;
161+ }
162+
163+ let test_key = format ! ( "{}_{:03}" , key_prefix, obj_size / 2 ) ;
164+
165+ group. bench_with_input (
166+ BenchmarkId :: new ( "get_by_key_length" , name) ,
167+ & ( obj, test_key) ,
168+ |b, ( obj, key) | {
169+ b. iter ( || obj. get ( key) )
170+ }
171+ ) ;
172+ }
173+ group. finish ( ) ;
174+ }
175+
176+ fn bench_real_world_patterns ( c : & mut Criterion ) {
177+ let core_ids = core_affinity:: get_core_ids ( ) . unwrap ( ) ;
178+ core_affinity:: set_for_current ( core_ids[ 0 ] ) ;
179+
180+ let mut group = c. benchmark_group ( "real_world_patterns" ) ;
181+
182+ // Simulate common JSON patterns
183+ let json_configs = [
184+ ( "api_response" , r#"{"status": "success", "data": {"id": 123, "name": "John", "email": "[email protected] "}, "timestamp": "2024-01-01T00:00:00Z", "version": "1.0"}"# ) , 185+ ( "user_profile" , r#"{"userId": 12345, "username": "johndoe", "firstName": "John", "lastName": "Doe", "email": "[email protected] ", "birthDate": "1990-01-01", "isActive": true, "roles": ["user", "admin"], "preferences": {"theme": "dark", "language": "en"}, "lastLogin": "2024-01-01T12:00:00Z"}"# ) , 186+ ] ;
187+
188+ for ( name, json) in json_configs {
189+ let obj: Object = from_str ( json) . unwrap ( ) ;
190+
191+ // Test common access patterns
192+ let test_keys = match name {
193+ "api_response" => vec ! [ "status" , "data" , "timestamp" ] ,
194+ "user_profile" => vec ! [ "userId" , "email" , "isActive" , "preferences" ] ,
195+ _ => vec ! [ "status" ] ,
196+ } ;
197+
198+ for key in test_keys {
199+ group. bench_with_input (
200+ BenchmarkId :: new ( name, key) ,
201+ & ( obj. clone ( ) , key) ,
202+ |b, ( obj, key) | {
203+ b. iter ( || obj. get ( key) )
204+ }
205+ ) ;
206+ }
207+ }
208+ group. finish ( ) ;
209+ }
210+
211+ criterion_group ! (
212+ benches,
213+ bench_small_objects,
214+ bench_medium_objects,
215+ bench_large_objects,
216+ bench_different_key_positions,
217+ bench_cache_behavior,
218+ bench_key_length_impact,
219+ bench_real_world_patterns
220+ ) ;
221+ criterion_main ! ( benches) ;
0 commit comments