chore(samples): add message-list benchmark page - #2779
Conversation
A scratch screen in sample_app for profiling StreamMessageListView under synthetic message floods. Has its own entrypoint so it stays out of the main sample app's UI; run with: flutter run --profile -t benchmark/main_benchmark.dart The page injects synthetic `message.new` events through `client.handleEvent` at a configurable rate, with chips for LIMIT (in-memory cap), FLOOD (events per recording), and SPEED (msg/s) so a single recording is comparable across builds. Dashboard updates are routed through a separate ValueNotifier so HUD repaints don't taint the list's frame timings. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughTwo new files add a standalone Flutter benchmark tool for ChangesStreamMessageListView Benchmark Tool
Sequence Diagram(s)sequenceDiagram
participant main
participant StreamChatClient
participant _BenchmarkLauncherState
participant _BenchmarkPageState
participant SchedulerBinding
participant ValueNotifier
main->>StreamChatClient: connectUser(credentials)
main->>_BenchmarkLauncherState: runApp
_BenchmarkLauncherState->>StreamChatClient: channel.watch(limit: 25)
StreamChatClient-->>_BenchmarkLauncherState: Channel
_BenchmarkLauncherState->>_BenchmarkPageState: BenchmarkPage(channel)
rect rgba(70, 130, 180, 0.5)
Note over _BenchmarkPageState,SchedulerBinding: Flood active
_BenchmarkPageState->>StreamChatClient: handleEvent(message.new) [periodic]
SchedulerBinding->>_BenchmarkPageState: timingsCallback(frames)
_BenchmarkPageState->>_BenchmarkPageState: collect _FrameSample, prune window
_BenchmarkPageState->>ValueNotifier: publish _DashboardSnapshot at 2Hz
ValueNotifier-->>_BenchHudPill: rebuild FPS/msg/mem metrics
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
sample_app/benchmark/main_benchmark.dart (1)
13-16: 🧹 Nitpick | 🔵 Trivial | 💤 Low valueConsider externalizing credentials.
Static analysis flagged these as hardcoded secrets. While these appear to be shared demo credentials for the sample app, externalizing them via environment variables or a gitignored config file would:
- Keep credentials out of version control history
- Allow different credentials per environment
- Follow security best practices
For a benchmark-only tool this may be acceptable, but worth noting for future reference.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@sample_app/benchmark/main_benchmark.dart` around lines 13 - 16, The constants _apiKey, _userId, and _userToken are hardcoded directly in the source file, which exposes credentials in version control. Move these credential values to environment variables or a gitignored configuration file instead. Update the const declarations to read from environment variables using a method like String.fromEnvironment() or by loading them from a gitignored config file at runtime, ensuring the credentials are no longer embedded in the code.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@sample_app/benchmark/benchmark_page.dart`:
- Around line 621-632: The Align widget in the build method has a key:
UniqueKey() parameter that creates a new key on every build call, forcing
Flutter to discard and recreate the element unnecessarily and introducing
measurement noise in the benchmarking tool. Remove the key parameter entirely
from the Align widget since the _BenchHud widget is stateless and does not
require a unique key for element reuse.
- Around line 192-199: The code has inconsistent null handling for
`widget.channel.state`: line 192 uses safe navigation with `state?.messages`,
but line 194 uses force unwrap with `state!.messagesStream`. Since
`channel.watch()` is awaited before this page is shown, `state` should be
guaranteed non-null, so update line 192 to use force unwrap
`widget.channel.state!.messages` instead of the safe navigation operator to make
the null handling explicit and consistent throughout the listen callback block.
In `@sample_app/benchmark/main_benchmark.dart`:
- Line 7: Replace the relative import statement for benchmark_page.dart with a
package import. Change the import from relative path syntax (import
'benchmark_page.dart') to package syntax (import 'package:sample_app/...') to
comply with the always_use_package_imports coding guideline.
---
Nitpick comments:
In `@sample_app/benchmark/main_benchmark.dart`:
- Around line 13-16: The constants _apiKey, _userId, and _userToken are
hardcoded directly in the source file, which exposes credentials in version
control. Move these credential values to environment variables or a gitignored
configuration file instead. Update the const declarations to read from
environment variables using a method like String.fromEnvironment() or by loading
them from a gitignored config file at runtime, ensuring the credentials are no
longer embedded in the code.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: ad28b2fc-b439-4a8d-a4a0-f7633180567f
📒 Files selected for processing (2)
sample_app/benchmark/benchmark_page.dartsample_app/benchmark/main_benchmark.dart
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2779 +/- ##
=======================================
Coverage 69.59% 69.59%
=======================================
Files 426 426
Lines 25675 25675
=======================================
Hits 17868 17868
Misses 7807 7807 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Consistent non-null `channel.state` handling: capture once into a local and read `messages` / `messagesStream` off it. The page is only shown after `channel.watch()` resolves, so the bang is the honest expression of that invariant. - Drop `UniqueKey()` on the HUD's `Align` — it forced a discard + rebuild on every parent rebuild, which is exactly the kind of measurement noise this page is supposed to avoid. The HUD's outer `RepaintBoundary` already gives it its own compositor layer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Adds an internal profiling screen to
sample_appfor measuringStreamMessageListViewunder load. Lives atsample_app/benchmark/(sibling tolib/, not packaged with the regular app) with its own entrypoint so it stays out of normal sample-app navigation.Run with:
cd sample_app flutter run --profile -t benchmark/main_benchmark.dartThe page injects synthetic
message.newevents throughclient.handleEvent(same path the WebSocket pipeline uses) at a configurable rate. Chips control:StreamMessageListViewConfiguration.maximumMessageLimit)Dashboard updates are routed through a
ValueNotifierso HUD repaints don't bubble up intoStreamMessageListView's rebuild path — keeps the measured frame timings clean.This was originally drafted on the v10 branch and recovered from a dangling commit; APIs were ported to current master (
StreamMessageItemBuilder3-arg signature,StreamMessageListViewConfiguration,StreamMessageComposer).Test plan
flutter run --profile -t benchmark/main_benchmark.dartfromsample_app/launches the benchmark page🤖 Generated with Claude Code
Summary by CodeRabbit