@@ -8,6 +8,7 @@ use std::io::{Read, Seek, SeekFrom, Write};
8
8
9
9
use crate :: frames:: UnresolvedFrames ;
10
10
11
+ use aligned_vec:: AVec ;
11
12
use tempfile:: NamedTempFile ;
12
13
13
14
pub const BUCKETS : usize = 1 << 12 ;
@@ -148,6 +149,7 @@ pub struct TempFdArray<T: 'static> {
148
149
file : NamedTempFile ,
149
150
buffer : Box < [ T ; BUFFER_LENGTH ] > ,
150
151
buffer_index : usize ,
152
+ flush_n : usize ,
151
153
}
152
154
153
155
impl < T : Default + Debug > TempFdArray < T > {
@@ -162,6 +164,7 @@ impl<T: Default + Debug> TempFdArray<T> {
162
164
file,
163
165
buffer,
164
166
buffer_index : 0 ,
167
+ flush_n : 0 ,
165
168
} )
166
169
}
167
170
}
@@ -175,6 +178,7 @@ impl<T> TempFdArray<T> {
175
178
BUFFER_LENGTH * std:: mem:: size_of :: < T > ( ) ,
176
179
)
177
180
} ;
181
+ self . flush_n += 1 ;
178
182
self . file . write_all ( buf) ?;
179
183
180
184
Ok ( ( ) )
@@ -192,10 +196,16 @@ impl<T> TempFdArray<T> {
192
196
}
193
197
194
198
fn try_iter ( & self ) -> std:: io:: Result < impl Iterator < Item = & T > > {
195
- let mut file_vec = Vec :: new ( ) ;
199
+ let size = BUFFER_LENGTH * self . flush_n * std:: mem:: size_of :: < T > ( ) ;
200
+
201
+ let mut file_vec = AVec :: with_capacity ( std:: mem:: align_of :: < T > ( ) , size) ;
196
202
let mut file = self . file . reopen ( ) ?;
197
- file. seek ( SeekFrom :: Start ( 0 ) ) ?;
198
- file. read_to_end ( & mut file_vec) ?;
203
+
204
+ unsafe {
205
+ // it's safe as the capacity is initialized to `size`, and it'll be filled with `size` bytes
206
+ file_vec. set_len ( size) ;
207
+ }
208
+ file. read_exact ( & mut file_vec[ 0 ..size] ) ?;
199
209
file. seek ( SeekFrom :: End ( 0 ) ) ?;
200
210
201
211
Ok ( TempFdArrayIterator {
@@ -208,7 +218,7 @@ impl<T> TempFdArray<T> {
208
218
209
219
pub struct TempFdArrayIterator < ' a , T > {
210
220
pub buffer : & ' a [ T ] ,
211
- pub file_vec : Vec < u8 > ,
221
+ pub file_vec : AVec < u8 > ,
212
222
pub index : usize ,
213
223
}
214
224
@@ -266,7 +276,7 @@ mod test_utils {
266
276
use super :: * ;
267
277
use std:: collections:: BTreeMap ;
268
278
269
- pub fn add_map ( hashmap : & mut BTreeMap < usize , isize > , entry : & Entry < usize > ) {
279
+ pub fn add_map < T : std :: cmp :: Ord + Copy > ( hashmap : & mut BTreeMap < T , isize > , entry : & Entry < T > ) {
270
280
match hashmap. get_mut ( & entry. item ) {
271
281
None => {
272
282
hashmap. insert ( entry. item , entry. count ) ;
@@ -359,4 +369,57 @@ mod tests {
359
369
}
360
370
}
361
371
}
372
+
373
+ #[ derive( Debug , Hash , Eq , PartialEq , PartialOrd , Ord , Default , Clone , Copy ) ]
374
+ struct AlignTest {
375
+ a : u16 ,
376
+ b : u32 ,
377
+ c : u64 ,
378
+ d : u64 ,
379
+ }
380
+
381
+ // collector_align_test uses a bigger item to test the alignment of the collector
382
+ #[ test]
383
+ fn collector_align_test ( ) {
384
+ let mut collector = Collector :: new ( ) . unwrap ( ) ;
385
+ let mut real_map = BTreeMap :: new ( ) ;
386
+
387
+ for item in 0 ..( 1 << 12 ) * 4 {
388
+ for _ in 0 ..( item % 4 ) {
389
+ collector
390
+ . add (
391
+ AlignTest {
392
+ a : item as u16 ,
393
+ b : item as u32 ,
394
+ c : item as u64 ,
395
+ d : item as u64 ,
396
+ } ,
397
+ 1 ,
398
+ )
399
+ . unwrap ( ) ;
400
+ }
401
+ }
402
+
403
+ collector. try_iter ( ) . unwrap ( ) . for_each ( |entry| {
404
+ test_utils:: add_map ( & mut real_map, entry) ;
405
+ } ) ;
406
+
407
+ for item in 0 ..( 1 << 12 ) * 4 {
408
+ let count = ( item % 4 ) as isize ;
409
+ let align_item = AlignTest {
410
+ a : item as u16 ,
411
+ b : item as u32 ,
412
+ c : item as u64 ,
413
+ d : item as u64 ,
414
+ } ;
415
+ match real_map. get ( & align_item) {
416
+ Some ( value) => {
417
+ assert_eq ! ( count, * value) ;
418
+ }
419
+ None => {
420
+ assert_eq ! ( count, 0 ) ;
421
+ }
422
+ }
423
+ }
424
+ }
362
425
}
0 commit comments