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.
- package/.claude-plugin/marketplace.json +14 -6
- package/.claude-plugin/plugin.json +2 -2
- package/README.md +22 -2
- package/package.json +7 -2
- package/skills/perf/SKILL.md +10 -10
- package/skills/perf/evals/evals.json +80 -0
- package/skills/perf/evals/trigger-eval.json +38 -0
- package/skills/perf/references/tools/loadrunner.md +24 -0
- package/skills/perf/references/tools/neoload.md +54 -0
- package/skills/perf/references/topics/correlation.md +4 -0
- package/skills/perf/references/topics/database-testing.md +2 -0
- package/skills/perf/references/topics/llm-inference.md +48 -0
- package/skills/perf/references/topics/modern-architectures.md +2 -0
- package/skills/perf/references/topics/observability.md +2 -0
- package/skills/perf/references/topics/production-testing.md +2 -0
- package/skills/perf/references/topics/protocol-testing.md +65 -0
- package/skills/perf/references/topics/results-analysis.md +2 -0
- package/skills/perf/references/topics/script-generation.md +10 -17
- package/skills/perf/references/topics/test-data.md +2 -0
- package/skills/perf/references/topics/test-execution.md +32 -5
|
@@ -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
|
|
9
|
-
"version": "
|
|
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
|
|
16
|
-
"version": "
|
|
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
|
-
"
|
|
76
|
-
"
|
|
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": "
|
|
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": "
|
|
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
|
],
|
package/skills/perf/SKILL.md
CHANGED
|
@@ -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
|
|
97
|
-
| **Open source** | ✅ | ✅ | ✅ | ✅ |
|
|
98
|
-
| **Protocol support** | HTTP, JDBC, JMS, MQTT, FTP, gRPC | HTTP, gRPC, WS | HTTP, JMS, gRPC | HTTP, gRPC | HTTP, gRPC, WS,
|
|
99
|
-
| **Developer-friendly** | Medium | High | High | High |
|
|
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
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
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
|
-
|
|
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`.
|