perf-skills 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,15 +5,15 @@
5
5
  "email": "contact@qainsights.com"
6
6
  },
7
7
  "metadata": {
8
- "description": "Expert AI skill for performance testing - covers the full lifecycle using JMeter, k6, Gatling, Locust, NeoLoad, LoadRunner, and OctoPerf.",
9
- "version": "1.0.4"
8
+ "description": "Expert AI skill for performance testing - covers the full lifecycle using JMeter, k6, Gatling, Locust, Artillery, NeoLoad, LoadRunner, OctoPerf, plus LLM inference benchmarking and SLO/capacity planning.",
9
+ "version": "4.0.0"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "perf",
14
14
  "source": "./",
15
- "description": "Expert guidance for performance testing: planning, scripting, executing, and analyzing load/stress/soak/spike tests across 7 tools and 10 topic areas.",
16
- "version": "1.0.4",
15
+ "description": "Expert guidance for performance testing: planning, scripting, executing, and analyzing load/stress/soak/spike tests across 8 tools, 13 topic areas, LLM inference benchmarking, and SLO/capacity planning.",
16
+ "version": "4.0.0",
17
17
  "author": {
18
18
  "name": "NaveenKumar Namachivayam",
19
19
  "email": "contact@qainsights.com"
@@ -28,6 +28,7 @@
28
28
  "k6",
29
29
  "gatling",
30
30
  "locust",
31
+ "artillery",
31
32
  "neoload",
32
33
  "loadrunner",
33
34
  "octoperf",
@@ -38,6 +39,10 @@
38
39
  "websocket",
39
40
  "observability",
40
41
  "ci-cd",
42
+ "llm-inference",
43
+ "vllm",
44
+ "slo",
45
+ "capacity-planning",
41
46
  "performance-testing-best-practices",
42
47
  "performance-testing-strategies",
43
48
  "black-friday-performance-testing",
@@ -68,12 +73,15 @@
68
73
  "k6",
69
74
  "gatling",
70
75
  "locust",
76
+ "artillery",
71
77
  "neoload",
72
78
  "loadrunner",
73
79
  "octoperf",
74
80
  "performance-engineering",
75
- "load-testing-automation",
76
- "performance-testing-automation",
81
+ "llm-inference",
82
+ "vllm",
83
+ "slo",
84
+ "capacity-planning",
77
85
  "performance-testing-best-practices",
78
86
  "performance-testing-strategies"
79
87
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perf",
3
- "description": "Expert guidance for performance testing: planning, scripting, executing, and analyzing load/stress/soak/spike tests using JMeter, k6, Gatling, Locust, NeoLoad, LoadRunner, OctoPerf.",
4
- "version": "1.0.4",
3
+ "description": "Expert guidance for performance testing: planning, scripting, executing, and analyzing load/stress/soak/spike tests using JMeter, k6, Gatling, Locust, Artillery, NeoLoad, LoadRunner, OctoPerf, plus LLM inference benchmarking and SLO/capacity planning.",
4
+ "version": "4.0.0",
5
5
  "skills": "./skills/"
6
6
  }
package/README.md CHANGED
@@ -30,9 +30,10 @@
30
30
 
31
31
  | Category | Supported Technologies |
32
32
  | :--- | :--- |
33
- | **Open Source** | Apache JMeter, k6 (Grafana Labs), Gatling, Locust |
33
+ | **Open Source** | Apache JMeter, k6 (Grafana Labs), Gatling, Locust, Artillery |
34
34
  | **Commercial/SaaS** | NeoLoad (Tricentis), LoadRunner (OpenText), OctoPerf |
35
35
  | **Protocols** | HTTP/REST, gRPC, GraphQL, WebSocket, SSE, JDBC, SOAP, Kafka/MQ, Citrix, SAP |
36
+ | **AI/ML** | LLM inference benchmarking (vLLM, TRT-LLM, SGLang), SLO/capacity planning |
36
37
 
37
38
  ---
38
39
 
@@ -60,6 +61,7 @@ A major highlight of this library is the **Dynamic Value Correlation** engine ([
60
61
  | AI Assistant | Integration Method |
61
62
  | :--- | :--- |
62
63
  | **Claude Code** | Native Plugin or `CLAUDE.md` context referencing |
64
+ | **Qwen Code** | Native Skill (`/perf`) or `QWEN.md` context referencing |
63
65
  | **Windsurf (Cascade)** | Local Skill configuration |
64
66
  | **Cursor** | Custom rules `.cursor/rules/` or index via `@Docs` |
65
67
  | **Cline / Roo Code** | Workspace instructions / custom rules |
@@ -92,6 +94,24 @@ To update to the latest version:
92
94
 
93
95
  ---
94
96
 
97
+ ### Qwen Code Skill
98
+
99
+ Install as a user-level skill so `/perf` is available in every project:
100
+ ```bash
101
+ qwen skills add QAInsights/perf-skills
102
+ ```
103
+
104
+ Or for a single project, copy the skill directory and reference it in `QWEN.md`:
105
+ ```bash
106
+ cp -r perf-skills/skills/perf ./perf
107
+ ```
108
+ ```markdown
109
+ <!-- QWEN.md -->
110
+ For performance testing questions, read `perf/SKILL.md` for routing, then load the relevant reference files from `perf/references/`.
111
+ ```
112
+
113
+ ---
114
+
95
115
  ### Install as local Skills (npx)
96
116
 
97
117
  If you are using a tool that supports `npx skills`, add it directly:
@@ -191,7 +211,7 @@ perf-skills/
191
211
  │ ├── k6.md # k6 JS/TS scripting, thresholds, VU options
192
212
  │ ├── gatling.md # Gatling Scala/Java DSL & feeders
193
213
  │ ├── locust.md # Locust Python scripting & FastHttpUser
194
- │ ├── artillery.md # Artillery YAML/JS/TS scripting, phases, ensure SLOs, cloud
214
+ │ ├── artillery.md # Artillery YAML/JS/TS scripting, phases, ensure SLOs, cloud
195
215
  │ ├── neoload.md # NeoLoad GUI configs & API execution
196
216
  │ ├── loadrunner.md # LoadRunner VuGen C scripting
197
217
  │ └── octoperf.md # OctoPerf JMeter-based cloud execution
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "perf-skills",
3
- "version": "3.0.0",
4
- "description": "Expert AI skill for performance testing - covers JMeter, k6, Gatling, Locust, NeoLoad, LoadRunner, OctoPerf across the full lifecycle",
3
+ "version": "4.0.0",
4
+ "description": "Expert AI skill for performance testing - covers JMeter, k6, Gatling, Locust, Artillery, NeoLoad, LoadRunner, OctoPerf, LLM inference benchmarking, and SLO/capacity planning across the full lifecycle",
5
5
  "main": "skills/perf/SKILL.md",
6
6
  "files": [
7
7
  "skills/",
@@ -14,6 +14,7 @@
14
14
  "k6",
15
15
  "gatling",
16
16
  "locust",
17
+ "artillery",
17
18
  "neoload",
18
19
  "loadrunner",
19
20
  "octoperf",
@@ -24,6 +25,10 @@
24
25
  "websocket",
25
26
  "observability",
26
27
  "ci-cd",
28
+ "llm-inference",
29
+ "vllm",
30
+ "slo",
31
+ "capacity-planning",
27
32
  "claude-skills",
28
33
  "ai-assistant"
29
34
  ],
@@ -93,12 +93,12 @@ Use this to recommend the right tool when the user hasn't decided yet.
93
93
 
94
94
  | Criteria | JMeter | k6 | Gatling | Locust | Artillery | NeoLoad | LoadRunner | OctoPerf |
95
95
  |----------------------|---------------------|-----------------------|----------------------|----------------|------------------|-------------------------|-----------------------|
96
- | **Language** | GUI/XML + Groovy | JavaScript/TypeScript | Scala/Java | Python | GUI + NeoLoad DSL| VuGen C-like | Web UI (JMeter-based) |
97
- | **Open source** | ✅ | ✅ | ✅ | ✅ | | ❌ | ❌ (SaaS) |
98
- | **Protocol support** | HTTP, JDBC, JMS, MQTT, FTP, gRPC | HTTP, gRPC, WS | HTTP, JMS, gRPC | HTTP, gRPC | HTTP, gRPC, WS, SAP | HTTP, Citrix, SAP, Flex | HTTP (JMeter-backed) |
99
- | **Developer-friendly** | Medium | High | High | High | Low | Low | Medium |
100
- | **Enterprise support** | Community + BlazeMeter | Grafana Cloud | Gatling Enterprise | Limited | Artillery Cloud | ✅ | ✅ | ✅ |
101
- | **CI/CD integration** | Good (Maven/Gradle) | Excellent | Excellent | Good | Good | Moderate | Good |
96
+ | **Language** | GUI/XML + Groovy | JavaScript/TypeScript | Scala/Java | Python | YAML / JS / TS | GUI + NeoLoad DSL | VuGen C-like | Web UI (JMeter-based) |
97
+ | **Open source** | ✅ | ✅ | ✅ | ✅ | ✅ (core) | ❌ | ❌ | (SaaS) |
98
+ | **Protocol support** | HTTP, JDBC, JMS, MQTT, FTP, gRPC | HTTP, gRPC, WS | HTTP, JMS, gRPC | HTTP, gRPC | HTTP, gRPC, WS, Socket.IO | HTTP, SAP, Citrix, Flex | HTTP, SAP, Citrix, many | HTTP (JMeter-backed) |
99
+ | **Developer-friendly** | Medium | High | High | High | Medium | Low | Low | Medium |
100
+ | **Enterprise support** | Community + BlazeMeter | Grafana Cloud | Gatling Enterprise | Limited | Artillery Cloud | ✅ | ✅ | ✅ |
101
+ | **CI/CD integration** | Good (Maven/Gradle) | Excellent | Excellent | Good | Good | Moderate | Good | Good |
102
102
  | **Cloud execution** | BlazeMeter, OctoPerf | Grafana Cloud | Gatling Enterprise | Self-managed | Artillery Cloud (Lambda/Fargate) | NeoLoad Cloud | AWS/on-prem | OctoPerf Cloud |
103
103
  | **Best for** | Legacy systems, JDBC, protocols | Modern APIs, TypeScript devs | High-throughput HTTP | Python teams, flexible | Node teams, YAML tests, cloud scale | SAP/Citrix enterprise | Mainframe, legacy enterprise | JMeter teams needing cloud UI |
104
104
 
@@ -223,13 +223,13 @@ the specific mapping rather than a generic explanation.
223
223
  | User entrypoint | Thread Group | `default()` function | `scenario()` | task methods | `flow` in scenario | `Action()` |
224
224
  | Concurrency ctrl | Thread Group settings | executor | `inject()` | `spawn_rate` | `maxVusers` / `arrivalRate` | Vuser Group |
225
225
  | Think time | Constant/Uniform Timer | `sleep()` | `pause()` | `time.sleep()` | `think` | `lr_think_time()` |
226
- | Inline assertion | Response Assertion | `check()` | `.check()` | `catch_response` | `lr_eval_string()` |
226
+ | Inline assertion | Response Assertion | `check()` | `.check()` | `catch_response` | `afterResponse` hooks | `lr_eval_string()` |
227
227
  | SLA enforcement | Duration Assertion | `thresholds` | Assertions (Enterprise) | custom + exit code | `ensure` plugin | SLA definition |
228
228
  | Correlation | Regex / CSS Extractor | `res.json()` / regex | `.check()` + `saveAs()` | `response.text` + regex | `capture` (json/xpath/regexp/header) | `web_reg_save_param`|
229
229
  | Data feed | CSV Data Set Config | `SharedArray` | `feeder` | CSV reader | `payload` / `variables` | `lr_paramarr()` |
230
230
  | Grouping | Transaction Controller | `group()` | `group()` | task sets | `name` on scenario | Transaction |
231
- | Distributed | Controller + Agents | k6 cloud / k6 operator | Gatling Enterprise | master + workers | Load Generator |
232
- | Results output | .jtl (CSV/XML) | JSON / InfluxDB / cloud | simulation.log | CSV / Locust web UI | .lrr file |
231
+ | Distributed | Controller + Agents | k6 cloud / k6 operator | Gatling Enterprise | master + workers | Lambda / Fargate workers | Load Generator |
232
+ | Results output | .jtl (CSV/XML) | JSON / InfluxDB / cloud | simulation.log | CSV / Locust web UI | JSON / HTML report | .lrr file |
233
233
 
234
234
  ---
235
235
 
@@ -344,4 +344,4 @@ prescribing a solution:
344
344
  - Where will tests **run from** (local, CI, cloud)?
345
345
  - What **environment** is being tested (dev, staging, prod)?
346
346
  - Is there an **APM tool** in place (Datadog, Dynatrace, Grafana,
347
- New Relic)??)??
347
+ New Relic)?
@@ -144,6 +144,86 @@
144
144
  "text": "Notes that values are baselines and should be adjusted to actual SLA requirements"
145
145
  }
146
146
  ]
147
+ },
148
+ {
149
+ "id": 8,
150
+ "prompt": "My Artillery test reports great metrics but my CI pipeline always passes even when p95 latency is 5 seconds. How do I make the test fail in CI?",
151
+ "expected_output": "Identifies missing ensure block as the cause. Without ensure, Artillery always exits 0. Provides an ensure.thresholds example with p95 and error rate conditions.",
152
+ "files": [],
153
+ "assertions": [
154
+ {
155
+ "id": "ensure-block-cause",
156
+ "text": "Identifies that without an ensure block, Artillery always exits 0 regardless of metrics"
157
+ },
158
+ {
159
+ "id": "ensure-example",
160
+ "text": "Provides a concrete ensure.thresholds or ensure.conditions YAML example"
161
+ },
162
+ {
163
+ "id": "exit-code",
164
+ "text": "Explains that ensure causes a non-zero exit code when thresholds are breached, enabling CI gating"
165
+ }
166
+ ]
167
+ },
168
+ {
169
+ "id": 9,
170
+ "prompt": "I set arrivalRate to 100 in Artillery expecting 100 concurrent users, but my backend is getting overwhelmed with way more than 100 simultaneous requests. What's happening?",
171
+ "expected_output": "Explains that arrivalRate is new users per second (open model), not concurrency. On a slow backend, VUs pile up unbounded. Recommends maxVusers to cap concurrency or arrivalCount for a fixed total.",
172
+ "files": [],
173
+ "assertions": [
174
+ {
175
+ "id": "open-model-explanation",
176
+ "text": "Explains that arrivalRate means new users per second (open model), not concurrent users"
177
+ },
178
+ {
179
+ "id": "pileup-risk",
180
+ "text": "Explains that on a slow backend, pending VUs accumulate unboundedly"
181
+ },
182
+ {
183
+ "id": "maxvusers-fix",
184
+ "text": "Recommends maxVusers to cap real concurrency, or arrivalCount for a fixed total number of users"
185
+ }
186
+ ]
187
+ },
188
+ {
189
+ "id": 10,
190
+ "prompt": "We're benchmarking our vLLM endpoint for a chat application. What metrics should we measure and what tools should we use?",
191
+ "expected_output": "Recommends TTFT, TPOT/ITL, tokens per second, and goodput as key metrics. Suggests vLLM bench, GenAI-Perf, GuideLLM, or llmperf as benchmarking tools. Distinguishes streaming vs non-streaming measurement.",
192
+ "files": [],
193
+ "assertions": [
194
+ {
195
+ "id": "ttft-tpot-metrics",
196
+ "text": "Names TTFT (time to first token) and TPOT or ITL (inter-token latency) as key streaming metrics"
197
+ },
198
+ {
199
+ "id": "benchmarking-tools",
200
+ "text": "Recommends at least one specific LLM benchmarking tool such as vLLM bench, GenAI-Perf, GuideLLM, or llmperf"
201
+ },
202
+ {
203
+ "id": "goodput-or-throughput",
204
+ "text": "Mentions goodput or tokens per second as a throughput metric distinct from raw request latency"
205
+ }
206
+ ]
207
+ },
208
+ {
209
+ "id": 11,
210
+ "prompt": "How do I set up SLO-based CI gating for my k6 load tests? I want the build to fail if we burn more than 2% of our error budget.",
211
+ "expected_output": "Explains error budget concept (100% - SLO target). Shows how to translate an error budget into k6 thresholds. Recommends tracking burn rate over the test window.",
212
+ "files": [],
213
+ "assertions": [
214
+ {
215
+ "id": "error-budget-concept",
216
+ "text": "Explains error budget as 100% minus the SLO target (e.g., 99.9% SLO = 0.1% budget)"
217
+ },
218
+ {
219
+ "id": "k6-threshold-mapping",
220
+ "text": "Shows how to express the error budget as concrete k6 thresholds"
221
+ },
222
+ {
223
+ "id": "burn-rate",
224
+ "text": "Mentions burn rate or multi-window alerting as a way to avoid false positives from short test runs"
225
+ }
226
+ ]
147
227
  }
