80
80
81
81
use crate :: irep:: { Irep , IrepId , Symbol , SymbolTable } ;
82
82
use crate :: { InternString , InternedString } ;
83
+ #[ cfg( not( test) ) ]
84
+ use fxhash:: FxHashMap ;
85
+ #[ cfg( test) ]
83
86
use std:: collections:: HashMap ;
84
87
use std:: fs:: File ;
85
88
use std:: hash:: Hash ;
@@ -199,7 +202,28 @@ impl IrepNumberingInv {
199
202
}
200
203
}
201
204
205
+ #[ cfg( not( test) ) ]
206
+ /// A numbering of [InternedString], [IrepId] and [Irep] based on their contents.
207
+ /// Note that using [FxHashMap] makes our caches faster, but we still have to use
208
+ /// the default [HashMap] in a test context as only it implements the
209
+ /// `memuse::DynamicUsage` trait we need for memory profiling under test.
210
+ struct IrepNumbering {
211
+ /// Map from [InternedString] to their unique numbers.
212
+ string_cache : FxHashMap < InternedString , usize > ,
213
+
214
+ /// Inverse string cache.
215
+ inv_string_cache : Vec < NumberedString > ,
216
+
217
+ /// Map from [IrepKey] to their unique numbers.
218
+ cache : FxHashMap < IrepKey , usize > ,
219
+
220
+ /// Inverse cache, allows to get a NumberedIrep from its unique number.
221
+ inv_cache : IrepNumberingInv ,
222
+ }
223
+
224
+ #[ cfg( test) ]
202
225
/// A numbering of [InternedString], [IrepId] and [Irep] based on their contents.
226
+ /// See above for explanation of why this definition is only used in a test context.
203
227
struct IrepNumbering {
204
228
/// Map from [InternedString] to their unique numbers.
205
229
string_cache : HashMap < InternedString , usize > ,
@@ -214,16 +238,31 @@ struct IrepNumbering {
214
238
inv_cache : IrepNumberingInv ,
215
239
}
216
240
241
+ #[ cfg( not( test) ) ]
217
242
impl IrepNumbering {
218
243
fn new ( ) -> Self {
219
244
IrepNumbering {
220
- string_cache : HashMap :: new ( ) ,
245
+ string_cache : FxHashMap :: default ( ) ,
221
246
inv_string_cache : Vec :: new ( ) ,
222
- cache : HashMap :: new ( ) ,
247
+ cache : FxHashMap :: default ( ) ,
223
248
inv_cache : IrepNumberingInv :: new ( ) ,
224
249
}
225
250
}
251
+ }
226
252
253
+ #[ cfg( test) ]
254
+ impl IrepNumbering {
255
+ fn new ( ) -> Self {
256
+ IrepNumbering {
257
+ string_cache : HashMap :: default ( ) ,
258
+ inv_string_cache : Vec :: new ( ) ,
259
+ cache : HashMap :: default ( ) ,
260
+ inv_cache : IrepNumberingInv :: new ( ) ,
261
+ }
262
+ }
263
+ }
264
+
265
+ impl IrepNumbering {
227
266
/// Returns a [NumberedString] from its number if it exists, None otherwise.
228
267
fn numbered_string_from_number ( & mut self , string_number : usize ) -> Option < NumberedString > {
229
268
self . inv_string_cache . get ( string_number) . copied ( )
@@ -248,7 +287,7 @@ impl IrepNumbering {
248
287
/// Turns a [IrepId] to a [NumberedString]. The [IrepId] gets the number of its
249
288
/// string representation.
250
289
fn number_irep_id ( & mut self , irep_id : & IrepId ) -> NumberedString {
251
- self . number_string ( & irep_id. to_string ( ) . intern ( ) )
290
+ self . number_string ( & irep_id. to_string_cow ( ) . intern ( ) )
252
291
}
253
292
254
293
/// Turns an [Irep] into a [NumberedIrep]. The [Irep] is recursively traversed
@@ -264,20 +303,18 @@ impl IrepNumbering {
264
303
. map ( |( key, value) | ( self . number_irep_id ( key) . number , self . number_irep ( value) . number ) )
265
304
. collect ( ) ;
266
305
let key = IrepKey :: new ( id, & sub, & named_sub) ;
267
- self . get_or_insert ( & key)
306
+ self . get_or_insert ( key)
268
307
}
269
308
270
309
/// Gets the existing [NumberedIrep] from the [IrepKey] or inserts a fresh
271
310
/// one and returns it.
272
- fn get_or_insert ( & mut self , key : & IrepKey ) -> NumberedIrep {
273
- if let Some ( number) = self . cache . get ( key) {
274
- // Return the NumberedIrep from the inverse cache
275
- return self . inv_cache . index [ * number] ;
276
- }
277
- // This is where the key gets its unique number assigned.
278
- let number = self . inv_cache . add_key ( key) ;
279
- self . cache . insert ( key. clone ( ) , number) ;
280
- self . inv_cache . index [ number]
311
+ fn get_or_insert ( & mut self , key : IrepKey ) -> NumberedIrep {
312
+ let number = self . cache . entry ( key) . or_insert_with_key ( |key| {
313
+ // This is where the key gets its unique number assigned.
314
+ self . inv_cache . add_key ( key)
315
+ } ) ;
316
+
317
+ self . inv_cache . index [ * number]
281
318
}
282
319
283
320
/// Returns the unique number of the `id` field of the given [NumberedIrep].
@@ -794,7 +831,7 @@ where
794
831
let key = IrepKey :: new ( id, & sub, & named_sub) ;
795
832
796
833
// Insert key in the numbering
797
- let numbered = self . numbering . get_or_insert ( & key) ;
834
+ let numbered = self . numbering . get_or_insert ( key) ;
798
835
799
836
// Map number from the binary to new number
800
837
self . add_irep_mapping ( irep_number, numbered. number ) ;
0 commit comments