Skip to content

feat: replace CountMinSketch with FastFrequencySketch in Artery compression#3023

Open
He-Pin wants to merge 1 commit into
mainfrom
feature/artery-frequency-sketch
Open

feat: replace CountMinSketch with FastFrequencySketch in Artery compression#3023
He-Pin wants to merge 1 commit into
mainfrom
feature/artery-frequency-sketch

Conversation

@He-Pin

@He-Pin He-Pin commented May 31, 2026

Copy link
Copy Markdown
Member

Motivation

The Artery compression system uses a CountMinSketch (128KB per connection, 16×1024×8 bytes) for heavy hitter detection in actor ref and class manifest compression tables. Pekko already has FastFrequencySketch in pekko-actor (used for cluster sharding entity passivation) which is:

  • ~32x more memory efficient (~4KB vs ~128KB per inbound connection)
  • Includes TinyLFU reset — periodic halving of all counters provides natural aging, enabling the heavy hitters table to adapt to changing traffic patterns over time
  • Already battle-tested — used in production cluster sharding passivation strategies

This addresses akka/akka-core#31093.

Modification

  • InboundCompressions.scala: Replace CountMinSketch with FastFrequencySketch[T] in InboundCompression. The increment method now calls frequencySketch.increment(value) per occurrence and uses frequencySketch.frequency(value) as the estimated weight for heavy hitter detection.
  • TopHeavyHitters.scala:
    • update() now always allows weight updates for existing heavy hitters (previously only allowed increases). This is necessary because FrequencySketch's periodic reset halves all counters.
    • updateExistingHeavyHitter() supports both weight increase (push down) and decrease (bubble up) in the heap.
    • New fixHeapUp() method for bidirectional heap property restoration.
    • isHeavy() check now only gates insertion of new entries.
  • CountMinSketch.java: Removed — was INTERNAL API with no external users.
  • CountMinSketchBenchmark.scala: Updated to benchmark FastFrequencySketch instead.
  • Legal files: Removed CountMinSketch/stream-lib attribution (no longer bundled).

Result

Artery compression uses ~4KB instead of ~128KB per inbound connection. Heavy hitters now adapt to changing traffic patterns via TinyLFU aging rather than tracking monotonically increasing absolute counts.

Tests

  • remote / testOnly ...HeavyHittersSpec: 13/13 passed (includes 2 new tests for weight decrease and heap upward restoration)
  • remote / testOnly ...CompressionTableSpec: 3/3 passed
  • remote / testOnly ...OutboundCompressionSpec: 2/2 passed

References

Refs akka/akka-core#31093

@He-Pin He-Pin added this to the 2.0.0-M4 milestone May 31, 2026
@He-Pin He-Pin requested a review from pjfanning May 31, 2026 18:09
@He-Pin He-Pin marked this pull request as draft May 31, 2026 18:42
Comment thread build.sbt Outdated
@pjfanning

pjfanning commented May 31, 2026

Copy link
Copy Markdown
Member

I'd prefer if the old code was kept and made configurable - as in let user choose the compression scheme

He-Pin added a commit that referenced this pull request May 31, 2026
Motivation:
Reviewer (pjfanning) requested keeping the original CountMinSketch code
and making the compression scheme configurable so users can choose.

Modification:
- Restored CountMinSketch.java (was deleted in previous commit)
- Restored legal files for CountMinSketch attribution
- Added configuration option  to choose
  between 'count-min-sketch' and 'fast-frequency-sketch' (default)
- Created FrequencySketch abstraction trait with wrappers for both
  CountMinSketch and FastFrequencySketch
- Reverted CountMinSketchBenchmark to use CountMinSketch directly
  (FastFrequencySketch is private[pekko] and not accessible from bench-jmh)
- Removed MiMa filter since CountMinSketch is no longer removed

Result:
Users can now choose between CountMinSketch (legacy, ~128KB per connection)
and FastFrequencySketch (default, ~4KB per connection with TinyLFU aging).

Tests:
- remote/testOnly ...HeavyHittersSpec: 13/13 passed
- remote/testOnly ...CompressionTableSpec: 3/3 passed
- remote/compile: passed
- bench-jmh/compile: passed
- remote/mimaReportBinaryIssues: passed

Refs: #3023
@He-Pin He-Pin force-pushed the feature/artery-frequency-sketch branch from be77b6e to 83cd9ae Compare May 31, 2026 19:46
@He-Pin He-Pin marked this pull request as ready for review May 31, 2026 19:51
@He-Pin He-Pin requested a review from pjfanning June 16, 2026 10:01
Comment thread remote/src/main/resources/reference.conf
@He-Pin He-Pin force-pushed the feature/artery-frequency-sketch branch from 2bfe105 to eb1fd14 Compare June 16, 2026 12:16
@He-Pin He-Pin requested a review from pjfanning June 16, 2026 12:29
…ession

Motivation:
The Artery compression system uses a CountMinSketch (128KB per
connection, 16x1024x8 bytes) for heavy hitter detection in actor ref
and class manifest compression tables. Pekko already has
FastFrequencySketch in pekko-actor (used for cluster sharding entity
passivation) which is ~32x more memory efficient (~4KB vs ~128KB per
inbound connection), includes TinyLFU reset for natural aging, and is
already battle-tested in production. This addresses akka/akka-core#31093.

Modification:
- InboundCompressions.scala: Add configurable frequency-sketch-implementation
  setting supporting both "fast-frequency-sketch" (default) and
  "count-min-sketch" (legacy). Introduce FrequencySketch trait with
  CountMinSketchFrequencySketch and FastFrequencySketchWrapper
  implementations. InboundCompression uses the configured sketch for
  heavy hitter detection.
- TopHeavyHitters.scala: update() always allows weight updates for
  existing heavy hitters (necessary for FrequencySketch periodic reset).
  updateExistingHeavyHitter() supports both weight increase (push down)
  and decrease (bubble up) in the heap. New fixHeapUp() method for
  bidirectional heap property restoration. isHeavy() check only gates
  insertion of new entries.
- CountMinSketch.java: Kept as legacy option, wrapped via
  CountMinSketchFrequencySketch adapter.
- CountMinSketchBenchmark.scala: Updated to benchmark both
  implementations.
- reference.conf: Added frequency-sketch-implementation config with
  "fast-frequency-sketch" as default.
- CompressionIntegrationSpec: Added integration test verifying
  compression works with count-min-sketch implementation.

Result:
Artery compression uses ~4KB instead of ~128KB per inbound connection
by default. Heavy hitters adapt to changing traffic patterns via
TinyLFU aging. Legacy CountMinSketch remains available via config.

Tests:
- remote/testOnly HeavyHittersSpec: 13/13 passed (includes 2 new tests)
- remote/testOnly CompressionTableSpec: 3/3 passed
- remote/testOnly OutboundCompressionSpec: 2/2 passed
- remote/Test/compile: success (new CompressionIntegrationSpec test)

References:
Refs akka/akka-core#31093
@He-Pin He-Pin force-pushed the feature/artery-frequency-sketch branch from eb1fd14 to f6d81c2 Compare June 17, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants