@@ -9,7 +9,6 @@ use crate::hot::{
99 tables,
1010} ;
1111use alloy:: primitives:: { Address , B256 , BlockNumber , U256 } ;
12- use itertools:: Itertools ;
1312use reth:: {
1413 primitives:: { Account , Header , SealedHeader } ,
1514 revm:: db:: BundleState ,
@@ -310,13 +309,15 @@ pub trait UnsafeHistoryWrite: UnsafeDbWrite + HistoryRead {
310309 // Get the existing last shard (if any) and remember its key so we can
311310 // delete it before writing new shards
312311 let existing = self . last_account_history ( acct) ?;
313- let mut last_shard =
314- existing. as_ref ( ) . map ( |( _, list) | list. clone ( ) ) . unwrap_or_default ( ) ;
312+ // Save the old key before taking ownership of the list
313+ let old_key = existing. as_ref ( ) . map ( |( key, _) | * key) ;
314+ // Take ownership instead of cloning
315+ let mut last_shard = existing. map ( |( _, list) | list) . unwrap_or_default ( ) ;
315316
316317 last_shard. append ( indices) . map_err ( HistoryError :: IntList ) ?;
317318
318319 // Delete the existing shard before writing new ones to avoid duplicates
319- if let Some ( ( old_key, _ ) ) = existing {
320+ if let Some ( old_key) = old_key {
320321 self . queue_delete_dual :: < tables:: AccountsHistory > ( & acct, & old_key) ?;
321322 }
322323
@@ -327,19 +328,22 @@ pub trait UnsafeHistoryWrite: UnsafeDbWrite + HistoryRead {
327328 }
328329
329330 // slow path: rechunk into multiple shards
330- let chunks = last_shard. iter ( ) . chunks ( sharded_key:: NUM_OF_INDICES_IN_SHARD ) ;
331+ // Reuse a single buffer to avoid allocating a new Vec per chunk
332+ let mut chunk_buf = Vec :: with_capacity ( sharded_key:: NUM_OF_INDICES_IN_SHARD ) ;
333+ let mut iter = last_shard. iter ( ) . peekable ( ) ;
331334
332- let mut chunks = chunks. into_iter ( ) . peekable ( ) ;
335+ while iter. peek ( ) . is_some ( ) {
336+ chunk_buf. clear ( ) ;
337+ chunk_buf. extend ( iter. by_ref ( ) . take ( sharded_key:: NUM_OF_INDICES_IN_SHARD ) ) ;
333338
334- while let Some ( chunk) = chunks. next ( ) {
335- let shard = BlockNumberList :: new_pre_sorted ( chunk) ;
336- let highest_block_number = if chunks. peek ( ) . is_some ( ) {
337- shard. iter ( ) . next_back ( ) . expect ( "`chunks` does not return empty list" )
339+ let highest_block_number = if iter. peek ( ) . is_some ( ) {
340+ * chunk_buf. last ( ) . expect ( "chunk_buf is non-empty" )
338341 } else {
339342 // Insert last list with `u64::MAX`.
340343 u64:: MAX
341344 } ;
342345
346+ let shard = BlockNumberList :: new_pre_sorted ( chunk_buf. iter ( ) . copied ( ) ) ;
343347 self . write_account_history ( & acct, highest_block_number, & shard) ?;
344348 }
345349 }
@@ -382,13 +386,15 @@ pub trait UnsafeHistoryWrite: UnsafeDbWrite + HistoryRead {
382386 // Get the existing last shard (if any) and remember its key so we can
383387 // delete it before writing new shards
384388 let existing = self . last_storage_history ( & addr, & slot) ?;
385- let mut last_shard =
386- existing. as_ref ( ) . map ( |( _, list) | list. clone ( ) ) . unwrap_or_default ( ) ;
389+ // Save the old key before taking ownership of the list (clone is cheap for ShardedKey)
390+ let old_key = existing. as_ref ( ) . map ( |( key, _) | key. clone ( ) ) ;
391+ // Take ownership instead of cloning the BlockNumberList
392+ let mut last_shard = existing. map ( |( _, list) | list) . unwrap_or_default ( ) ;
387393
388394 last_shard. append ( indices) . map_err ( HistoryError :: IntList ) ?;
389395
390396 // Delete the existing shard before writing new ones to avoid duplicates
391- if let Some ( ( old_key, _ ) ) = existing {
397+ if let Some ( old_key) = old_key {
392398 self . queue_delete_dual :: < tables:: StorageHistory > ( & addr, & old_key) ?;
393399 }
394400
@@ -399,19 +405,22 @@ pub trait UnsafeHistoryWrite: UnsafeDbWrite + HistoryRead {
399405 }
400406
401407 // slow path: rechunk into multiple shards
402- let chunks = last_shard. iter ( ) . chunks ( sharded_key:: NUM_OF_INDICES_IN_SHARD ) ;
408+ // Reuse a single buffer to avoid allocating a new Vec per chunk
409+ let mut chunk_buf = Vec :: with_capacity ( sharded_key:: NUM_OF_INDICES_IN_SHARD ) ;
410+ let mut iter = last_shard. iter ( ) . peekable ( ) ;
403411
404- let mut chunks = chunks. into_iter ( ) . peekable ( ) ;
412+ while iter. peek ( ) . is_some ( ) {
413+ chunk_buf. clear ( ) ;
414+ chunk_buf. extend ( iter. by_ref ( ) . take ( sharded_key:: NUM_OF_INDICES_IN_SHARD ) ) ;
405415
406- while let Some ( chunk) = chunks. next ( ) {
407- let shard = BlockNumberList :: new_pre_sorted ( chunk) ;
408- let highest_block_number = if chunks. peek ( ) . is_some ( ) {
409- shard. iter ( ) . next_back ( ) . expect ( "`chunks` does not return empty list" )
416+ let highest_block_number = if iter. peek ( ) . is_some ( ) {
417+ * chunk_buf. last ( ) . expect ( "chunk_buf is non-empty" )
410418 } else {
411419 // Insert last list with `u64::MAX`.
412420 u64:: MAX
413421 } ;
414422
423+ let shard = BlockNumberList :: new_pre_sorted ( chunk_buf. iter ( ) . copied ( ) ) ;
415424 self . write_storage_history ( & addr, slot, highest_block_number, & shard) ?;
416425 }
417426 }
0 commit comments