1use std::collections::VecDeque;
23use std::iter::FromIterator;
24
25use columnation::{Columnation, Region};
26use differential_dataflow::consolidation::consolidate_updates;
27use differential_dataflow::difference::Semigroup;
28use differential_dataflow::lattice::Lattice;
29use differential_dataflow::trace::implementations::BatchContainer;
30use differential_dataflow::trace::implementations::merge_batcher::{Extractor, Merger};
31use differential_dataflow::trace::implementations::ord_neu::BuilderInput;
32use timely::container::{ContainerBuilder, DrainContainer, PushInto, SizableContainer};
33use timely::progress::Timestamp;
34use timely::progress::frontier::{Antichain, AntichainRef};
35use timely::{Accountable, PartialOrder};
36
37pub struct ColumnationStack<T: Columnation> {
51 local: Vec<T>,
52 inner: T::InnerRegion,
53}
54
55impl<T: Columnation> ColumnationStack<T> {
56 pub fn with_capacity(capacity: usize) -> Self {
61 Self {
62 local: Vec::with_capacity(capacity),
63 inner: T::InnerRegion::default(),
64 }
65 }
66
67 #[inline(always)]
72 pub fn reserve_items<'a, I>(&mut self, items: I)
73 where
74 I: Iterator<Item = &'a T> + Clone,
75 T: 'a,
76 {
77 self.local.reserve(items.clone().count());
78 self.inner.reserve_items(items);
79 }
80
81 #[inline(always)]
86 pub fn reserve_regions<'a, I>(&mut self, regions: I)
87 where
88 Self: 'a,
89 I: Iterator<Item = &'a Self> + Clone,
90 {
91 self.local
92 .reserve(regions.clone().map(|cs| cs.local.len()).sum());
93 self.inner.reserve_regions(regions.map(|cs| &cs.inner));
94 }
95
96 pub fn copy(&mut self, item: &T) {
100 unsafe {
101 self.local.push(self.inner.copy(item));
102 }
103 }
104
105 pub fn clear(&mut self) {
107 unsafe {
108 self.local.set_len(0);
109 self.inner.clear();
110 }
111 }
112
113 pub fn retain_from<P: FnMut(&T) -> bool>(&mut self, index: usize, mut predicate: P) {
117 let mut write_position = index;
118 for position in index..self.local.len() {
119 if predicate(&self[position]) {
120 self.local.swap(position, write_position);
121 write_position += 1;
122 }
123 }
124 unsafe {
125 self.local.set_len(write_position);
128 }
129 }
130
131 pub unsafe fn local(&mut self) -> &mut [T] {
137 &mut self.local[..]
138 }
139
140 #[inline]
142 pub fn heap_size(&self, mut callback: impl FnMut(usize, usize)) {
143 let size_of = std::mem::size_of::<T>();
144 callback(self.local.len() * size_of, self.local.capacity() * size_of);
145 self.inner.heap_size(callback);
146 }
147
148 #[inline]
150 pub fn summed_heap_size(&self) -> (usize, usize) {
151 let (mut length, mut capacity) = (0, 0);
152 self.heap_size(|len, cap| {
153 length += len;
154 capacity += cap
155 });
156 (length, capacity)
157 }
158
159 #[inline]
161 pub fn len(&self) -> usize {
162 self.local.len()
163 }
164
165 pub fn is_empty(&self) -> bool {
167 self.local.is_empty()
168 }
169
170 #[inline]
172 pub fn capacity(&self) -> usize {
173 self.local.capacity()
174 }
175
176 #[inline]
178 pub fn reserve(&mut self, additional: usize) {
179 self.local.reserve(additional)
180 }
181}
182
183impl<A: Columnation, B: Columnation> ColumnationStack<(A, B)> {
184 pub fn copy_destructured(&mut self, t1: &A, t2: &B) {
186 unsafe {
187 self.local.push(self.inner.copy_destructured(t1, t2));
188 }
189 }
190}
191
192impl<A: Columnation, B: Columnation, C: Columnation> ColumnationStack<(A, B, C)> {
193 pub fn copy_destructured(&mut self, r0: &A, r1: &B, r2: &C) {
195 unsafe {
196 self.local.push(self.inner.copy_destructured(r0, r1, r2));
197 }
198 }
199}
200
201impl<T: Columnation> std::ops::Deref for ColumnationStack<T> {
202 type Target = [T];
203 #[inline(always)]
204 fn deref(&self) -> &Self::Target {
205 &self.local[..]
206 }
207}
208
209impl<T: Columnation> Drop for ColumnationStack<T> {
210 fn drop(&mut self) {
211 self.clear();
212 }
213}
214
215impl<T: Columnation> Default for ColumnationStack<T> {
216 fn default() -> Self {
217 Self {
218 local: Vec::new(),
219 inner: T::InnerRegion::default(),
220 }
221 }
222}
223
224impl<'a, A: 'a + Columnation> FromIterator<&'a A> for ColumnationStack<A> {
225 fn from_iter<I: IntoIterator<Item = &'a A>>(iter: I) -> Self {
226 let iter = iter.into_iter();
227 let mut c = ColumnationStack::<A>::with_capacity(iter.size_hint().0);
228 for element in iter {
229 c.copy(element);
230 }
231 c
232 }
233}
234
235impl<T: Columnation + PartialEq> PartialEq for ColumnationStack<T> {
236 fn eq(&self, other: &Self) -> bool {
237 PartialEq::eq(&self[..], &other[..])
238 }
239}
240
241impl<T: Columnation + Eq> Eq for ColumnationStack<T> {}
242
243impl<T: Columnation + std::fmt::Debug> std::fmt::Debug for ColumnationStack<T> {
244 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245 self[..].fmt(f)
246 }
247}
248
249impl<T: Columnation> Clone for ColumnationStack<T> {
250 fn clone(&self) -> Self {
251 let mut new: Self = Default::default();
252 for item in &self[..] {
253 new.copy(item);
254 }
255 new
256 }
257
258 fn clone_from(&mut self, source: &Self) {
259 self.clear();
260 for item in &source[..] {
261 self.copy(item);
262 }
263 }
264}
265
266impl<T: Columnation> PushInto<T> for ColumnationStack<T> {
267 #[inline]
268 fn push_into(&mut self, item: T) {
269 self.copy(&item);
270 }
271}
272
273impl<T: Columnation> PushInto<&T> for ColumnationStack<T> {
274 #[inline]
275 fn push_into(&mut self, item: &T) {
276 self.copy(item);
277 }
278}
279
280impl<T: Columnation> PushInto<&&T> for ColumnationStack<T> {
281 #[inline]
282 fn push_into(&mut self, item: &&T) {
283 self.copy(*item);
284 }
285}
286
287impl<T: Columnation> Accountable for ColumnationStack<T> {
290 #[inline]
291 fn record_count(&self) -> i64 {
292 i64::try_from(self.local.len()).unwrap()
293 }
294 #[inline]
295 fn is_empty(&self) -> bool {
296 self.local.is_empty()
297 }
298}
299
300impl<T: Columnation> DrainContainer for ColumnationStack<T> {
301 type Item<'a>
302 = &'a T
303 where
304 Self: 'a;
305 type DrainIter<'a>
306 = std::slice::Iter<'a, T>
307 where
308 Self: 'a;
309 #[inline]
310 fn drain(&mut self) -> Self::DrainIter<'_> {
311 (*self).iter()
312 }
313}
314
315impl<T: Columnation> SizableContainer for ColumnationStack<T> {
316 fn at_capacity(&self) -> bool {
317 self.len() == self.capacity()
318 }
319 fn ensure_capacity(&mut self, stash: &mut Option<Self>) {
320 if self.capacity() == 0 {
321 *self = stash.take().unwrap_or_default();
322 self.clear();
323 }
324 let preferred = timely::container::buffer::default_capacity::<T>();
325 if self.capacity() < preferred {
326 self.reserve(preferred - self.capacity());
327 }
328 }
329}
330
331impl<T: Clone + Ord + Columnation + 'static> BatchContainer for ColumnationStack<T> {
332 type Owned = T;
333 type ReadItem<'a> = &'a T;
334
335 #[inline(always)]
336 fn into_owned<'a>(item: Self::ReadItem<'a>) -> Self::Owned {
337 item.clone()
338 }
339 #[inline(always)]
340 fn clone_onto<'a>(item: Self::ReadItem<'a>, other: &mut Self::Owned) {
341 other.clone_from(item);
342 }
343
344 fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b> {
345 item
346 }
347
348 fn push_ref(&mut self, item: Self::ReadItem<'_>) {
349 self.push_into(item)
350 }
351 fn push_own(&mut self, item: &Self::Owned) {
352 self.push_into(item)
353 }
354
355 fn clear(&mut self) {
356 self.clear()
357 }
358
359 fn with_capacity(size: usize) -> Self {
360 Self::with_capacity(size)
361 }
362 fn merge_capacity(cont1: &Self, cont2: &Self) -> Self {
363 let mut new = Self::default();
364 new.reserve_regions(std::iter::once(cont1).chain(std::iter::once(cont2)));
365 new
366 }
367 fn index(&self, index: usize) -> Self::ReadItem<'_> {
368 &self[index]
369 }
370 fn len(&self) -> usize {
371 self[..].len()
372 }
373}
374
375impl<K, V, T, R> BuilderInput<K, V> for ColumnationStack<((K::Owned, V::Owned), T, R)>
376where
377 K: for<'a> BatchContainer<
378 ReadItem<'a>: PartialEq<&'a K::Owned>,
379 Owned: Ord + Columnation + Clone + 'static,
380 >,
381 V: for<'a> BatchContainer<
382 ReadItem<'a>: PartialEq<&'a V::Owned>,
383 Owned: Ord + Columnation + Clone + 'static,
384 >,
385 T: Timestamp + Lattice + Columnation + Clone + 'static,
386 R: Ord + Clone + Semigroup + Columnation + 'static,
387{
388 type Key<'a> = &'a K::Owned;
389 type Val<'a> = &'a V::Owned;
390 type Time = T;
391 type Diff = R;
392
393 fn into_parts<'a>(
394 ((key, val), time, diff): Self::Item<'a>,
395 ) -> (Self::Key<'a>, Self::Val<'a>, Self::Time, Self::Diff) {
396 (key, val, time.clone(), diff.clone())
397 }
398
399 fn key_eq(this: &&K::Owned, other: K::ReadItem<'_>) -> bool {
400 K::reborrow(other) == *this
401 }
402
403 fn val_eq(this: &&V::Owned, other: V::ReadItem<'_>) -> bool {
404 V::reborrow(other) == *this
405 }
406
407 fn key_val_upd_counts(chain: &[Self]) -> (usize, usize, usize) {
408 let mut keys = 0;
409 let mut vals = 0;
410 let mut upds = 0;
411 let mut prev_keyval = None;
412 for link in chain.iter() {
413 for ((key, val), _, _) in link.iter() {
414 if let Some((p_key, p_val)) = prev_keyval {
415 if p_key != key {
416 keys += 1;
417 vals += 1;
418 } else if p_val != val {
419 vals += 1;
420 }
421 } else {
422 keys += 1;
423 vals += 1;
424 }
425 upds += 1;
426 prev_keyval = Some((key, val));
427 }
428 }
429 (keys, vals, upds)
430 }
431}
432
433pub struct ColumnationChunker<T: Columnation> {
444 pending: Vec<T>,
445 ready: VecDeque<ColumnationStack<T>>,
446 empty: Option<ColumnationStack<T>>,
447}
448
449impl<T: Columnation> Default for ColumnationChunker<T> {
450 fn default() -> Self {
451 Self {
452 pending: Vec::default(),
453 ready: VecDeque::default(),
454 empty: None,
455 }
456 }
457}
458
459impl<D, T, R> ColumnationChunker<(D, T, R)>
460where
461 D: Columnation + Ord,
462 T: Columnation + Ord,
463 R: Columnation + Semigroup,
464{
465 const BUFFER_SIZE_BYTES: usize = 64 << 10;
466
467 fn chunk_capacity() -> usize {
468 let size = std::mem::size_of::<(D, T, R)>();
469 if size == 0 {
470 Self::BUFFER_SIZE_BYTES
471 } else if size <= Self::BUFFER_SIZE_BYTES {
472 Self::BUFFER_SIZE_BYTES / size
473 } else {
474 1
475 }
476 }
477
478 fn form_chunk(&mut self) {
479 consolidate_updates(&mut self.pending);
480 if self.pending.len() >= Self::chunk_capacity() {
481 while self.pending.len() > Self::chunk_capacity() {
482 let mut chunk = ColumnationStack::with_capacity(Self::chunk_capacity());
483 for item in self.pending.drain(..chunk.capacity()) {
484 chunk.copy(&item);
485 }
486 self.ready.push_back(chunk);
487 }
488 }
489 }
490}
491
492impl<'a, D, T, R> PushInto<&'a mut Vec<(D, T, R)>> for ColumnationChunker<(D, T, R)>
493where
494 D: Columnation + Ord + Clone,
495 T: Columnation + Ord + Clone,
496 R: Columnation + Semigroup + Clone,
497{
498 fn push_into(&mut self, container: &'a mut Vec<(D, T, R)>) {
499 if self.pending.capacity() < Self::chunk_capacity() * 2 {
500 self.pending
501 .reserve(Self::chunk_capacity() * 2 - self.pending.len());
502 }
503
504 let mut drain = container.drain(..).peekable();
505 while drain.peek().is_some() {
506 self.pending
507 .extend((&mut drain).take(self.pending.capacity() - self.pending.len()));
508 if self.pending.len() == self.pending.capacity() {
509 self.form_chunk();
510 }
511 }
512 }
513}
514
515impl<D, T, R> ContainerBuilder for ColumnationChunker<(D, T, R)>
516where
517 D: Columnation + Ord + Clone + 'static,
518 T: Columnation + Ord + Clone + 'static,
519 R: Columnation + Semigroup + Clone + 'static,
520{
521 type Container = ColumnationStack<(D, T, R)>;
522
523 fn extract(&mut self) -> Option<&mut Self::Container> {
524 if let Some(ready) = self.ready.pop_front() {
525 self.empty = Some(ready);
526 self.empty.as_mut()
527 } else {
528 None
529 }
530 }
531
532 fn finish(&mut self) -> Option<&mut Self::Container> {
533 consolidate_updates(&mut self.pending);
534 while !self.pending.is_empty() {
535 let mut chunk = ColumnationStack::with_capacity(Self::chunk_capacity());
536 for item in self
537 .pending
538 .drain(..std::cmp::min(self.pending.len(), chunk.capacity()))
539 {
540 chunk.copy(&item);
541 }
542 self.ready.push_back(chunk);
543 }
544 self.empty = self.ready.pop_front();
545 self.empty.as_mut()
546 }
547}
548
549pub struct ColInternalMerger<D, T, R> {
561 _marker: std::marker::PhantomData<(D, T, R)>,
562}
563
564impl<D, T, R> Default for ColInternalMerger<D, T, R> {
565 fn default() -> Self {
566 Self {
567 _marker: std::marker::PhantomData,
568 }
569 }
570}
571
572impl<D, T, R> ColInternalMerger<D, T, R>
573where
574 D: Ord + Columnation + Clone + 'static,
575 T: Ord + Columnation + Clone + PartialOrder + 'static,
576 R: Default + Semigroup + Columnation + Clone + 'static,
577{
578 fn chunk_capacity() -> usize {
580 const BUFFER_SIZE_BYTES: usize = 64 << 10;
581 let size = std::mem::size_of::<(D, T, R)>();
582 if size == 0 {
583 BUFFER_SIZE_BYTES
584 } else if size <= BUFFER_SIZE_BYTES {
585 BUFFER_SIZE_BYTES / size
586 } else {
587 1
588 }
589 }
590
591 fn empty(stash: &mut Vec<ColumnationStack<(D, T, R)>>) -> ColumnationStack<(D, T, R)> {
593 let target = Self::chunk_capacity();
594 match stash.pop() {
595 Some(mut chunk) if chunk.capacity() >= target => {
596 chunk.clear();
597 chunk
598 }
599 _ => ColumnationStack::with_capacity(target),
600 }
601 }
602
603 fn recycle(
605 mut chunk: ColumnationStack<(D, T, R)>,
606 stash: &mut Vec<ColumnationStack<(D, T, R)>>,
607 ) {
608 chunk.clear();
609 stash.push(chunk);
610 }
611
612 fn drain_side(
618 head: &mut ColumnationStack<(D, T, R)>,
619 pos: &mut usize,
620 list: &mut std::vec::IntoIter<ColumnationStack<(D, T, R)>>,
621 result: &mut ColumnationStack<(D, T, R)>,
622 output: &mut Vec<ColumnationStack<(D, T, R)>>,
623 stash: &mut Vec<ColumnationStack<(D, T, R)>>,
624 ) {
625 if *pos < head[..].len() {
627 if result.is_empty() && *pos == 0 {
628 std::mem::swap(result, head);
629 } else {
630 for i in *pos..head[..].len() {
631 result.copy(&head[i]);
632 }
633 }
634 *pos = head[..].len();
635 }
636 if !result.is_empty() {
638 output.push(std::mem::replace(result, Self::empty(stash)));
639 }
640 output.extend(list);
642 }
643}
644
645impl<D, T, R> Merger for ColInternalMerger<D, T, R>
646where
647 D: Ord + Columnation + Clone + 'static,
648 T: Ord + Columnation + Clone + PartialOrder + 'static,
649 R: Default + Semigroup + Columnation + Clone + 'static,
650{
651 type Chunk = ColumnationStack<(D, T, R)>;
652
653 fn merge(
654 &mut self,
655 list1: Vec<Self::Chunk>,
656 list2: Vec<Self::Chunk>,
657 output: &mut Vec<Self::Chunk>,
658 stash: &mut Vec<Self::Chunk>,
659 ) {
660 use std::cmp::Ordering;
661
662 let mut list1 = list1.into_iter();
663 let mut list2 = list2.into_iter();
664 let mut head1 = list1.next().unwrap_or_default();
665 let mut head2 = list2.next().unwrap_or_default();
666 let mut pos1 = 0;
667 let mut pos2 = 0;
668 let mut result = Self::empty(stash);
669 let mut diff = R::default();
670
671 while pos1 < head1[..].len() && pos2 < head2[..].len() {
673 while pos1 < head1[..].len() && pos2 < head2[..].len() && !result.at_capacity() {
675 let (d1, t1, r1) = &head1[pos1];
676 let (d2, t2, r2) = &head2[pos2];
677 match (d1, t1).cmp(&(d2, t2)) {
678 Ordering::Less => {
679 result.copy(&head1[pos1]);
680 pos1 += 1;
681 }
682 Ordering::Greater => {
683 result.copy(&head2[pos2]);
684 pos2 += 1;
685 }
686 Ordering::Equal => {
687 diff.clone_from(r1);
688 diff.plus_equals(r2);
689 if !diff.is_zero() {
690 result.copy_destructured(d1, t1, &diff);
691 }
692 pos1 += 1;
693 pos2 += 1;
694 }
695 }
696 }
697 if result.at_capacity() {
698 output.push(std::mem::replace(&mut result, Self::empty(stash)));
699 }
700 if pos1 >= head1[..].len() {
701 let old = std::mem::replace(&mut head1, list1.next().unwrap_or_default());
702 Self::recycle(old, stash);
703 pos1 = 0;
704 }
705 if pos2 >= head2[..].len() {
706 let old = std::mem::replace(&mut head2, list2.next().unwrap_or_default());
707 Self::recycle(old, stash);
708 pos2 = 0;
709 }
710 }
711
712 Self::drain_side(
716 &mut head1,
717 &mut pos1,
718 &mut list1,
719 &mut result,
720 output,
721 stash,
722 );
723 Self::drain_side(
724 &mut head2,
725 &mut pos2,
726 &mut list2,
727 &mut result,
728 output,
729 stash,
730 );
731
732 if !result.is_empty() {
733 output.push(result);
734 }
735 }
736
737 fn len(chunk: &Self::Chunk) -> usize {
738 chunk[..].len()
739 }
740
741 fn allocation(chunk: &Self::Chunk) -> (usize, usize, usize) {
742 let (mut size, mut capacity, mut allocations) = (0, 0, 0);
743 chunk.heap_size(|siz, cap| {
744 size += siz;
745 capacity += cap;
746 allocations += 1;
747 });
748 (size, capacity, allocations)
749 }
750}
751
752impl<D, T, R> Extractor for ColInternalMerger<D, T, R>
753where
754 D: Ord + Columnation + Clone + 'static,
755 T: Ord + Columnation + Clone + PartialOrder + 'static,
756 R: Default + Semigroup + Columnation + Clone + 'static,
757{
758 type Time = T;
759
760 fn extract(
761 &mut self,
762 merged: Vec<Self::Chunk>,
763 upper: AntichainRef<T>,
764 frontier: &mut Antichain<T>,
765 readied: &mut Vec<Self::Chunk>,
766 kept: &mut Vec<Self::Chunk>,
767 stash: &mut Vec<Self::Chunk>,
768 ) {
769 let mut keep = Self::empty(stash);
770 let mut ready = Self::empty(stash);
771
772 for chunk in merged {
773 let len = chunk[..].len();
774 for i in 0..len {
775 let (data, time, diff) = &chunk[i];
776 if upper.less_equal(time) {
777 frontier.insert_with(time, |time| time.clone());
778 keep.copy_destructured(data, time, diff);
779 } else {
780 ready.copy_destructured(data, time, diff);
781 }
782 if keep.at_capacity() {
783 kept.push(std::mem::replace(&mut keep, Self::empty(stash)));
784 }
785 if ready.at_capacity() {
786 readied.push(std::mem::replace(&mut ready, Self::empty(stash)));
787 }
788 }
789 Self::recycle(chunk, stash);
791 }
792
793 if !keep.is_empty() {
794 kept.push(keep);
795 }
796 if !ready.is_empty() {
797 readied.push(ready);
798 }
799 }
800}