perf: benchmarks, allocation budgets, and instrumentation#10
Conversation
Add performance infrastructure to measure and guard against regressions: - ActiveSupport::Notifications instrumentation on Client, Executor, and Serializer hot paths for runtime observability - benchmark-ips suite (serialization, client ops, executor cycle) with mocked PGMQ to isolate gem overhead from database I/O - memory_profiler-based detailed allocation analysis and leak detection - Allocation budget specs that fail CI if object counts spike above thresholds (send_message <50, send_batch <25/item, read_batch <30, JSON round-trip <20) or if any objects are retained (leak detection) - Rake tasks: bench, bench:serialization, bench:client, bench:executor, bench:memory
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR adds benchmarking scripts and Rake tasks, introduces a conditional Instrumentation API, wraps serializer/client/executor hot paths with instrumentation, and adds memory-allocation tests. It also adds test-only gems Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client
participant PGMQ as PGMQ
participant Instrument as Instrumentation
participant Serializer as Serializer
participant Executor as Executor
Client->>Instrument: instrument("pgbus.client.send_message", queue:)
Instrument-->>Client: yield
Client->>Serializer: serialize_job(job)
Serializer->>Instrument: instrument("pgbus.serializer.serialize", kind: :job)
Instrument-->>Serializer: yield
Serializer-->>Client: serialized_payload
Client->>PGMQ: produce(serialized_payload)
Client-->>Instrument: instrumentation complete
Executor->>Instrument: instrument("pgbus.executor.execute", queue:, job_class:)
Instrument-->>Executor: yield
Executor->>PGMQ: read_message
PGMQ-->>Executor: message
Executor->>Serializer: deserialize_job(payload)
Serializer->>Instrument: instrument("pgbus.serializer.deserialize", kind: :job)
Instrument-->>Serializer: yield
Serializer-->>Executor: job_instance
Executor->>Executor: execute_job(job_instance)
Executor->>PGMQ: archive_message
Executor-->>Instrument: instrumentation complete
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@benchmarks/memory_profile.rb`:
- Around line 69-76: Fix the incorrect hash-style access to MemoryProfiler Stat
objects in memory_profile.rb: replace stat[:count] and stat[:memory] with the
Stat method accessors (stat.count and stat.memsize) and stop using stat[:data];
instead pull the gem or location label from the grouping returned by
report.retained_memory_by_gem / report.retained_memory_by_location (e.g.,
iterate with |gem_name, stats| or |location, stats| and then use stat.count and
stat.memsize for each Stat). Ensure you update the puts lines to use the
gem_name/location label plus stat.count and stat.memsize.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ff370d0b-2d84-43f9-a266-0a80a7a23f56
📒 Files selected for processing (12)
GemfileRakefilebenchmarks/bench_helper.rbbenchmarks/client_bench.rbbenchmarks/executor_bench.rbbenchmarks/memory_profile.rbbenchmarks/serialization_bench.rblib/pgbus/active_job/executor.rblib/pgbus/client.rblib/pgbus/instrumentation.rblib/pgbus/serializer.rbspec/pgbus/allocation_budget_spec.rb
memory_profiler returns Hashes with :data and :count keys, not objects with method accessors. The :count key in retained_memory_by_* methods represents bytes, while retained_objects_by_* methods give object counts. Split the output to show both object counts and memory bytes correctly.
Summary
ActiveSupport::Notificationsevents on Client (send_message,send_batch,read_message,read_batch), Executor (execute), and Serializer (serialize,deserialize) for runtime observabilitybenchmark-ips+memory_profilerscripts measuring throughput and memory for serialization, client ops, and executor cycles — PGMQ mocked to isolate gem overheadrake bench,rake bench:serialization,rake bench:client,rake bench:executor,rake bench:memoryTest plan
bundle exec rake benchto verify benchmark scripts execute end-to-endbundle exec rake bench:memoryto baseline current allocation profileSummary by CodeRabbit
New Features
Tests
Chores