1use crate::Row;
27use std::cell::RefCell;
28
29const POOL_SIZE: usize = 16;
33
34const MAX_CACHED_CAPACITY: usize = 64_000;
38
39thread_local! {
41 static ROW_VEC_POOL: RefCell<Vec<Vec<(i64, Row)>>> = const { RefCell::new(Vec::new()) };
42}
43
44#[inline]
47pub fn clear_row_vec_pool() {
48 ROW_VEC_POOL.with(|pool| {
49 if let Ok(mut p) = pool.try_borrow_mut() {
50 p.clear();
51 }
52 });
53}
54
55#[cfg(feature = "dhat-heap")]
61#[derive(Debug, Default)]
62pub struct PoolStats {
63 pub hits: u64,
65 pub misses: u64,
67 pub returns: u64,
69 pub evictions: u64,
71 pub oversized_discards: u64,
73 pub bytes_requested: u64,
75 pub bytes_from_pool: u64,
77 pub current_pool_size: usize,
79 pub total_pool_capacity: usize,
81}
82
83#[cfg(feature = "dhat-heap")]
84impl PoolStats {
85 pub fn hit_rate(&self) -> f64 {
87 let total = self.hits + self.misses;
88 if total == 0 {
89 0.0
90 } else {
91 (self.hits as f64 / total as f64) * 100.0
92 }
93 }
94
95 pub fn bytes_saved(&self) -> u64 {
97 self.bytes_from_pool
98 }
99}
100
101#[cfg(feature = "dhat-heap")]
102impl std::fmt::Display for PoolStats {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 writeln!(f, "RowVec Pool Statistics:")?;
105 writeln!(f, " Hits: {:>10}", self.hits)?;
106 writeln!(f, " Misses: {:>10}", self.misses)?;
107 writeln!(f, " Hit Rate: {:>9.1}%", self.hit_rate())?;
108 writeln!(f, " Returns: {:>10}", self.returns)?;
109 writeln!(f, " Evictions: {:>10}", self.evictions)?;
110 writeln!(f, " Oversized Discards:{:>10}", self.oversized_discards)?;
111 writeln!(
112 f,
113 " Bytes Requested: {:>10}",
114 format_bytes(self.bytes_requested)
115 )?;
116 writeln!(
117 f,
118 " Bytes From Pool: {:>10}",
119 format_bytes(self.bytes_from_pool)
120 )?;
121 writeln!(
122 f,
123 " Bytes Saved: {:>10}",
124 format_bytes(self.bytes_saved())
125 )?;
126 writeln!(f, " Current Pool Size: {:>10}", self.current_pool_size)?;
127 writeln!(
128 f,
129 " Pool Capacity: {:>10}",
130 format_bytes(self.total_pool_capacity as u64 * 16)
131 )?;
132 Ok(())
133 }
134}
135
136#[cfg(feature = "dhat-heap")]
137fn format_bytes(bytes: u64) -> String {
138 if bytes >= 1_073_741_824 {
139 format!("{:.2} GB", bytes as f64 / 1_073_741_824.0)
140 } else if bytes >= 1_048_576 {
141 format!("{:.2} MB", bytes as f64 / 1_048_576.0)
142 } else if bytes >= 1024 {
143 format!("{:.2} KB", bytes as f64 / 1024.0)
144 } else {
145 format!("{} B", bytes)
146 }
147}
148
149#[cfg(feature = "dhat-heap")]
150thread_local! {
151 static POOL_STATS: RefCell<PoolStats> = RefCell::new(PoolStats::default());
152}
153
154#[cfg(feature = "dhat-heap")]
156pub fn get_pool_stats() -> PoolStats {
157 POOL_STATS.with(|stats| {
158 let mut s = stats.borrow().clone();
159 ROW_VEC_POOL.with(|pool| {
161 let pool = pool.borrow();
162 s.current_pool_size = pool.len();
163 s.total_pool_capacity = pool.iter().map(|v| v.capacity()).sum();
164 });
165 s
166 })
167}
168
169#[cfg(feature = "dhat-heap")]
171pub fn print_pool_stats() {
172 eprintln!("{}", get_pool_stats());
173}
174
175#[cfg(feature = "dhat-heap")]
177pub fn reset_pool_stats() {
178 POOL_STATS.with(|stats| {
179 *stats.borrow_mut() = PoolStats::default();
180 });
181}
182
183#[cfg(feature = "dhat-heap")]
184impl Clone for PoolStats {
185 fn clone(&self) -> Self {
186 Self {
187 hits: self.hits,
188 misses: self.misses,
189 returns: self.returns,
190 evictions: self.evictions,
191 oversized_discards: self.oversized_discards,
192 bytes_requested: self.bytes_requested,
193 bytes_from_pool: self.bytes_from_pool,
194 current_pool_size: self.current_pool_size,
195 total_pool_capacity: self.total_pool_capacity,
196 }
197 }
198}
199
200#[cfg(feature = "dhat-heap")]
202macro_rules! track_hit {
203 ($capacity:expr) => {
204 POOL_STATS.with(|stats| {
205 let mut s = stats.borrow_mut();
206 s.hits += 1;
207 s.bytes_from_pool += ($capacity as u64) * 16;
208 });
209 };
210}
211
212#[cfg(not(feature = "dhat-heap"))]
213macro_rules! track_hit {
214 ($capacity:expr) => {};
215}
216
217#[cfg(feature = "dhat-heap")]
218macro_rules! track_miss {
219 ($capacity:expr) => {
220 POOL_STATS.with(|stats| {
221 let mut s = stats.borrow_mut();
222 s.misses += 1;
223 s.bytes_requested += ($capacity as u64) * 16;
224 });
225 };
226}
227
228#[cfg(not(feature = "dhat-heap"))]
229macro_rules! track_miss {
230 ($capacity:expr) => {};
231}
232
233#[cfg(feature = "dhat-heap")]
234macro_rules! track_return {
235 () => {
236 POOL_STATS.with(|stats| {
237 stats.borrow_mut().returns += 1;
238 });
239 };
240}
241
242#[cfg(not(feature = "dhat-heap"))]
243macro_rules! track_return {
244 () => {};
245}
246
247#[cfg(feature = "dhat-heap")]
248macro_rules! track_eviction {
249 () => {
250 POOL_STATS.with(|stats| {
251 stats.borrow_mut().evictions += 1;
252 });
253 };
254}
255
256#[cfg(not(feature = "dhat-heap"))]
257macro_rules! track_eviction {
258 () => {};
259}
260
261#[cfg(feature = "dhat-heap")]
262macro_rules! track_oversized {
263 () => {
264 POOL_STATS.with(|stats| {
265 stats.borrow_mut().oversized_discards += 1;
266 });
267 };
268}
269
270#[cfg(not(feature = "dhat-heap"))]
271macro_rules! track_oversized {
272 () => {};
273}
274
275#[derive(Debug)]
280pub struct RowVec {
281 inner: Option<Vec<(i64, Row)>>,
282}
283
284impl RowVec {
285 #[inline]
288 pub fn new() -> Self {
289 let v = ROW_VEC_POOL.with(|pool| pool.try_borrow_mut().ok().and_then(|mut p| p.pop()));
292 match v {
293 Some(buf) => {
294 track_hit!(buf.capacity());
295 Self { inner: Some(buf) }
296 }
297 None => {
298 track_miss!(16);
299 Self {
300 inner: Some(Vec::with_capacity(16)),
301 }
302 }
303 }
304 }
305
306 #[inline]
309 pub fn with_capacity(capacity: usize) -> Self {
310 let v = ROW_VEC_POOL.with(|pool| {
312 let mut pool = match pool.try_borrow_mut() {
313 Ok(p) => p,
314 Err(_) => return None, };
316 if pool.is_empty() {
317 return None;
318 }
319 let idx = pool.partition_point(|b| b.capacity() < capacity);
322 if idx < pool.len() {
323 Some(pool.remove(idx))
325 } else {
326 pool.pop()
328 }
329 });
330
331 match v {
332 Some(mut buf) => {
333 let buf_cap = buf.capacity();
334 if buf_cap >= capacity {
335 track_hit!(buf_cap);
337 } else {
338 track_hit!(buf_cap);
340 buf.reserve_exact(capacity - buf.len());
341 }
342 Self { inner: Some(buf) }
343 }
344 None => {
345 track_miss!(capacity);
346 Self {
347 inner: Some(Vec::with_capacity(capacity)),
348 }
349 }
350 }
351 }
352
353 #[inline]
357 pub fn from_vec(v: Vec<(i64, Row)>) -> Self {
358 Self { inner: Some(v) }
359 }
360
361 #[inline]
365 pub fn into_vec(mut self) -> Vec<(i64, Row)> {
366 self.inner.take().unwrap_or_default()
367 }
368
369 #[inline]
371 pub fn len(&self) -> usize {
372 self.inner.as_ref().map(|v| v.len()).unwrap_or(0)
373 }
374
375 #[inline]
377 pub fn is_empty(&self) -> bool {
378 self.len() == 0
379 }
380
381 #[inline]
383 pub fn push(&mut self, item: (i64, Row)) {
384 if let Some(v) = self.inner.as_mut() {
385 v.push(item);
386 }
387 }
388
389 #[inline]
391 pub fn clear(&mut self) {
392 if let Some(v) = self.inner.as_mut() {
393 v.clear();
394 }
395 }
396
397 #[inline]
399 pub fn iter(&self) -> impl Iterator<Item = &(i64, Row)> {
400 self.inner.as_ref().unwrap().iter()
401 }
402
403 #[inline]
405 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut (i64, Row)> {
406 self.inner.as_mut().unwrap().iter_mut()
407 }
408
409 #[inline]
411 pub fn get(&self, index: usize) -> Option<&(i64, Row)> {
412 self.inner.as_ref().and_then(|v| v.get(index))
413 }
414
415 #[inline]
418 pub fn drain_rows(&mut self) -> impl Iterator<Item = Row> + '_ {
419 self.inner.as_mut().unwrap().drain(..).map(|(_, row)| row)
420 }
421
422 #[inline]
424 pub fn rows(&self) -> impl Iterator<Item = &Row> {
425 self.inner.as_ref().unwrap().iter().map(|(_, row)| row)
426 }
427}
428
429impl Default for RowVec {
430 fn default() -> Self {
431 Self::new()
432 }
433}
434
435impl Clone for RowVec {
436 fn clone(&self) -> Self {
437 let mut cloned = RowVec::with_capacity(self.len());
438 for (id, row) in self.inner.as_ref().unwrap().iter() {
439 cloned.push((*id, row.clone()));
440 }
441 cloned
442 }
443}
444
445impl std::ops::Deref for RowVec {
446 type Target = Vec<(i64, Row)>;
447
448 #[inline]
449 fn deref(&self) -> &Self::Target {
450 self.inner.as_ref().unwrap()
451 }
452}
453
454impl std::ops::DerefMut for RowVec {
455 #[inline]
456 fn deref_mut(&mut self) -> &mut Self::Target {
457 self.inner.as_mut().unwrap()
458 }
459}
460
461impl Drop for RowVec {
462 #[inline]
463 fn drop(&mut self) {
464 if let Some(mut v) = self.inner.take() {
465 let cap = v.capacity();
466 if cap > MAX_CACHED_CAPACITY {
468 track_oversized!();
469 return; }
471 v.clear();
472 ROW_VEC_POOL.with(|pool| {
473 let mut pool = match pool.try_borrow_mut() {
475 Ok(p) => p,
476 Err(_) => return, };
478 if pool.len() < POOL_SIZE {
479 let insert_idx = pool.partition_point(|b| b.capacity() < cap);
481 pool.insert(insert_idx, v);
482 track_return!();
483 } else {
484 if !pool.is_empty() && pool[0].capacity() < cap {
487 pool.remove(0);
489 let insert_idx = pool.partition_point(|b| b.capacity() < cap);
490 pool.insert(insert_idx, v);
491 track_return!();
492 track_eviction!();
493 }
494 }
496 });
497 }
498 }
499}
500
501impl std::ops::Index<usize> for RowVec {
502 type Output = (i64, Row);
503
504 #[inline]
505 fn index(&self, index: usize) -> &Self::Output {
506 &self.inner.as_ref().unwrap()[index]
507 }
508}
509
510impl std::ops::IndexMut<usize> for RowVec {
511 #[inline]
512 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
513 &mut self.inner.as_mut().unwrap()[index]
514 }
515}
516
517pub struct RowVecIter {
520 inner: std::mem::ManuallyDrop<RowVec>,
521 front: usize,
522 back: usize,
523}
524
525impl Iterator for RowVecIter {
526 type Item = (i64, Row);
527
528 #[inline]
529 fn next(&mut self) -> Option<Self::Item> {
530 if self.front >= self.back {
531 return None;
532 }
533 let vec = self.inner.inner.as_ref()?;
534 let item = unsafe { std::ptr::read(vec.as_ptr().add(self.front)) };
537 self.front += 1;
538 Some(item)
539 }
540
541 #[inline]
542 fn size_hint(&self) -> (usize, Option<usize>) {
543 let len = self.back.saturating_sub(self.front);
544 (len, Some(len))
545 }
546}
547
548impl DoubleEndedIterator for RowVecIter {
549 #[inline]
550 fn next_back(&mut self) -> Option<Self::Item> {
551 if self.front >= self.back {
552 return None;
553 }
554 self.back -= 1;
555 let vec = self.inner.inner.as_ref()?;
556 let item = unsafe { std::ptr::read(vec.as_ptr().add(self.back)) };
558 Some(item)
559 }
560}
561
562impl ExactSizeIterator for RowVecIter {}
563
564impl Drop for RowVecIter {
565 fn drop(&mut self) {
566 if let Some(vec) = self.inner.inner.as_mut() {
568 for i in self.front..self.back {
569 unsafe {
572 std::ptr::drop_in_place(vec.as_mut_ptr().add(i));
573 }
574 }
575 unsafe {
578 vec.set_len(0);
579 }
580 }
581 unsafe {
584 std::mem::ManuallyDrop::drop(&mut self.inner);
585 }
586 }
587}
588
589impl IntoIterator for RowVec {
590 type Item = (i64, Row);
591 type IntoIter = RowVecIter;
592
593 #[inline]
594 fn into_iter(self) -> Self::IntoIter {
595 let len = self.len();
596 RowVecIter {
597 inner: std::mem::ManuallyDrop::new(self),
598 front: 0,
599 back: len,
600 }
601 }
602}
603
604impl<'a> IntoIterator for &'a RowVec {
605 type Item = &'a (i64, Row);
606 type IntoIter = std::slice::Iter<'a, (i64, Row)>;
607
608 #[inline]
609 fn into_iter(self) -> Self::IntoIter {
610 self.inner.as_ref().unwrap().iter()
611 }
612}
613
614impl<'a> IntoIterator for &'a mut RowVec {
615 type Item = &'a mut (i64, Row);
616 type IntoIter = std::slice::IterMut<'a, (i64, Row)>;
617
618 #[inline]
619 fn into_iter(self) -> Self::IntoIter {
620 self.inner.as_mut().unwrap().iter_mut()
621 }
622}
623
624impl FromIterator<(i64, Row)> for RowVec {
626 fn from_iter<I: IntoIterator<Item = (i64, Row)>>(iter: I) -> Self {
627 let iter = iter.into_iter();
628 let (lower, upper) = iter.size_hint();
629 let capacity = upper.unwrap_or(lower).max(16);
631 let mut rv = RowVec::with_capacity(capacity);
632 for item in iter {
633 rv.push(item);
634 }
635 rv
636 }
637}
638
639const ROW_ID_MAX_CACHED_CAPACITY: usize = 256_000;
646
647const ROW_ID_POOL_SIZE: usize = 16;
649
650thread_local! {
652 static ROW_ID_VEC_POOL: RefCell<Vec<Vec<i64>>> = const { RefCell::new(Vec::new()) };
653}
654
655#[inline]
658pub fn clear_row_id_vec_pool() {
659 ROW_ID_VEC_POOL.with(|pool| {
660 if let Ok(mut p) = pool.try_borrow_mut() {
661 p.clear();
662 }
663 });
664}
665
666#[derive(Debug)]
671pub struct RowIdVec {
672 inner: Option<Vec<i64>>,
673}
674
675impl RowIdVec {
676 #[inline]
679 pub fn new() -> Self {
680 let v = ROW_ID_VEC_POOL.with(|pool| pool.try_borrow_mut().ok().and_then(|mut p| p.pop()));
681 match v {
682 Some(buf) => Self { inner: Some(buf) },
683 None => Self {
684 inner: Some(Vec::with_capacity(16)),
685 },
686 }
687 }
688
689 #[inline]
692 pub fn with_capacity(capacity: usize) -> Self {
693 let v = ROW_ID_VEC_POOL.with(|pool| {
694 let mut pool = match pool.try_borrow_mut() {
695 Ok(p) => p,
696 Err(_) => return None,
697 };
698 if pool.is_empty() {
699 return None;
700 }
701 let idx = pool.partition_point(|b| b.capacity() < capacity);
703 if idx < pool.len() {
704 Some(pool.remove(idx))
706 } else {
707 pool.pop()
709 }
710 });
711
712 match v {
713 Some(mut buf) => {
714 let buf_cap = buf.capacity();
715 if buf_cap < capacity {
716 buf.reserve_exact(capacity - buf.len());
718 }
719 Self { inner: Some(buf) }
720 }
721 None => Self {
722 inner: Some(Vec::with_capacity(capacity)),
723 },
724 }
725 }
726
727 #[inline]
730 pub fn from_vec(v: Vec<i64>) -> Self {
731 Self { inner: Some(v) }
732 }
733
734 #[inline]
738 pub fn into_vec(mut self) -> Vec<i64> {
739 self.inner.take().unwrap_or_default()
740 }
741
742 #[inline]
744 pub fn len(&self) -> usize {
745 self.inner.as_ref().map(|v| v.len()).unwrap_or(0)
746 }
747
748 #[inline]
750 pub fn is_empty(&self) -> bool {
751 self.len() == 0
752 }
753
754 #[inline]
756 pub fn push(&mut self, item: i64) {
757 if let Some(v) = self.inner.as_mut() {
758 v.push(item);
759 }
760 }
761
762 #[inline]
764 pub fn extend<I: IntoIterator<Item = i64>>(&mut self, iter: I) {
765 if let Some(v) = self.inner.as_mut() {
766 v.extend(iter);
767 }
768 }
769
770 #[inline]
772 pub fn clear(&mut self) {
773 if let Some(v) = self.inner.as_mut() {
774 v.clear();
775 }
776 }
777
778 #[inline]
780 pub fn iter(&self) -> impl Iterator<Item = &i64> {
781 self.inner.as_ref().unwrap().iter()
782 }
783
784 #[inline]
786 pub fn reserve(&mut self, additional: usize) {
787 if let Some(v) = self.inner.as_mut() {
788 v.reserve(additional);
789 }
790 }
791
792 #[inline]
794 pub fn sort(&mut self) {
795 if let Some(v) = self.inner.as_mut() {
796 v.sort_unstable();
797 }
798 }
799
800 #[inline]
802 pub fn dedup(&mut self) {
803 if let Some(v) = self.inner.as_mut() {
804 v.dedup();
805 }
806 }
807}
808
809impl Default for RowIdVec {
810 fn default() -> Self {
811 Self::new()
812 }
813}
814
815impl Clone for RowIdVec {
816 fn clone(&self) -> Self {
817 let mut cloned = RowIdVec::with_capacity(self.len());
818 if let Some(v) = self.inner.as_ref() {
819 cloned.extend(v.iter().copied());
820 }
821 cloned
822 }
823}
824
825impl std::ops::Deref for RowIdVec {
826 type Target = Vec<i64>;
827
828 #[inline]
829 fn deref(&self) -> &Self::Target {
830 self.inner.as_ref().unwrap()
831 }
832}
833
834impl std::ops::DerefMut for RowIdVec {
835 #[inline]
836 fn deref_mut(&mut self) -> &mut Self::Target {
837 self.inner.as_mut().unwrap()
838 }
839}
840
841impl Drop for RowIdVec {
842 #[inline]
843 fn drop(&mut self) {
844 if let Some(mut v) = self.inner.take() {
845 let cap = v.capacity();
846 if cap > ROW_ID_MAX_CACHED_CAPACITY {
848 return; }
850 v.clear();
851 ROW_ID_VEC_POOL.with(|pool| {
852 let mut pool = match pool.try_borrow_mut() {
853 Ok(p) => p,
854 Err(_) => return,
855 };
856 if pool.len() < ROW_ID_POOL_SIZE {
857 let insert_idx = pool.partition_point(|b| b.capacity() < cap);
859 pool.insert(insert_idx, v);
860 } else {
861 if !pool.is_empty() && pool[0].capacity() < cap {
864 pool.remove(0);
866 let insert_idx = pool.partition_point(|b| b.capacity() < cap);
867 pool.insert(insert_idx, v);
868 }
869 }
871 });
872 }
873 }
874}
875
876impl<'a> IntoIterator for &'a RowIdVec {
877 type Item = &'a i64;
878 type IntoIter = std::slice::Iter<'a, i64>;
879
880 #[inline]
881 fn into_iter(self) -> Self::IntoIter {
882 self.inner.as_ref().unwrap().iter()
883 }
884}
885
886pub struct RowIdVecIntoIter {
892 inner: std::vec::IntoIter<i64>,
893}
894
895impl Iterator for RowIdVecIntoIter {
896 type Item = i64;
897
898 #[inline]
899 fn next(&mut self) -> Option<Self::Item> {
900 self.inner.next()
901 }
902
903 #[inline]
904 fn size_hint(&self) -> (usize, Option<usize>) {
905 self.inner.size_hint()
906 }
907}
908
909impl ExactSizeIterator for RowIdVecIntoIter {}
910
911impl IntoIterator for RowIdVec {
912 type Item = i64;
913 type IntoIter = RowIdVecIntoIter;
914
915 #[inline]
916 fn into_iter(mut self) -> Self::IntoIter {
917 let v = self.inner.take().unwrap_or_default();
918 RowIdVecIntoIter {
919 inner: v.into_iter(),
920 }
921 }
922}
923
924impl FromIterator<i64> for RowIdVec {
926 fn from_iter<I: IntoIterator<Item = i64>>(iter: I) -> Self {
927 let iter = iter.into_iter();
928 let (lower, upper) = iter.size_hint();
929 let capacity = upper.unwrap_or(lower).max(16);
930 let mut rv = RowIdVec::with_capacity(capacity);
931 for item in iter {
932 rv.push(item);
933 }
934 rv
935 }
936}
937
938#[cfg(test)]
939mod tests {
940 use super::*;
941 use crate::Value;
942
943 #[test]
944 fn test_row_vec_basic() {
945 let mut rv = RowVec::new();
946 rv.push((1, Row::from_values(vec![Value::Integer(1)])));
947 rv.push((2, Row::from_values(vec![Value::Integer(2)])));
948
949 assert_eq!(rv.len(), 2);
950 assert!(!rv.is_empty());
951 }
952
953 #[test]
954 fn test_row_vec_cache_reuse() {
955 {
957 let mut rv = RowVec::with_capacity(100);
958 rv.push((1, Row::from_values(vec![Value::Integer(1)])));
959 }
961
962 let rv2 = RowVec::new();
964 assert!(
965 rv2.capacity() >= 100,
966 "Expected capacity >= 100, got {}",
967 rv2.capacity()
968 );
969 }
970
971 #[test]
972 fn test_reused_buffers_guarantee_adjacent_requested_capacity() {
973 clear_row_vec_pool();
974 clear_row_id_vec_pool();
975
976 {
977 let row_vec = RowVec::with_capacity(16);
978 assert_eq!(row_vec.capacity(), 16);
979 }
980 let row_vec = RowVec::with_capacity(17);
981 assert!(row_vec.capacity() >= 17);
982
983 {
984 let row_ids = RowIdVec::with_capacity(16);
985 assert_eq!(row_ids.capacity(), 16);
986 }
987 let row_ids = RowIdVec::with_capacity(17);
988 assert!(row_ids.capacity() >= 17);
989 }
990
991 #[test]
992 fn test_row_vec_into_iter() {
993 let mut rv = RowVec::new();
994 rv.push((1, Row::from_values(vec![Value::Integer(1)])));
995 rv.push((2, Row::from_values(vec![Value::Integer(2)])));
996
997 let collected: Vec<_> = rv.into_iter().collect();
998 assert_eq!(collected.len(), 2);
999 assert_eq!(collected[0].0, 1);
1001 assert_eq!(collected[1].0, 2);
1002 }
1003
1004 #[test]
1005 fn test_row_vec_rev() {
1006 let mut rv = RowVec::new();
1007 rv.push((1, Row::from_values(vec![Value::Integer(1)])));
1008 rv.push((2, Row::from_values(vec![Value::Integer(2)])));
1009 rv.push((3, Row::from_values(vec![Value::Integer(3)])));
1010
1011 let collected: Vec<_> = rv.into_iter().rev().collect();
1013 assert_eq!(collected.len(), 3);
1014 assert_eq!(collected[0].0, 3); assert_eq!(collected[1].0, 2);
1016 assert_eq!(collected[2].0, 1); }
1018
1019 #[test]
1020 fn test_row_vec_skip_take_rev() {
1021 let mut rv = RowVec::new();
1022 for i in 1..=10 {
1023 rv.push((i, Row::from_values(vec![Value::Integer(i)])));
1024 }
1025
1026 let collected: Vec<_> = rv.into_iter().rev().skip(2).take(3).collect();
1028 assert_eq!(collected.len(), 3);
1029 assert_eq!(collected[0].0, 8); assert_eq!(collected[1].0, 7);
1031 assert_eq!(collected[2].0, 6);
1032 }
1033
1034 #[test]
1035 fn test_row_vec_pool_keeps_buffers() {
1036 {
1038 let mut rv = RowVec::with_capacity(500);
1039 rv.push((1, Row::from_values(vec![Value::Integer(1)])));
1040 }
1042
1043 let rv2 = RowVec::new();
1045 assert!(
1046 rv2.capacity() >= 16, "Expected capacity >= 16, got {}",
1048 rv2.capacity()
1049 );
1050 }
1051
1052 #[test]
1053 fn test_row_vec_pool_respects_max_capacity() {
1054 {
1057 let mut rv = RowVec::with_capacity(MAX_CACHED_CAPACITY + 1000);
1058 rv.push((1, Row::from_values(vec![Value::Integer(1)])));
1059 }
1061
1062 let rv2 = RowVec::with_capacity(16);
1065 assert!(
1066 rv2.capacity() < MAX_CACHED_CAPACITY,
1067 "Expected small capacity, got {}",
1068 rv2.capacity()
1069 );
1070 }
1071
1072 #[test]
1073 fn test_row_vec_pool_concurrent_usage() {
1074 let mut rv1 = RowVec::with_capacity(100);
1077 let mut rv2 = RowVec::with_capacity(200);
1078 let mut rv3 = RowVec::with_capacity(300);
1079 rv1.push((1, Row::from_values(vec![Value::Integer(1)])));
1080 rv2.push((2, Row::from_values(vec![Value::Integer(2)])));
1081 rv3.push((3, Row::from_values(vec![Value::Integer(3)])));
1082
1083 assert!(
1085 rv1.capacity() >= 100,
1086 "rv1 capacity {} < 100",
1087 rv1.capacity()
1088 );
1089 assert!(
1090 rv2.capacity() >= 200,
1091 "rv2 capacity {} < 200",
1092 rv2.capacity()
1093 );
1094 assert!(
1095 rv3.capacity() >= 300,
1096 "rv3 capacity {} < 300",
1097 rv3.capacity()
1098 );
1099
1100 drop(rv1);
1102 drop(rv2);
1103 drop(rv3);
1104
1105 let rv_a = RowVec::new();
1107 let rv_b = RowVec::new();
1108 let rv_c = RowVec::new();
1109
1110 assert!(
1113 rv_a.capacity() >= 16,
1114 "rv_a capacity {} < 16",
1115 rv_a.capacity()
1116 );
1117 assert!(
1118 rv_b.capacity() >= 16,
1119 "rv_b capacity {} < 16",
1120 rv_b.capacity()
1121 );
1122 assert!(
1123 rv_c.capacity() >= 16,
1124 "rv_c capacity {} < 16",
1125 rv_c.capacity()
1126 );
1127 }
1128}