Repository navigation
Add a per-tenant composite rebuild stress harness that reports peak physical footprint - #5830
Merged
Merged
Conversation
…hysical footprint (#5820) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #5820
What it is
src/TenantRebuildStress: a console harness for the JasperFx/jasperfx#1113 and #1127 scenario. It uses per-tenant event partitioning, many tenants, and a composite projection rebuilt with one agent per tenant. It reports the process's peak physical footprint, sampled once a second with macOStop -stats mem,cmprs(never RSS).--fanoutof--bucketslarge documents (--payload-kb), so each page builds thousands of big upserts. Stage 2 is a small single-stream projection.RebuildProjectionAsync(name, tenantId: null, ...), withMaxConcurrentRebuildsPerDatabase = --concurrencyso every tenant rebuilds at once.--serialize on|offsetsDaemonSettings.SerializeTenantProjectionBatchesby reflection, so the same harness runs on a JasperFx from before the setting existed (--serialize unset).--mode seed|rebuild|both. Seed once, then rebuild in fresh processes so runs share one data set. Each run prints aRESULT|version|serialize|seconds|peakMemMB|peakMem+CmprsMB|buckets|touchesline and the projected counts, to check against the events.First numbers (MacBook, Postgres 17 in Docker)
24 tenants × 1,000 events, 4,000 buckets of 8 KB per tenant, 40 buckets per event,
BatchSize500, 24 concurrent cells. Every run projected the same 95,997 buckets and 955,190 touches, which matches a count taken straight frommt_events.SerializeTenantProjectionBatchesThe batch queue bounds the memory that built batches hold: 8.2 GB to 355 MB under workstation GC, with the rebuild about twice as slow. Under server GC on this many-core box, the GC's per-heap allocation budgets set the footprint (about 5 GB) whatever the queue does, so the queue's effect barely shows there. A container with a memory limit constrains those budgets, so the warm-up node in #1113 is the measurement that settles it. This harness can be run with
DOTNET_GCHeapHardLimitto approximate one.The 2.100 rows need the JasperFx 2.100 pin and #5829, which are on the
jasperfx-2.100-localbranch. On master, a second per-tenant composite rebuild on the same schema projects nothing (#5829). The harness itself only references Marten, so it builds on master's pin.🤖 Generated with Claude Code