Skip to content

Batch download counts - #1518

Open
LaurentRDC wants to merge 2 commits into
haskell:masterfrom
LaurentRDC:optimize-download-counts
Open

Batch download counts#1518
LaurentRDC wants to merge 2 commits into
haskell:masterfrom
LaurentRDC:optimize-download-counts

Conversation

@LaurentRDC

@LaurentRDC LaurentRDC commented Aug 24, 2026

Copy link
Copy Markdown

This patch batches download counts, rather than incurring an acid-state transaction for every download.

This reduces the number of events related to download counts, while creating the potential for some downloads being dropped due to the in-memory cache being flushed only periodically.

Benchmarks included in this patch show much better replay times, and a smaller acid-state event log, proportional to the batching factor. The cost is slightly higher memory usage due to the in-memory download counts cache.

In order to properly shutdown the download counts feature, a "pre-shutdown" step has been added to features, such that download counts can be flushed to disk on graceful shutdown.

This batching does not require anything special when it comes to deployment, as the previous download counts can be modeled as batches of 1. This patch therefore doesn't require a migration.

Partially fixes #1342. The way downloads are stored in per package-day counts forever could also be optimized, but this will require a change in the event log representation.

Benchmarks

The DownloadCountBench benchmarks below distributed 20k downloads over 300 packages. In the batched mode, downloads are batched in batches of 3000. Using individual mode uses the legacy patch of incrementing the on-disk download count by 1.

Legacy behavior

> cabal run DownloadCountBench -- individual 200000 200
individual (one event per download): 200000 downloads over 200 distinct package versions
  time to record            6.365 s
  event log on disk         34694 KB
  start-up replay           0.388 s
  allocated                 5324 MB
  peak live heap            158 KB
  InMemStats memSize        1122 KB

New behavior, where batches of 3000 download counts are flushed at once

> cabal run DownloadCountBench -- batched 200000 200 3000
individual (one event per download): 200000 downloads over 200 distinct package versions
  time to record            0.068 s
  event log on disk         1187 KB
  start-up replay           0.015 s
  allocated                 521 MB
  peak live heap            186 KB
  InMemStats memSize        1122 KB

This is an extreme example, but it still shows major performance improvements, roughly proportional to batching.

@LaurentRDC
LaurentRDC force-pushed the optimize-download-counts branch from 5ce96f4 to 2321247 Compare August 24, 2026 20:59
This patch batches download counts, rather than incurring an acid-state
transaction for every download.

This reduces the number of events related to download counts, while creating
the potential for some downloads being dropped due to the in-memory cache
being flushed only periodically.

Benchmarks included in this patch show much better replay times, and a smaller
acid-state event log, proportional to the batching factor. The cost
is slightly higher memory usage due to the in-memory download counts cache.

In order to properly shutdown the download counts feature, a "pre-shutdown" step
has been added to features, such that download counts can be flushed to disk
on graceful shutdown.

This batching does not require anything special when it comes to deployment,
as the previous download counts can be modeled as batches of 1. This patch
therefore doesn't require a migration.

Partially fixes haskell#1342
@LaurentRDC
LaurentRDC force-pushed the optimize-download-counts branch from 2321247 to d7ab719 Compare August 24, 2026 21:01
Comment thread src/Distribution/Server/Features/DownloadCount.hs Outdated
@LaurentRDC
LaurentRDC marked this pull request as ready for review August 24, 2026 23:06
@mergify

mergify Bot commented Aug 24, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

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.

Download count feature needs optimizing

1 participant