1
- use bevy:: log:: tracing_subscriber;
2
1
use bevy:: log:: tracing_subscriber:: layer:: SubscriberExt ;
3
- use bevy:: utils:: { tracing, HashMap } ;
2
+ use bevy:: log:: { tracing_subscriber, Level } ;
3
+ use bevy:: reflect:: Reflect ;
4
+ use bevy:: utils:: tracing;
5
+ use bevy:: utils:: tracing:: span;
6
+ use bevy_mod_scripting_core:: bindings:: {
7
+ FromScript , IntoScript , Mut , Ref , ReflectReference , ScriptValue , Val ,
8
+ } ;
4
9
use criterion:: { criterion_main, measurement:: Measurement , BenchmarkGroup , Criterion } ;
5
- use script_integration_test_harness:: { run_lua_benchmark, run_rhai_benchmark} ;
10
+ use criterion:: { BatchSize , BenchmarkFilter } ;
11
+ use regex:: Regex ;
12
+ use script_integration_test_harness:: test_functions:: rand:: Rng ;
13
+ use script_integration_test_harness:: {
14
+ perform_benchmark_with_generator, run_lua_benchmark, run_rhai_benchmark,
15
+ } ;
16
+ use std:: collections:: HashMap ;
6
17
use std:: { path:: PathBuf , sync:: LazyLock , time:: Duration } ;
7
18
use test_utils:: { discover_all_tests, Test } ;
8
19
@@ -65,10 +76,24 @@ impl BenchmarkExecutor for Test {
65
76
}
66
77
}
67
78
68
- fn script_benchmarks ( criterion : & mut Criterion ) {
79
+ fn script_benchmarks ( criterion : & mut Criterion , filter : Option < Regex > ) {
69
80
// find manifest dir
70
81
let manifest_dir = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
71
- let tests = discover_all_tests ( manifest_dir, |p| p. starts_with ( "benchmarks" ) ) ;
82
+ let tests = discover_all_tests ( manifest_dir, |p| {
83
+ p. path . starts_with ( "benchmarks" )
84
+ && if let Some ( filter) = & filter {
85
+ let matching = filter. is_match ( & p. benchmark_name ( ) ) ;
86
+ if !matching {
87
+ println ! (
88
+ "Skipping benchmark: '{}'. due to filter: '{filter}'" ,
89
+ p. benchmark_name( )
90
+ ) ;
91
+ } ;
92
+ matching
93
+ } else {
94
+ true
95
+ }
96
+ } ) ;
72
97
73
98
// group by benchmark group
74
99
let mut grouped: HashMap < String , Vec < Test > > =
@@ -83,9 +108,16 @@ fn script_benchmarks(criterion: &mut Criterion) {
83
108
}
84
109
85
110
for ( group, tests) in grouped {
111
+ println ! ( "Running benchmarks for group: {}" , group) ;
86
112
let mut benchmark_group = criterion. benchmark_group ( group) ;
87
113
88
114
for t in tests {
115
+ println ! ( "Running benchmark: {}" , t. benchmark_name( ) ) ;
116
+ span ! (
117
+ Level :: INFO ,
118
+ "Benchmark harness for test" ,
119
+ test_name = & t. benchmark_name( )
120
+ ) ;
89
121
t. execute ( & mut benchmark_group) ;
90
122
}
91
123
@@ -104,22 +136,135 @@ fn maybe_with_profiler(f: impl Fn(bool)) {
104
136
105
137
tracing:: subscriber:: set_global_default ( subscriber) . unwrap ( ) ;
106
138
107
- let _ = tracing_tracy:: client:: span!( "test2" ) ;
108
- tracing:: info_span!( "test" ) ;
109
-
110
139
f ( true ) ;
111
140
} else {
112
141
f ( false ) ;
113
142
}
114
143
}
115
144
145
+ /// benchmarks measuring conversion time for script values and other things
146
+ fn conversion_benchmarks ( criterion : & mut Criterion ) {
147
+ let mut group = criterion. benchmark_group ( "conversions" ) ;
148
+
149
+ #[ derive( Reflect ) ]
150
+ struct ReflectyVal ( pub u32 ) ;
151
+
152
+ perform_benchmark_with_generator (
153
+ "ScriptValue::List" ,
154
+ & |rng, _| {
155
+ let mut array = Vec :: new ( ) ;
156
+ for _ in 0 ..10 {
157
+ array. push ( ScriptValue :: Integer ( rng. random ( ) ) ) ;
158
+ }
159
+ ScriptValue :: List ( array)
160
+ } ,
161
+ & |w, i| {
162
+ let i = i. into_script ( w. clone ( ) ) . unwrap ( ) ;
163
+ let _ = Vec :: < ScriptValue > :: from_script ( i, w) . unwrap ( ) ;
164
+ } ,
165
+ & mut group,
166
+ BatchSize :: SmallInput ,
167
+ ) ;
168
+
169
+ perform_benchmark_with_generator (
170
+ "ScriptValue::Map" ,
171
+ & |rng, _| {
172
+ let mut map = HashMap :: default ( ) ;
173
+ for _ in 0 ..10 {
174
+ map. insert (
175
+ rng. random :: < u32 > ( ) . to_string ( ) ,
176
+ ScriptValue :: Integer ( rng. random ( ) ) ,
177
+ ) ;
178
+ }
179
+ ScriptValue :: Map ( map)
180
+ } ,
181
+ & |w, i| {
182
+ let i = i. into_script ( w. clone ( ) ) . unwrap ( ) ;
183
+ let _ = HashMap :: < String , ScriptValue > :: from_script ( i, w) . unwrap ( ) ;
184
+ } ,
185
+ & mut group,
186
+ BatchSize :: SmallInput ,
187
+ ) ;
188
+
189
+ perform_benchmark_with_generator (
190
+ "ScriptValue::Reference::from_into" ,
191
+ & |rng, world| {
192
+ let allocator = world. allocator ( ) ;
193
+ let mut allocator = allocator. write ( ) ;
194
+ ReflectReference :: new_allocated ( ReflectyVal ( rng. random ( ) ) , & mut allocator)
195
+ } ,
196
+ & |w, i| {
197
+ let i = i. into_script ( w. clone ( ) ) . unwrap ( ) ;
198
+ let _ = ReflectReference :: from_script ( i, w) . unwrap ( ) ;
199
+ } ,
200
+ & mut group,
201
+ BatchSize :: SmallInput ,
202
+ ) ;
203
+
204
+ perform_benchmark_with_generator (
205
+ "Val<T>::from_into" ,
206
+ & |rng, _| Val :: new ( ReflectyVal ( rng. random :: < u32 > ( ) ) ) ,
207
+ & |w, i| {
208
+ let v = i. into_script ( w. clone ( ) ) . unwrap ( ) ;
209
+ Val :: < ReflectyVal > :: from_script ( v, w) . unwrap ( ) ;
210
+ } ,
211
+ & mut group,
212
+ BatchSize :: SmallInput ,
213
+ ) ;
214
+
215
+ perform_benchmark_with_generator (
216
+ "Ref<T>::from" ,
217
+ & |rng, w| {
218
+ Val :: new ( ReflectyVal ( rng. random :: < u32 > ( ) ) )
219
+ . into_script ( w)
220
+ . unwrap ( )
221
+ } ,
222
+ & |w, i| {
223
+ Ref :: < ReflectyVal > :: from_script ( i, w) . unwrap ( ) ;
224
+ } ,
225
+ & mut group,
226
+ BatchSize :: SmallInput ,
227
+ ) ;
228
+
229
+ perform_benchmark_with_generator (
230
+ "Mut<T>::from" ,
231
+ & |rng, w| {
232
+ Val :: new ( ReflectyVal ( rng. random :: < u32 > ( ) ) )
233
+ . into_script ( w)
234
+ . unwrap ( )
235
+ } ,
236
+ & |w, i| {
237
+ Mut :: < ReflectyVal > :: from_script ( i, w) . unwrap ( ) ;
238
+ } ,
239
+ & mut group,
240
+ BatchSize :: SmallInput ,
241
+ ) ;
242
+ }
243
+
116
244
pub fn benches ( ) {
117
245
maybe_with_profiler ( |_profiler| {
118
246
let mut criterion: criterion:: Criterion < _ > = ( criterion:: Criterion :: default ( ) )
119
247
. configure_from_args ( )
120
248
. measurement_time ( Duration :: from_secs ( 10 ) ) ;
249
+ let arguments = std:: env:: args ( )
250
+ . skip ( 1 ) // the executable name
251
+ . filter ( |a| !a. starts_with ( "-" ) )
252
+ . collect :: < Vec < String > > ( ) ;
253
+
254
+ // take first argument as .*<val>.* regex for benchmarks
255
+ // criterion will already have that as a filter, but we want to make sure we're on the same page
256
+ let filter = if let Some ( n) = arguments. first ( ) {
257
+ println ! ( "using filter: '{n}'" ) ;
258
+ let regex = Regex :: new ( n) . unwrap ( ) ;
259
+ let filter = BenchmarkFilter :: Regex ( regex. clone ( ) ) ;
260
+ criterion = criterion. with_benchmark_filter ( filter) ;
261
+ Some ( regex)
262
+ } else {
263
+ None
264
+ } ;
121
265
122
- script_benchmarks ( & mut criterion) ;
266
+ script_benchmarks ( & mut criterion, filter) ;
267
+ conversion_benchmarks ( & mut criterion) ;
123
268
} ) ;
124
269
}
125
270
criterion_main ! ( benches) ;
0 commit comments