148
228
  ]
149
229
  }
@@ -0,0 +1,38 @@
1
+ {
2
+ "skill_name": "perf",
3
+ "description": "Queries that SHOULD trigger the perf skill",
4
+ "trigger": [
5
+ "Help me write a k6 load test for our REST API",
6
+ "My JMeter test crashes with OutOfMemoryError in CI",
7
+ "What tool should I use for load testing a gRPC service?",
8
+ "How do I correlate JSESSIONID in JMeter?",
9
+ "Set up a distributed Locust run in GitLab CI",
10
+ "Our p95 latency spikes during database writes",
11
+ "What TTFT can our vLLM endpoint sustain at 200 concurrent users?",
12
+ "How many replicas do we need for our SLO?",
13
+ "Write an Artillery test with ensure thresholds for our checkout API",
14
+ "Compare k6 vs Gatling for high-throughput HTTP testing",
15
+ "My Locust test shows zero failures but the server logs have 500 errors",
16
+ "How do I parameterize test data in Gatling?",
17
+ "Set up k6 thresholds for CI gating in GitHub Actions",
18
+ "What is a good p95 target for a payment endpoint?",
19
+ "Help me design a soak test to find memory leaks",
20
+ "How do I benchmark tokens per second on our LLM inference server?",
21
+ "My Artillery arrivalRate is overwhelming the backend",
22
+ "Explain Little's Law and how it applies to load testing",
23
+ "How do I test WebSocket performance?",
24
+ "Set up error budget alerts for our 99.9% SLO"
25
+ ],
26
+ "no_trigger": [
27
+ "Help me write a unit test for my Python function",
28
+ "What is the difference between SQL and NoSQL databases?",
29
+ "How do I set up a React component?",
30
+ "Explain how Docker containers work",
31
+ "Write a REST API endpoint in Express.js",
32
+ "How do I configure ESLint for my project?",
33
+ "What is the best way to learn machine learning?",
34
+ "Help me debug a CSS layout issue",
35
+ "How do I set up a Kubernetes cluster?",
36
+ "Write a GitHub Actions workflow for deploying my app"
37
+ ]
38
+ }
@@ -112,5 +112,29 @@ web_add_header("Authorization", "Bearer {AuthToken}");
112
112
  - Use **Correlation graphs** to overlay server metrics (CPU, memory) from SiteScope/Diagnostics.
