Two-Stack Sliding-Window Aggregation

(orlp.net)

70 points | by surprisetalk 2 days ago

6 comments

  • ktimespi 11 minutes ago
    I was working on aggregations like this for a datalog research project and couldn't figure out a way to do it without recomputing the entire window. I love the way this exchanges space for compute, this is really cool!!!
  • tinco 2 hours ago
    Very cool, might I suggest you rename your `pop` function to `shift` (or if you like ugly names `popleft`)? Popping windows isn't really a thing, it made me double take on the code.
    • orlp 1 hour ago
      I don't like `shift` as a name because it might give the impression the entire window shifts. Push increases the window size by one and pop decreases the window size by one (evicting the earliest pushed element).

      In my mental model `shift` would move the entire window, it would be one push + one pop.

      • tinco 1 hour ago
        Ok, but shift is the commonly used name for that operation, and pop commonly does something else than what you just described. If you could come up with a better word than shift that would be fine, but pop should be the inverse of push in my opinion. If you push, then pop, you should have the same data as you started with.
        • orlp 43 minutes ago
          > If you push, then pop, you should have the same data as you started with.

          That's the case for a LIFO queue, but not a FIFO queue. Both commonly use the push/pop nomenclature.

          • tinco 36 minutes ago
            Ah I haven't seen that before. I must admit that I'm not in the literature side of things. Any time I've seen a queue in production it would use put/get or enqueue/dequeue and in Ruby scripts you'd use an array and use push/shift.
      • teiferer 40 minutes ago
        Unfortunately, pop means two different things then. For the python lists, it pops "from the right" but for TwoStackAgg it pops "from the left". That makes the code harder to grasp.

        Maybe use popleft?

  • armcat 2 hours ago
    This is very cool, I can see a big use case on this for streaming analytics and anomaly detection. So if I get this right, you get:

    - Amortized O(1) work per window update

    - O(1) aggregate queries, assuming a fixed cost merge operation

    - O(W) memory for W buckets, with sketch size treated as fixed

    - No need to recompute the entire window every second

    • orlp 1 hour ago
      That's right, and one more property I consider very important for numerical stability:

      - The aggregate only depends on the value currently in the window.

      Most problems caused by NaNs/infinities/catastrophic cancellation/etc in sliding windows are covered by this property.

  • MawKKe 1 hour ago
    Would be nice to have some example code how the class is intended to be used
  • teiferer 42 minutes ago
    What do you need self.values_agg for? It is only used for the aggregate of values not yet represented in cum_aggs if finalize is called. That value could just get computed right there on the fly.

    Is it maybe for repeated finalize calls? To essentially re-use those computations?

  • ibraryunus 1 hour ago
    [flagged]