1+ # Architecture Overview
2+
3+ Lading measures performance of long-running programs (daemons) using synthetic,
4+ repeatable load generation. It operates with three components:
5+
6+ - ** Generators** : Create deterministic load and push to targets
7+ - ** Targets** : Programs being tested (run as subprocesses by lading)
8+ - ** Blackholes** : Optionally receive output from targets
9+
10+ Data flows: Generator → Target → Blackhole
11+
12+ Key principle: Pre-compute everything possible. This minimizes runtime overhead
13+ and interference with the target being measured.
14+
115# Design Goals
216
317Lading is a performance tool. It's behavior has consequences on the development
@@ -15,6 +29,32 @@ this means that lading will pre-allocate where possible, will explicitly thread
1529randomness and other sources of non-determinism into code paths and will
1630preference algorithms that have better worst-case behavior.
1731
32+ ## Performance Guidance
33+
34+ Always consider performance implications of changes. Focus on "obviously fast" patterns:
35+ - Pre-allocate collections when size is known
36+ - Avoid allocations in hot paths
37+ - Choose algorithms with good worst-case behavior over average-case
38+ - Prefer bounded operations over unbounded ones
39+ - Avoid unnecessary cloning or copying
40+
41+ Do NOT dive into performance optimization rabbit holes without profiling data.
42+ Benchmarks alone are insufficient - real performance work requires profiling.
43+ Stick to obviously correct performance patterns.
44+
45+ ## Error Handling
46+
47+ Lading MUST NOT panic. Use controlled shutdowns only. All errors should be
48+ propagated using Result types. Panics are only acceptable for truly exceptional
49+ circumstances that cannot be handled (e.g., fundamental invariant violations that
50+ indicate memory corruption).
51+
52+ When handling errors:
53+ - Always use Result<T, E> for fallible operations
54+ - Propagate errors up to where they can be meaningfully handled
55+ - Provide context when wrapping errors
56+ - Design for graceful degradation where possible
57+
1858# Code Style
1959
2060This project enforces code style through automated tooling. Use ` ci/validate ` to
@@ -26,8 +66,8 @@ not preferred if a duplicated pattern will satisfy. Our reasoning for this is it
2666makes ramp-up for new engineers easier: all you must do is follow the pattern,
2767not internalize a complex type hierarchy. There are obvious places in the code
2868base where replicated patterns have been made into abstractions -- we follow the
29- "shape" rule, if you have three or more repeats, make a jig -- but we do not
30- start there .
69+ "shape" rule: if you have three or more repeats, make a jig. This is a hard rule:
70+ 3+ repetitions = create an abstraction. Less than 3 = duplicate the pattern .
3171
3272Lading is written to be as easy to contribute to as possible. We ask that any
3373dependency used in the project in more than one crate be present in the
@@ -43,14 +83,35 @@ or two of code. Do add comments that explain the "why" of a block of code, how
4383it functions or is unusual in a way that an experienced engineer might not
4484understand.
4585
86+ Always add comments for:
87+ - Non-obvious performance optimizations
88+ - Complex state machines or control flow
89+ - Unusual algorithm choices
90+ - Workarounds for external limitations
91+ - Any code that would make an experienced engineer pause and wonder "why?"
92+
4693Crate versions are always given as XX.YY and not XX.YY.ZZ.
4794
4895# Testing
4996
50- Where possible lading prefers property tests over unit tests and in especially
51- critical components we require proofs. We use
52- [ proptest] ( https://github.com/proptest-rs/proptest ) in this project for property
53- tests and the [ kani] ( https://github.com/model-checking/kani ) proof tool.
97+ ALWAYS prefer property tests over unit tests. Unit tests are insufficient for
98+ lading's requirements. We use [ proptest] ( https://github.com/proptest-rs/proptest )
99+ for property testing.
100+
101+ Critical components are those which must function correctly or lading itself
102+ cannot function. These require proofs using [ kani] ( https://github.com/model-checking/kani ) :
103+ - Throttling (MUST be correct - lading is used to make throughput claims)
104+ - Core data generation
105+ - Fundamental algorithms
106+
107+ The throttle is especially critical: incorrect throttling invalidates all
108+ performance claims made using lading.
109+
110+ When writing tests:
111+ - Default to property tests
112+ - Unit tests are only acceptable for simple pure functions
113+ - Think about the properties your code should maintain
114+ - Test invariants, not specific examples
54115
55116# CRITICAL: Validation Workflow
56117
@@ -72,10 +133,48 @@ To identify outdated dependencies: Use `ci/outdated`
72133
73134To run micro-benchmarks: ` cargo criterion `
74135
136+ ## Dependencies
137+
138+ Due to lading's unusual constraints (performance, determinism, correctness),
139+ we often must implement functionality rather than use external crates.
140+
141+ Before suggesting a new dependency, consider:
142+ - Does it meet our performance requirements?
143+ - Is it deterministic?
144+ - Does it give us sufficient control?
145+ - Is the functionality core to lading's purpose?
146+
147+ When in doubt, implement rather than import.
148+
149+ ## Common Patterns and Anti-Patterns
150+
151+ ### DO:
152+ - Pre-allocate buffers and collections when size is known
153+ - Use bounded channels/queues over unbounded
154+ - Design for worst-case scenarios
155+ - Use fixed-size data structures where possible
156+ - Propagate errors up to where they can be handled meaningfully
157+
158+ ### DON'T:
159+ - Use ` .unwrap() ` or ` .expect() ` (these panic)
160+ - Allocate in hot paths
161+ - Use unbounded growth patterns
162+ - Add external dependencies without careful consideration
163+ - Implement complex abstractions for fewer than 3 use cases
164+
75165# Key Reminders for Claude
76166
771671 . ALWAYS use ` ci/validate ` after code changes - never skip this
781682 . Do NOT run cargo commands directly - use the ci/ scripts
791693 . When users ask about build/test failures, suggest running ` ci/validate `
801704 . If users are confused about project correctness criteria, point them to ` ci/validate `
811715 . The ci/ scripts are the single source of truth for validation
172+ 6 . Always consider performance - suggest "obviously fast" patterns
173+ 7 . Do NOT suggest performance optimizations without profiling data
174+ 8 . When in doubt, prefer pre-allocation and good worst-case behavior
175+ 9 . NEVER suggest code that could panic - use Result types
176+ 10 . Be skeptical of external dependencies - we often need custom implementations
177+ 11 . Remember the throttle is critical - any changes there need extra scrutiny
178+ 12 . Generators must be deterministic - no randomness without explicit seeding
179+ 13 . Pre-compute in initialization, not in hot paths
180+ 14 . Think about how your code affects the measurement of the target
0 commit comments