@@ -2529,8 +2529,11 @@ impl QwpWsSizeHint {
25292529 }
25302530
25312531 fn len ( & mut self , tables : & [ QwpWsTableBuffer ] ) -> usize {
2532- let dirty_tables = std:: mem:: take ( & mut self . dirty_tables ) ;
2533- for table_idx in dirty_tables {
2532+ // Preserve the dirty-index allocation across size queries. Taking and
2533+ // dropping this vector allocated once per row after every buffer clear,
2534+ // even though the buffer itself is explicitly reusable.
2535+ let mut dirty_tables = std:: mem:: take ( & mut self . dirty_tables ) ;
2536+ for table_idx in dirty_tables. drain ( ..) {
25342537 if table_idx >= tables. len ( ) || table_idx >= self . tables . len ( ) {
25352538 continue ;
25362539 }
@@ -2548,6 +2551,8 @@ impl QwpWsSizeHint {
25482551 self . recomputed_tables += 1 ;
25492552 }
25502553 }
2554+ debug_assert ! ( dirty_tables. is_empty( ) ) ;
2555+ self . dirty_tables = dirty_tables;
25512556
25522557 QWP_MESSAGE_HEADER_SIZE
25532558 + 2
@@ -2847,6 +2852,15 @@ impl QwpWsColumnarBuffer {
28472852 . recomputed_tables
28482853 }
28492854
2855+ #[ cfg( test) ]
2856+ fn size_hint_dirty_capacity ( & self ) -> usize {
2857+ self . size_hint
2858+ . lock ( )
2859+ . unwrap_or_else ( |poisoned| poisoned. into_inner ( ) )
2860+ . dirty_tables
2861+ . capacity ( )
2862+ }
2863+
28502864 pub ( crate ) fn row_count ( & self ) -> usize {
28512865 self . state . row_count
28522866 }
@@ -10111,6 +10125,33 @@ mod tests {
1011110125 assert_eq ! ( buf. size_hint_recomputed_tables( ) , recomputed + 1 ) ;
1011210126 }
1011310127
10128+ #[ cfg( feature = "_sender-qwp-ws" ) ]
10129+ #[ test]
10130+ fn qwp_ws_cached_size_hint_retains_dirty_index_capacity ( ) {
10131+ let mut buf = QwpWsColumnarBuffer :: new ( 127 ) ;
10132+ buf. table ( "trades" )
10133+ . unwrap ( )
10134+ . column_i64 ( "value" , 1 )
10135+ . unwrap ( )
10136+ . at_now ( )
10137+ . unwrap ( ) ;
10138+ let _ = buf. len ( ) ;
10139+ let capacity = buf. size_hint_dirty_capacity ( ) ;
10140+ assert ! ( capacity >= 1 ) ;
10141+
10142+ for value in 2 ..=10 {
10143+ buf. clear ( ) ;
10144+ buf. table ( "trades" )
10145+ . unwrap ( )
10146+ . column_i64 ( "value" , value)
10147+ . unwrap ( )
10148+ . at_now ( )
10149+ . unwrap ( ) ;
10150+ let _ = buf. len ( ) ;
10151+ assert_eq ! ( buf. size_hint_dirty_capacity( ) , capacity) ;
10152+ }
10153+ }
10154+
1011410155 #[ cfg( feature = "_sender-qwp-ws" ) ]
1011510156 #[ test]
1011610157 fn qwp_ws_columnar_clear_bookmark_drops_only_current_snapshot ( ) {
0 commit comments