113
113
  - Export to Excel or integrate with LoadRunner Cloud for trend analysis across runs.
114
114
 
115
+ ---
116
+
117
+ ## LoadRunner-Specific Tips
118
+
119
+ - **Register correlations before the request** - `web_reg_save_param_regexp` must appear
120
+ *before* the `web_url`/`web_submit_form` that returns the dynamic value. Placing it after
121
+ silently captures nothing.
122
+ - **Use `lr_eval_string()` for debugging** - log parameter values during replay
123
+ (`lr_log_message("Token={AuthToken}")`) to verify correlation is working before scaling VUs.
124
+ - **Avoid `lr_think_time(0)` in Action** - zero think time generates maximum RPS per VU,
125
+ which never reflects real user behavior. Use `lr_think_time(3)` or `lr_user_think_time()`
126
+ with a runtime distribution.
127
+ - **Parameterize with data tables, not hardcoded values** - use `lr_paramarr_idx()` or
128
+ Parameter List in VuGen to feed unique credentials per VU. Hardcoded users cause
129
+ session collisions and cache-hot results.
130
+ - **Set JVM heap for Load Generators** - default LG memory is often too low for 500+ VUs.
131
+ Increase via `mdrv -heap_size` or the LG configuration panel.
132
+ - **Use Goal-Oriented scenarios for capacity tests** - instead of guessing VU counts,
133
+ let Controller auto-adjust to hit a target RPS or response time. This finds the
134
+ saturation point without manual iteration.
135
+ - **Disable extended logging in CI** - `lr_set_debug_message` and extended logs add
136
+ 20-40% overhead. Use standard logging or disable entirely for large runs.
137
+
115
138
  > For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
