1
1
use std:: cmp:: Ordering ;
2
2
#[ cfg( feature = "legacy" ) ]
3
3
use std:: fs:: File ;
4
+ #[ cfg( feature = "prefetching" ) ]
5
+ use std:: intrinsics;
4
6
use std:: io;
5
7
use std:: ops:: Range ;
6
8
use std:: path:: Path ;
@@ -155,6 +157,7 @@ impl<T: Clone + DeserializeOwned + Serialize> BFieldMember<T> {
155
157
}
156
158
}
157
159
160
+ #[ inline]
158
161
pub fn get ( & self , key : & [ u8 ] ) -> BFieldLookup {
159
162
let k = u32:: from ( self . params . n_marker_bits ) ;
160
163
let putative_marker = self . get_raw ( key, k) ;
@@ -169,13 +172,29 @@ impl<T: Clone + DeserializeOwned + Serialize> BFieldMember<T> {
169
172
fn get_raw ( & self , key : & [ u8 ] , k : u32 ) -> BitVecSlice {
170
173
let marker_width = self . params . marker_width as usize ;
171
174
let hash = murmurhash3_x64_128 ( key, 0 ) ;
172
-
173
175
let mut merged_marker = BitVecSlice :: max_value ( ) ;
176
+ let mut positions: [ usize ; 16 ] = [ 0 ; 16 ] ; // support up to 16 hashes
174
177
for marker_ix in 0usize ..self . params . n_hashes as usize {
175
178
let pos = marker_pos ( hash, marker_ix, self . bitvec . size ( ) , marker_width) ;
176
- let marker = get_range ( & self . bitvec , pos..pos + marker_width) ;
179
+ positions[ marker_ix] = pos;
180
+
181
+ // pre-fetch the memory!
182
+ if cfg ! ( feature = "prefetching" ) {
183
+ unsafe {
184
+ let byte_idx_st = ( pos >> 3 ) as usize ;
185
+ let ptr: * const u8 = self . bitvec . mmap . as_ptr ( ) . offset ( byte_idx_st as isize ) ;
186
+ #[ cfg( feature = "prefetching" ) ]
187
+ intrinsics:: prefetch_read_data ( ptr, 3 ) ;
188
+ }
189
+ }
190
+ }
191
+
192
+ assert ! ( self . params. n_hashes <= 16 ) ;
193
+ for marker_ix in 0usize ..self . params . n_hashes as usize {
194
+ let pos = positions[ marker_ix] ;
195
+ let marker = self . bitvec . get_range ( pos..pos + marker_width) ;
177
196
merged_marker &= marker;
178
- if merged_marker. count_ones ( ) . cmp ( & k ) == Ordering :: Less {
197
+ if merged_marker. count_ones ( ) < k {
179
198
return 0 ;
180
199
}
181
200
}
@@ -226,50 +245,6 @@ fn marker_pos(hash: (u64, u64), n: usize, total_size: usize, _: usize) -> usize
226
245
i64:: abs ( mashed_hash % ( total_size as i64 - 64 ) ) as usize
227
246
}
228
247
229
- /// This is totally messed up, but we get a speed bump by doing this
230
- /// instead of using the _exact same_ function on the struct.
231
- #[ cfg( not( feature = "legacy" ) ) ]
232
- fn get_range ( bitvec : & MmapBitVec , r : Range < usize > ) -> BitVecSlice {
233
- if r. end - r. start > BIT_VEC_SLICE_SIZE as usize {
234
- panic ! ( format!( "Range too large (>{})" , BIT_VEC_SLICE_SIZE ) )
235
- } else if r. end > bitvec. size {
236
- panic ! ( "Range ends outside of BitVec" )
237
- }
238
- let byte_idx_st = ( r. start >> 3 ) as usize ;
239
- let byte_idx_en = ( ( r. end - 1 ) >> 3 ) as usize ;
240
- let new_size: u8 = ( r. end - r. start ) as u8 ;
241
-
242
- let mut v;
243
- let ptr: * const u8 = bitvec. mmap . as_ptr ( ) ;
244
-
245
- // read the last byte first
246
- unsafe {
247
- v = BitVecSlice :: from ( * ptr. offset ( byte_idx_en as isize ) ) ;
248
- }
249
- // align the end of the data with the end of the u64/u128
250
- v >>= 7 - ( ( r. end - 1 ) & 7 ) ;
251
-
252
- let bit_offset = new_size + ( r. start & 7 ) as u8 ;
253
- // copy over byte by byte
254
- // it would be faster to coerce into a u8 and a u64 (in case it spans 9 bytes) and then
255
- // copy over, but this doesn't work if the start is <8 bytes from the end, so we're doing
256
- // this for now and we can add a special case for that later
257
- for ( new_idx, old_idx) in ( byte_idx_st..byte_idx_en) . enumerate ( ) {
258
- unsafe {
259
- v |= BitVecSlice :: from ( * ptr. offset ( old_idx as isize ) ) <<
260
- ( bit_offset - 8u8 * ( new_idx as u8 + 1 ) ) ;
261
- }
262
- }
263
-
264
- // mask out the high bits in case we copied extra
265
- v & BitVecSlice :: max_value ( ) >> ( BIT_VEC_SLICE_SIZE - new_size)
266
- }
267
-
268
- #[ cfg( feature = "legacy" ) ]
269
- fn get_range ( bitvec : & MmapBitVec , r : Range < usize > ) -> BitVecSlice {
270
- bitvec. get_range ( r)
271
- }
272
-
273
248
#[ test]
274
249
fn test_bfield ( ) {
275
250
let mut bfield: BFieldMember < usize > = BFieldMember :: in_memory ( 1024 , 3 , 64 , 4 ) . unwrap ( ) ;
0 commit comments