@@ -9,12 +9,20 @@ use smallvec::SmallVec;
9
9
use crate :: errors:: Error ;
10
10
use crate :: errors:: SBSError ;
11
11
12
- use crate :: inversion_tree:: InversionTree ;
13
12
use crate :: matrix:: Matrix ;
14
13
14
+ use lru:: LruCache ;
15
+
16
+ #[ cfg( feature = "std" ) ]
17
+ use parking_lot:: Mutex ;
18
+ #[ cfg( not( feature = "std" ) ) ]
19
+ use spin:: Mutex ;
20
+
15
21
use super :: Field ;
16
22
use super :: ReconstructShard ;
17
23
24
+ const DATA_DECODE_MATRIX_CACHE_CAPACITY : usize = 254 ;
25
+
18
26
// /// Parameters for parallelism.
19
27
// #[derive(PartialEq, Debug, Clone, Copy)]
20
28
// pub struct ParallelParam {
@@ -338,7 +346,7 @@ pub struct ReedSolomon<F: Field> {
338
346
parity_shard_count : usize ,
339
347
total_shard_count : usize ,
340
348
matrix : Matrix < F > ,
341
- tree : InversionTree < F > ,
349
+ data_decode_matrix_cache : Mutex < LruCache < Vec < usize > , Arc < Matrix < F > > > > ,
342
350
}
343
351
344
352
impl < F : Field > Clone for ReedSolomon < F > {
@@ -454,7 +462,7 @@ impl<F: Field> ReedSolomon<F> {
454
462
parity_shard_count : parity_shards,
455
463
total_shard_count : total_shards,
456
464
matrix,
457
- tree : InversionTree :: new ( data_shards , parity_shards ) ,
465
+ data_decode_matrix_cache : Mutex :: new ( LruCache :: new ( DATA_DECODE_MATRIX_CACHE_CAPACITY ) ) ,
458
466
} )
459
467
}
460
468
@@ -691,40 +699,35 @@ impl<F: Field> ReedSolomon<F> {
691
699
valid_indices : & [ usize ] ,
692
700
invalid_indices : & [ usize ] ,
693
701
) -> Arc < Matrix < F > > {
694
- // Attempt to get the cached inverted matrix out of the tree
695
- // based on the indices of the invalid rows.
696
- match self . tree . get_inverted_matrix ( & invalid_indices) {
697
- // If the inverted matrix isn't cached in the tree yet we must
698
- // construct it ourselves and insert it into the tree for the
699
- // future. In this way the inversion tree is lazily loaded.
700
- None => {
701
- // Pull out the rows of the matrix that correspond to the
702
- // shards that we have and build a square matrix. This
703
- // matrix could be used to generate the shards that we have
704
- // from the original data.
705
- let mut sub_matrix = Matrix :: new ( self . data_shard_count , self . data_shard_count ) ;
706
- for ( sub_matrix_row, & valid_index) in valid_indices. iter ( ) . enumerate ( ) {
707
- for c in 0 ..self . data_shard_count {
708
- sub_matrix. set ( sub_matrix_row, c, self . matrix . get ( valid_index, c) ) ;
709
- }
710
- }
711
- // Invert the matrix, so we can go from the encoded shards
712
- // back to the original data. Then pull out the row that
713
- // generates the shard that we want to decode. Note that
714
- // since this matrix maps back to the original data, it can
715
- // be used to create a data shard, but not a parity shard.
716
- let data_decode_matrix = Arc :: new ( sub_matrix. invert ( ) . unwrap ( ) ) ;
717
-
718
- // Cache the inverted matrix in the tree for future use keyed on the
719
- // indices of the invalid rows.
720
- self . tree
721
- . insert_inverted_matrix ( & invalid_indices, & data_decode_matrix)
722
- . unwrap ( ) ;
723
-
724
- data_decode_matrix
702
+ {
703
+ let mut cache = self . data_decode_matrix_cache . lock ( ) ;
704
+ if let Some ( entry) = cache. get ( invalid_indices) {
705
+ return entry. clone ( ) ;
706
+ }
707
+ }
708
+ // Pull out the rows of the matrix that correspond to the shards that
709
+ // we have and build a square matrix. This matrix could be used to
710
+ // generate the shards that we have from the original data.
711
+ let mut sub_matrix = Matrix :: new ( self . data_shard_count , self . data_shard_count ) ;
712
+ for ( sub_matrix_row, & valid_index) in valid_indices. iter ( ) . enumerate ( ) {
713
+ for c in 0 ..self . data_shard_count {
714
+ sub_matrix. set ( sub_matrix_row, c, self . matrix . get ( valid_index, c) ) ;
725
715
}
726
- Some ( m) => m,
727
716
}
717
+ // Invert the matrix, so we can go from the encoded shards back to the
718
+ // original data. Then pull out the row that generates the shard that
719
+ // we want to decode. Note that since this matrix maps back to the
720
+ // original data, it can be used to create a data shard, but not a
721
+ // parity shard.
722
+ let data_decode_matrix = Arc :: new ( sub_matrix. invert ( ) . unwrap ( ) ) ;
723
+ // Cache the inverted matrix for future use keyed on the indices of the
724
+ // invalid rows.
725
+ {
726
+ let data_decode_matrix = data_decode_matrix. clone ( ) ;
727
+ let mut cache = self . data_decode_matrix_cache . lock ( ) ;
728
+ cache. put ( Vec :: from ( invalid_indices) , data_decode_matrix) ;
729
+ }
730
+ data_decode_matrix
728
731
}
729
732
730
733
fn reconstruct_internal < T : ReconstructShard < F > > (
@@ -780,7 +783,7 @@ impl<F: Field> ReedSolomon<F> {
780
783
//
781
784
// The valid indices are used to construct the data decode matrix,
782
785
// the invalid indices are used to key the data decode matrix
783
- // in the inversion tree .
786
+ // in the data decode matrix cache .
784
787
//
785
788
// We only need exactly N valid indices, where N = `data_shard_count`,
786
789
// as the data decode matrix is a N x N matrix, thus only needs
0 commit comments