116
139
  > For CI/CD integration details, see `../topics/test-execution.md`.
140
+ > For correlation strategies across tools, see `../topics/correlation.md`.
@@ -57,5 +57,59 @@ curl -X POST "https://neoload-api.tricentis.com/v3/tests/{testId}/start" \
57
57
  - Integrate with **Dynatrace/AppDynamics** via built-in APM connectors.
58
58
  - Use **as-code YAML definitions** (NeoLoad as Code) for version-controlled test configs.
59
59
 
60
+ ---
61
+
62
+ ## NeoLoad as Code (YAML)
63
+
64
+ Version-control your test definitions instead of relying on the GUI `.nlp` file:
65
+
66
+ ```yaml
67
+ # neoload-project.yml
68
+ name: Checkout-Load-Test
69
+ populations:
70
+ - name: Checkout_Users
71
+ user_paths:
72
+ - name: Checkout_Flow
73
+ distribution: 70%
74
+ - name: Browse_Flow
75
+ distribution: 30%
76
+
77
+ scenarios:
78
+ - name: Regression_Load
79
+ populations:
80
+ - name: Checkout_Users
81
+ load_policy:
82
+ steps:
83
+ - type: ramp
84
+ from: 0
85
+ to: 200
86
+ duration: 120s
87
+ - type: constant
88
+ value: 200
89
+ duration: 600s
90
+ - type: ramp
91
+ from: 200
92
+ to: 0
93
+ duration: 60s
94
+
95
+ sla_profiles:
96
+ - name: Checkout_SLA
97
+ thresholds:
98
+ - per_transaction: Checkout
99
+ avg_response_time:
100
+ warn: 500ms
101
+ fail: 1000ms
102
+ error_rate:
103
+ warn: 1%
104
+ fail: 5%
105
+ ```
106
+
107
+ ```bash
108
+ # Validate and run from CLI
109
+ neoload-cli validate neoload-project.yml
110
+ neoload-cli run --scenario Regression_Load
111
+ ```
112
+
60
113
  > For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
61
114
  > For CI/CD integration details, see `../topics/test-execution.md`.
115
+ > For SLO threshold design, see `../topics/slo-capacity.md`.
@@ -404,3 +404,7 @@ If you need help configuring correlation, copy and paste the following prompt te
404
404
  3. Write the exact extraction syntax for the target tool.
405
405
  4. Show the exact injection syntax (including variable syntax, e.g., `${varName}`, `#{varName}`, `{varName}`).
406
406
  5. Explain how to debug and verify that the correlation succeeded.
407
+
408
+ ---
409
+
410
+ > **See also:** Tool-specific extractor syntax in `../tools/jmeter.md`, `../tools/k6.md`, `../tools/gatling.md`, `../tools/locust.md`, `../tools/loadrunner.md`, `../tools/artillery.md`. Script-level correlation patterns in `script-generation.md`.
@@ -212,3 +212,5 @@ WHERE NOT bl.granted;
212
212
  - [ ] Replication lag monitoring active (if using read replicas)
