@@ -4,7 +4,7 @@ use std::iter::FromIterator;
4
4
use std:: sync:: atomic:: { AtomicUsize , Ordering :: SeqCst } ;
5
5
6
6
use graph:: prelude:: { lazy_static, q} ;
7
- use rand:: { rngs:: SmallRng , thread_rng , Rng } ;
7
+ use rand:: { rngs:: SmallRng , Rng } ;
8
8
use rand:: { FromEntropy , SeedableRng } ;
9
9
use structopt:: StructOpt ;
10
10
@@ -187,26 +187,26 @@ trait Template<T>: CacheWeight + Default {
187
187
type Item ;
188
188
189
189
// Create a new test object
190
- fn create ( size : usize ) -> Self ;
190
+ fn create ( size : usize , rng : Option < & mut SmallRng > ) -> Self ;
191
191
192
192
// Return a sample of this test object of the given `size`. There's no
193
193
// fixed definition of 'size', other than that smaller sizes will
194
194
// take less memory than larger ones
195
- fn sample ( & self , size : usize ) -> Box < Self :: Item > ;
195
+ fn sample ( & self , size : usize , rng : Option < & mut SmallRng > ) -> Box < Self :: Item > ;
196
196
}
197
197
198
198
/// Template for testing caching of `String`
199
199
impl Template < String > for String {
200
200
type Item = String ;
201
201
202
- fn create ( size : usize ) -> Self {
202
+ fn create ( size : usize , _rng : Option < & mut SmallRng > ) -> Self {
203
203
let mut s = String :: with_capacity ( size) ;
204
204
for _ in 0 ..size {
205
205
s. push ( 'x' ) ;
206
206
}
207
207
s
208
208
}
209
- fn sample ( & self , size : usize ) -> Box < Self :: Item > {
209
+ fn sample ( & self , size : usize , _rng : Option < & mut SmallRng > ) -> Box < Self :: Item > {
210
210
Box :: new ( self [ 0 ..size] . into ( ) )
211
211
}
212
212
}
@@ -215,10 +215,10 @@ impl Template<String> for String {
215
215
impl Template < Vec < usize > > for Vec < usize > {
216
216
type Item = Vec < usize > ;
217
217
218
- fn create ( size : usize ) -> Self {
218
+ fn create ( size : usize , _rng : Option < & mut SmallRng > ) -> Self {
219
219
Vec :: from_iter ( 0 ..size)
220
220
}
221
- fn sample ( & self , size : usize ) -> Box < Self :: Item > {
221
+ fn sample ( & self , size : usize , _rng : Option < & mut SmallRng > ) -> Box < Self :: Item > {
222
222
Box :: new ( self [ 0 ..size] . into ( ) )
223
223
}
224
224
}
@@ -227,15 +227,15 @@ impl Template<Vec<usize>> for Vec<usize> {
227
227
impl Template < HashMap < String , String > > for HashMap < String , String > {
228
228
type Item = Self ;
229
229
230
- fn create ( size : usize ) -> Self {
230
+ fn create ( size : usize , _rng : Option < & mut SmallRng > ) -> Self {
231
231
let mut map = HashMap :: new ( ) ;
232
232
for i in 0 ..size {
233
233
map. insert ( format ! ( "key{}" , i) , format ! ( "value{}" , i) ) ;
234
234
}
235
235
map
236
236
}
237
237
238
- fn sample ( & self , size : usize ) -> Box < Self :: Item > {
238
+ fn sample ( & self , size : usize , _rng : Option < & mut SmallRng > ) -> Box < Self :: Item > {
239
239
Box :: new ( HashMap :: from_iter (
240
240
self . iter ( )
241
241
. take ( size)
@@ -246,16 +246,18 @@ impl Template<HashMap<String, String>> for HashMap<String, String> {
246
246
247
247
type ValueMap = MapMeasure < String , q:: Value > ;
248
248
249
- /// Template for testing roughly a GraphQL response, i.e., a `BTreeMap<String, Value>`
250
- impl Template < ValueMap > for ValueMap {
251
- type Item = ValueMap ;
252
-
253
- fn create ( size : usize ) -> Self {
249
+ impl ValueMap {
250
+ fn make_map ( size : usize , mut rng : Option < & mut SmallRng > ) -> Self {
254
251
let mut map = BTreeMap :: new ( ) ;
255
252
let modulus = if * NESTED_MAP { 9 } else { 8 } ;
256
253
257
254
for i in 0 ..size {
258
- let value = match i % modulus {
255
+ let kind = rng
256
+ . as_deref_mut ( )
257
+ . map ( |rng| rng. gen_range ( 0 , modulus) )
258
+ . unwrap_or ( i % modulus) ;
259
+
260
+ let value = match kind {
259
261
0 => q:: Value :: Boolean ( i % 11 > 5 ) ,
260
262
1 => q:: Value :: Int ( ( i as i32 ) . into ( ) ) ,
261
263
2 => q:: Value :: Null ,
@@ -276,42 +278,72 @@ impl Template<ValueMap> for ValueMap {
276
278
}
277
279
_ => unreachable ! ( ) ,
278
280
} ;
279
- map. insert ( format ! ( "val{}" , i) , value) ;
281
+
282
+ let key = rng. as_deref_mut ( ) . map ( |rng| rng. gen ( ) ) . unwrap_or ( i) % modulus;
283
+ map. insert ( format ! ( "val{}" , key) , value) ;
280
284
}
281
285
MapMeasure ( map)
282
286
}
287
+ }
283
288
284
- fn sample ( & self , size : usize ) -> Box < Self :: Item > {
285
- Box :: new ( MapMeasure ( BTreeMap :: from_iter (
286
- self . 0
287
- . iter ( )
288
- . take ( size)
289
- . map ( |( k, v) | ( k. to_owned ( ) , v. to_owned ( ) ) ) ,
290
- ) ) )
289
+ /// Template for testing roughly a GraphQL response, i.e., a `BTreeMap<String, Value>`
290
+ impl Template < ValueMap > for ValueMap {
291
+ type Item = ValueMap ;
292
+
293
+ fn create ( size : usize , rng : Option < & mut SmallRng > ) -> Self {
294
+ Self :: make_map ( size, rng)
295
+ }
296
+
297
+ fn sample ( & self , size : usize , rng : Option < & mut SmallRng > ) -> Box < Self :: Item > {
298
+ // If the user specified '--fixed', don't build a new map every call
299
+ // since that can be slow
300
+ if rng. is_none ( ) {
301
+ Box :: new ( MapMeasure ( BTreeMap :: from_iter (
302
+ self . 0
303
+ . iter ( )
304
+ . take ( size)
305
+ . map ( |( k, v) | ( k. to_owned ( ) , v. to_owned ( ) ) ) ,
306
+ ) ) )
307
+ } else {
308
+ Box :: new ( Self :: make_map ( size, rng) )
309
+ }
291
310
}
292
311
}
293
312
294
313
type UsizeMap = MapMeasure < usize , usize > ;
295
314
296
- /// Template for testing roughly a GraphQL response, i.e., a `BTreeMap<String, Value>`
297
- impl Template < UsizeMap > for UsizeMap {
298
- type Item = UsizeMap ;
299
-
300
- fn create ( size : usize ) -> Self {
315
+ impl UsizeMap {
316
+ fn make_map ( size : usize , mut rng : Option < & mut SmallRng > ) -> Self {
301
317
let mut map = BTreeMap :: new ( ) ;
302
318
for i in 0 ..size {
303
- map. insert ( i * 2 , i * 3 ) ;
319
+ let key = rng. as_deref_mut ( ) . map ( |rng| rng. gen ( ) ) . unwrap_or ( 2 * i) ;
320
+ map. insert ( key, i * 3 ) ;
304
321
}
305
322
MapMeasure ( map)
306
323
}
324
+ }
307
325
308
- fn sample ( & self , size : usize ) -> Box < Self :: Item > {
309
- Box :: new ( MapMeasure ( BTreeMap :: from_iter (
310
- self . 0
311
- . iter ( )
312
- . take ( size)
313
- . map ( |( k, v) | ( k. to_owned ( ) , v. to_owned ( ) ) ) ,
314
- ) ) )
326
+ /// Template for testing roughly a GraphQL response, i.e., a `BTreeMap<String, Value>`
327
+ impl Template < UsizeMap > for UsizeMap {
328
+ type Item = UsizeMap ;
329
+
330
+ fn create ( size : usize , rng : Option < & mut SmallRng > ) -> Self {
331
+ Self :: make_map ( size, rng)
332
+ }
333
+
334
+ fn sample ( & self , size : usize , rng : Option < & mut SmallRng > ) -> Box < Self :: Item > {
335
+ // If the user specified '--fixed', don't build a new map every call
336
+ // since that can be slow
337
+ if rng. is_none ( ) {
338
+ Box :: new ( MapMeasure ( BTreeMap :: from_iter (
339
+ self . 0
340
+ . iter ( )
341
+ . take ( size)
342
+ . map ( |( k, v) | ( k. to_owned ( ) , v. to_owned ( ) ) ) ,
343
+ ) ) )
344
+ } else {
345
+ Box :: new ( Self :: make_map ( size, rng) )
346
+ }
315
347
}
316
348
}
317
349
@@ -322,15 +354,15 @@ struct Cacheable<T> {
322
354
}
323
355
324
356
impl < T : Template < T > > Cacheable < T > {
325
- fn new ( size : usize ) -> Self {
357
+ fn new ( size : usize , rng : Option < & mut SmallRng > ) -> Self {
326
358
Cacheable {
327
359
cache : LfuCache :: new ( ) ,
328
- template : T :: create ( size) ,
360
+ template : T :: create ( size, rng ) ,
329
361
}
330
362
}
331
363
332
- fn sample ( & self , size : usize ) -> Box < T :: Item > {
333
- self . template . sample ( size)
364
+ fn sample ( & self , size : usize , rng : Option < & mut SmallRng > ) -> Box < T :: Item > {
365
+ self . template . sample ( size, rng )
334
366
}
335
367
336
368
fn name ( & self ) -> & ' static str {
@@ -361,13 +393,28 @@ struct Opt {
361
393
/// Always use objects of size `--obj-size`
362
394
#[ structopt( short, long) ]
363
395
fixed : bool ,
364
- /// The seed of the random number generator
396
+ /// The seed of the random number generator. A seed of 0 means that all
397
+ /// samples are taken from the same template object, and only differ in
398
+ /// size
365
399
#[ structopt( long) ]
366
400
seed : Option < u64 > ,
367
401
}
368
402
403
+ fn maybe_rng < ' a > ( opt : & ' a Opt , rng : & ' a mut SmallRng ) -> Option < & ' a mut SmallRng > {
404
+ if opt. seed == Some ( 0 ) {
405
+ None
406
+ } else {
407
+ Some ( rng)
408
+ }
409
+ }
410
+
369
411
fn stress < T : Template < T , Item = T > > ( opt : & Opt ) {
370
- let mut cacheable: Cacheable < T > = Cacheable :: new ( opt. obj_size ) ;
412
+ let mut rng = match opt. seed {
413
+ None => SmallRng :: from_entropy ( ) ,
414
+ Some ( seed) => SmallRng :: seed_from_u64 ( seed) ,
415
+ } ;
416
+
417
+ let mut cacheable: Cacheable < T > = Cacheable :: new ( opt. obj_size , maybe_rng ( opt, & mut rng) ) ;
371
418
372
419
println ! ( "type: {}" , cacheable. name( ) ) ;
373
420
println ! (
@@ -377,11 +424,6 @@ fn stress<T: Template<T, Item = T>>(opt: &Opt) {
377
424
opt. cache_size
378
425
) ;
379
426
380
- let mut rng = match opt. seed {
381
- None => SmallRng :: from_entropy ( ) ,
382
- Some ( seed) => SmallRng :: seed_from_u64 ( seed) ,
383
- } ;
384
-
385
427
let base_mem = ALLOCATED . load ( SeqCst ) ;
386
428
let print_mod = opt. niter / opt. print_count + 1 ;
387
429
let mut should_print = true ;
@@ -416,15 +458,15 @@ fn stress<T: Template<T, Item = T>>(opt: &Opt) {
416
458
rng. gen_range ( 0 , opt. obj_size )
417
459
} ;
418
460
let before = ALLOCATED . load ( SeqCst ) ;
419
- let sample = cacheable. sample ( size) ;
461
+ let sample = cacheable. sample ( size, maybe_rng ( opt , & mut rng ) ) ;
420
462
let weight = sample. weight ( ) ;
421
463
let alloc = ALLOCATED . load ( SeqCst ) - before;
422
464
sample_weight += weight;
423
465
sample_alloc += alloc;
424
466
if opt. samples {
425
467
println ! ( "sample: weight {:6} alloc {:6}" , weight, alloc, ) ;
426
468
}
427
- cacheable. cache . insert ( key, * cacheable . sample ( size ) ) ;
469
+ cacheable. cache . insert ( key, * sample) ;
428
470
}
429
471
if sample_alloc == sample_weight {
430
472
println ! (
0 commit comments