@@ -13,7 +13,10 @@ use self::position::Position;
13
13
use crate :: {
14
14
branch:: Branch ,
15
15
collections:: { hash_map:: Entry , HashMap } ,
16
- crypto:: cipher:: { self , Nonce , SecretKey } ,
16
+ crypto:: {
17
+ cipher:: { self , Nonce , SecretKey } ,
18
+ sign:: { Keypair , PublicKey } ,
19
+ } ,
17
20
error:: { Error , Result } ,
18
21
protocol:: {
19
22
Block , BlockContent , BlockId , BlockNonce , Locator , RootNode , SingleBlockPresence ,
@@ -506,10 +509,35 @@ pub(crate) async fn fork(blob_id: BlobId, src_branch: &Branch, dst_branch: &Bran
506
509
load_block_count_hint ( & mut tx, & root_node, blob_id, src_branch. keys ( ) . read ( ) ) . await ?
507
510
} ;
508
511
512
+ struct Batch {
513
+ tx : crate :: store:: WriteTransaction ,
514
+ changeset : Changeset ,
515
+ }
516
+
517
+ impl Batch {
518
+ async fn apply ( self , dst_branch_id : & PublicKey , write_keys : & Keypair ) -> Result < ( ) > {
519
+ let Batch { mut tx, changeset } = self ;
520
+ changeset. apply ( & mut tx, dst_branch_id, write_keys) . await ?;
521
+ tx. commit ( ) . await ?;
522
+ Ok ( ( ) )
523
+ }
524
+ }
525
+
526
+ // Based on some benchmarking it seems that batch values don't hurt the syncing performance too
527
+ // much. https://github.com/equalitie/ouisync/issues/143#issuecomment-1757951167
528
+ let batch_size = 2048 ;
529
+ let mut opt_batch = None ;
530
+
509
531
let locators = Locator :: head ( blob_id) . sequence ( ) . take ( end as usize ) ;
532
+
510
533
for locator in locators {
511
- let mut tx = src_branch. store ( ) . begin_write ( ) . await ?;
512
- let mut changeset = Changeset :: new ( ) ;
534
+ if opt_batch. is_none ( ) {
535
+ let tx = src_branch. store ( ) . begin_write ( ) . await ?;
536
+ let changeset = Changeset :: new ( ) ;
537
+ opt_batch = Some ( Batch { tx, changeset } ) ;
538
+ }
539
+
540
+ let Batch { tx, changeset } = opt_batch. as_mut ( ) . unwrap ( ) ;
513
541
514
542
let encoded_locator = locator. encode ( read_key) ;
515
543
@@ -529,10 +557,15 @@ pub(crate) async fn fork(blob_id: BlobId, src_branch: &Branch, dst_branch: &Bran
529
557
} ;
530
558
531
559
changeset. link_block ( encoded_locator, block_id, block_presence) ;
532
- changeset
533
- . apply ( & mut tx, dst_branch. id ( ) , write_keys)
534
- . await ?;
535
- tx. commit ( ) . await ?;
560
+
561
+ // The `+ 1` is there to not hit on the first run.
562
+ if ( locator. number ( ) + 1 ) % batch_size == 0 {
563
+ opt_batch
564
+ . take ( )
565
+ . unwrap ( )
566
+ . apply ( dst_branch. id ( ) , write_keys)
567
+ . await ?;
568
+ }
536
569
537
570
tracing:: trace!(
538
571
num = locator. number( ) ,
@@ -542,6 +575,10 @@ pub(crate) async fn fork(blob_id: BlobId, src_branch: &Branch, dst_branch: &Bran
542
575
) ;
543
576
}
544
577
578
+ if let Some ( batch) = opt_batch {
579
+ batch. apply ( dst_branch. id ( ) , write_keys) . await ?;
580
+ }
581
+
545
582
Ok ( ( ) )
546
583
}
547
584
0 commit comments