213
213
  - [ ] Connection pool metrics exposed and dashboarded
214
214
  - [ ] Cleanup script ready for test data removal post-test
215
+
216
+ > **See also:** JDBC sampler setup in `../tools/jmeter.md`. Monitoring and dashboards in `observability.md`. Interpreting saturation and bottleneck signals in `results-analysis.md`.
@@ -87,6 +87,54 @@ Purpose-built LLM benchmarkers surface token metrics natively. Prefer them over
87
87
 
88
88
  ---
89
89
 
90
+ ## Quick Start Commands
91
+
92
+ ```bash
93
+ # vLLM bench serve - max throughput probe with ShareGPT data
94
+ python -m vllm.entrypoints.openai.api_server --model meta-llama/Llama-3-8B &
95
+ python -m vllm bench serve \
96
+ --model meta-llama/Llama-3-8B \
97
+ --endpoint http://localhost:8000/v1/completions \
98
+ --dataset-name sharegpt \
99
+ --request-rate inf \
100
+ --max-concurrency 256 \
101
+ --num-prompts 500
102
+
103
+ # vLLM bench serve - realistic arrival pattern
104
+ python -m vllm bench serve \
105
+ --model meta-llama/Llama-3-8B \
106
+ --endpoint http://localhost:8000/v1/completions \
107
+ --dataset-name sharegpt \
108
+ --request-rate 10 \
109
+ --burstiness 1.0 \
110
+ --num-prompts 200
111
+
112
+ # GuideLLM - production SLA study
113
+ pip install guidedllm
114
+ guidedllm evaluate \
115
+ --model meta-llama/Llama-3-8B \
116
+ --base-url http://localhost:8000/v1 \
117
+ --data emulated --rate 10 --duration 120
118
+
119
+ # NVIDIA GenAI-Perf - multi-backend benchmark
120
+ genai-perf profile \
121
+ --model meta-llama/Llama-3-8B \
122
+ --endpoint-type chat \
123
+ --url localhost:8000 \
124
+ --concurrency 64 \
125
+ --request-count 200
126
+
127
+ # llmperf - quick latency/throughput check
128
+ python token_benchmark_ray.py \
129
+ --model meta-llama/Llama-3-8B \
130
+ --mean-input-tokens 512 \
131
+ --mean-output-tokens 128 \
132
+ --num-concurrent-requests 32 \
133
+ --results-dir ./results
134
+ ```
135
+
136
+ ---
137
+
90
138
  ## Test Design & Methodology
91
139
 
92
140
  1. **Start from real traffic shapes.** Use ShareGPT or captured production traces for prompt/output length distributions. Synthetic `random` datasets are fine for stress but unrealistic for sizing.
@@ -312,3 +312,5 @@ Define performance budgets in CI to prevent regressions:
312
312
  - [ ] Concurrency limits and provisioned concurrency validated
313
313
  - [ ] Frontend Core Web Vitals measured under backend load
314
314
  - [ ] Performance budgets defined and enforced in CI
315
+
316
+ > **See also:** CI/CD pipeline patterns in `test-execution.md`. Kubernetes and mesh monitoring in `observability.md`. SLO headroom for autoscaling decisions in `slo-capacity.md`.
@@ -199,3 +199,5 @@ Synthetic monitors catch regressions that slip through staging without requiring
199
199
  - [ ] Log aggregation active and searchable
200
200
  - [ ] Baseline metrics screenshot taken before test starts (for comparison)
201
201
  - [ ] Metrics retention configured to keep results for trend analysis
202
+
203
+ > **See also:** k6 metric primitives in `../tools/k6.md`. JMeter Backend Listener in `../tools/jmeter.md`. Interpreting the metrics in `results-analysis.md`. SLO thresholds in `slo-capacity.md`.
@@ -212,3 +212,5 @@ If something breaks during a test:
212
212
  4. **Roll back if needed** - restore previous version, restart services.
213
213
  5. **Preserve evidence** - don't restart services without capturing logs and heap dumps.
214
214
  6. **Post-mortem** - document what broke, at what load, what the root cause was.
215
+
216
+ > **See also:** CI/CD execution patterns in `test-execution.md`. Monitoring during production tests in `observability.md`. SLO and error budget framing in `slo-capacity.md`.
@@ -58,6 +58,36 @@ export default function () {
58
58
  - **Connection reuse**: Keep connections open across iterations; don't connect/close per request.
59
59
  - **Streaming throughput**: For server-streaming RPCs, measure messages-per-second, not just request latency.
60
60
  - **Deadline propagation**: Set gRPC deadlines in tests to match production timeouts.
61
+
62
+ ### Gatling gRPC Example
63
+
64
+ ```scala
65
+ // Requires: gatling-grpc plugin (io.gatling:gatling-grpc)
66
+ import io.gatling.core.Predef._
67
+ import io.gatling.grpc.Predef._
68
+ import io.grpc.ManagedChannelBuilder
69
+ import scala.concurrent.duration._
70
+
71
+ class GrpcSimulation extends Simulation {
72
+ val channel = ManagedChannelBuilder
73
+ .forAddress("grpc-server", 50051)
74
+ .usePlaintext()
75
+ .build()
76
+
77
+ val scn = scenario("gRPC Unary")
78
+ .exec(
79
+ grpc("SayHello")
80
+ .rpc(HelloServiceGrpc.METHOD_SAY_HELLO)
81
+ .payload(HelloRequest(greeting = "perf-test"))
82
+ .check(statusCode.is(StatusCode.OK))
83
+ )
84
+ .pause(1)
85
+
86
+ setUp(
87
+ scn.injectOpen(rampUsers(100).during(30.seconds))
88
+ ).protocols(grpc(channel))
89
+ }
90
+ ```
61
91
  - **Load balancer awareness**: gRPC over HTTP/2 with persistent connections can cause uneven load across backends - test with client-side load balancing or L7 proxy.
62
92
  - **Protobuf payload size**: Binary encoding is smaller than JSON - adjust throughput expectations accordingly.
63
93
 
@@ -199,6 +229,39 @@ export default function () {
199
229
  3. **Measure server-side**: File descriptor count, memory per connection, event loop lag.
200
230
  4. **Test reconnection storms**: Kill server, observe client reconnection behavior and server recovery.
201
231
 
232
+ ### Gatling WebSocket Example
233
+
234
+ ```scala
235
+ import io.gatling.core.Predef._
236
+ import io.gatling.http.Predef._
237
+ import scala.concurrent.duration._
238
+
239
+ class WebSocketSimulation extends Simulation {
240
+ val httpProtocol = http.baseUrl("https://app.example.com")
241
+
242
+ val scn = scenario("WebSocket Chat")
243
+ .exec(
244
+ ws("Connect WS")
245
+ .connect("/ws/chat")
246
+ .header("Authorization", "Bearer #{token}")
247
+ )
248
+ .exec(
249
+ ws("Subscribe")
250
+ .sendText("""{"type":"subscribe","channel":"updates"}""")
251
+ .await(30.seconds)(
252
+ ws.checkTextMessage("subscribed")
253
+ .check(bodyJsonPath("$.type").is("subscribed"))
254
+ )
255
+ )
256
+ .pause(30) // hold connection open
257
+ .exec(ws("Close").close)
258
+
259
+ setUp(
260
+ scn.injectOpen(rampUsers(500).during(60.seconds))
261
+ ).protocols(httpProtocol)
262
+ }
263
+ ```
264
+
202
265
  ---
203
266
 
204
267
  ## Message Queue / Event Streaming Testing
@@ -272,3 +335,5 @@ export function teardown() {
272
335
  - [ ] Backpressure / flow control behavior validated
273
336
  - [ ] Error codes and retry behavior tested (gRPC status codes, AMQP nacks, etc.)
274
337
  - [ ] End-to-end latency measured (not just request latency)
338
+
339
+ > **See also:** k6 scripting (all examples above) in `../tools/k6.md`. Gatling gRPC/WebSocket in `../tools/gatling.md`. JMeter JMS/plugins in `../tools/jmeter.md`. Workload design for streaming protocols in `workload-design.md`.
@@ -242,3 +242,5 @@ Structure your report:
242
242
  - Error log samples
243
243
  - Environment configuration
244
244
  ```
245
+
246
+ > **See also:** Metric collection and dashboards in `observability.md`. SLO interpretation and error budgets in `slo-capacity.md`. LLM-specific metrics (TTFT, TPOT, goodput) in `llm-inference.md`.
@@ -39,26 +39,17 @@ Record a HAR file from the browser → import into your tool → clean up and pa
39
39
 
40
40
  ---
41
41
 
42
- ## Correlation Deep Dive
42
+ ## Correlation
43
43
 
44
44
  Correlation is extracting a dynamic value from a response and using it in a subsequent request. Missing correlation is the #1 cause of performance script failure.
45
45
 
46
- ### Values that always need correlation
47
- - **Session tokens** (JSESSIONID, ASP.NET_SessionId)
48
- - **Auth tokens** (JWT, OAuth access_token, refresh_token)
49
- - **CSRF tokens** (`_token`, `authenticity_token`, `__RequestVerificationToken`)
50
- - **View state** (ASP.NET `__VIEWSTATE`, `__EVENTVALIDATION`)
51
- - **Resource IDs** (created order ID, cart ID, uploaded file ID)
52
- - **One-time codes** (OTP, nonce, challenge)
53
- - **Timestamps/signatures** used in request signing
54
-
55
- ### Correlation debugging approach
56
- 1. Run the script with 1 VU.
57
- 2. Look for HTTP 4xx errors (especially 403 Forbidden, 422 Unprocessable Entity).
58
- 3. Check the request body/headers - is a token missing or stale?
59
- 4. Use the tool's debug output or proxy (Fiddler, Charles) to inspect live traffic.
60
- 5. Identify where the value appears in a *previous* response.
61
- 6. Add an extractor at that response, reference the variable in the failing request.
46
+ > **Full reference:** see `correlation.md` for the complete correlation workflow, tool-specific extractor syntax, tech-stack rules (ASP.NET, Java, SAP, OAuth), brittle-vs-robust regex guidance, and the diagnostic playbook.
47
+
48
+ ### Quick checklist
49
+ - Session tokens, CSRF tokens, OAuth codes, resource IDs, and one-time nonces must always be correlated.
50
+ - Run with 1 VU first; 403/422 errors usually mean a missing or stale token.
51
+ - Use a proxy (Fiddler, Charles, mitmproxy) to find where the value appears in a previous response.
52
+ - Add the extractor at that response, reference the variable in the failing request.
62
53
 
63
54
  ---
64
55
 
@@ -219,3 +210,5 @@ Treat performance scripts as production code:
219
210
  - [ ] Single VU smoke test passes cleanly
220
211
  - [ ] Script loads test data from external source (CSV, API)
221
212
  - [ ] Environment-specific values in config/env vars
213
+
214
+ > **See also:** Full correlation reference in `correlation.md`. Parameterization and data feeds in `test-data.md`. Tool-specific syntax in `../tools/k6.md`, `../tools/jmeter.md`, `../tools/gatling.md`, `../tools/locust.md`.
@@ -194,3 +194,5 @@ const user = users[__VU - 1]; // VU 1 gets row 0, VU 2 gets row 1, etc.
194
194
  - [ ] CSV files available on all injector nodes (distributed tests)
195
195
  - [ ] Sensitive data masked/anonymized (not using real PII in test data)
196
196
  - [ ] Date/time sensitive records accounted for (e.g., expiry dates set far in future)
197
+
198
+ > **See also:** Tool-specific parameterization syntax in `../tools/k6.md` (SharedArray), `../tools/jmeter.md` (CSV Data Set Config), `../tools/gatling.md` (feeders), `../tools/locust.md`. Distributing data to injectors in `test-execution.md`.
@@ -114,12 +114,37 @@ bzt tests/load-test.jmx \
114
114
  ```
115
115
 
116
116
  ### AWS (DIY Cloud Execution)
117
- ```bash
118
- # Spin up EC2 injectors via Terraform, then run JMeter/k6
119
- # Use Auto Scaling Groups for burst capacity
120
- # Use S3 to store results, CloudWatch for metrics
121
117
 
122
- # Cost optimization: use Spot instances for injectors (price vs reliability tradeoff)
118
+ ```bash
119
+ # 1. Launch injectors with AWS CLI (or Terraform)
120
+ aws ec2 run-instances \
121
+ --image-id ami-0abcdef1234567890 \
122
+ --instance-type c5.2xlarge \
123
+ --count 4 \
124
+ --spot-price "0.15" \
125
+ --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=load-injector}]'
126
+
127
+ # 2. Install k6 on each injector (via user-data or SSM)
128
+ aws ssm send-command \
129
+ --instance-ids i-0abc i-0def i-0ghi i-0jkl \
130
+ --document-name "AWS-RunShellScript" \
131
+ --parameters 'commands=["sudo apt-get install -y k6"]'
132
+
133
+ # 3. Distribute the test script and run in parallel
134
+ for ip in 10.0.1.{10..13}; do
135
+ scp script.js ec2-user@$ip:~/ && \
136
+ ssh ec2-user@$ip "k6 run --vus 250 --duration 10m script.js --out json=/tmp/results.json" &
137
+ done
138
+ wait
139
+
140
+ # 4. Collect results to S3
141
+ for ip in 10.0.1.{10..13}; do
142
+ scp ec2-user@$ip:/tmp/results.json ./results/$(echo $ip | tr '.' '-')-results.json
143
+ done
144
+ aws s3 cp ./results/ s3://my-load-test-bucket/runs/$(date +%Y%m%d)/ --recursive
145
+
146
+ # Cost optimization: use Spot instances for injectors (60-90% cheaper).
147
+ # Handle interruptions with a 2-min warning hook that flushes partial results.
123
148
  ```
124
149
 
125
150
  ---
@@ -279,3 +304,5 @@ Always monitor the injector resources alongside the SUT:
279
304
  - [ ] Smoke test (1 VU) passed before full run
280
305
  - [ ] Team notified of test window
281
306
  - [ ] Rollback plan in place (especially for production testing)
307
+
308
+ > **See also:** Tool-specific CLI and distributed setup in `../tools/jmeter.md`, `../tools/k6.md`, `../tools/locust.md`, `../tools/gatling.md`, `../tools/artillery.md`. Monitoring during execution in `observability.md`. Production safety controls in `production-testing.md`.