Skip to content

Commit 6a43e5e

Browse files
author
rhamlett_microsoft
committed
Added load test endpoint feature
1 parent 81e9dd7 commit 6a43e5e

File tree

10 files changed

+1930
-5
lines changed

10 files changed

+1930
-5
lines changed

src/PerfProblemSimulator/Controllers/LoadTestController.cs

Lines changed: 400 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
* =============================================================================
3+
* LOAD TEST REQUEST MODEL - AI PORTABILITY DOCUMENTATION
4+
* =============================================================================
5+
*
6+
* PURPOSE:
7+
* Defines the input parameters for load test requests. All parameters have
8+
* sensible defaults, making the request body optional.
9+
*
10+
* JSON EXAMPLE:
11+
* {
12+
* "workIterations": 1000,
13+
* "bufferSizeKb": 5,
14+
* "softLimit": 50,
15+
* "degradationFactor": 5
16+
* }
17+
*
18+
* OR with defaults (empty body or null):
19+
* {}
20+
*
21+
* PORTING TO OTHER LANGUAGES:
22+
* - PHP: class LoadTestRequest { public int $workIterations = 1000; ... }
23+
* - Node.js: interface LoadTestRequest { workIterations?: number; ... }
24+
* - Java: public class LoadTestRequest { private int workIterations = 1000; ... }
25+
* - Python: @dataclass class LoadTestRequest: work_iterations: int = 1000
26+
*
27+
* =============================================================================
28+
*/
29+
30+
namespace PerfProblemSimulator.Models;
31+
32+
/// <summary>
33+
/// Request parameters for load test endpoint.
34+
/// All properties have defaults, making the request body optional.
35+
/// </summary>
36+
/// <remarks>
37+
/// <para>
38+
/// <strong>PARAMETER TUNING GUIDE:</strong>
39+
/// </para>
40+
/// <list type="bullet">
41+
/// <item>
42+
/// <term>workIterations</term>
43+
/// <description>
44+
/// Higher values = more CPU time per request. Start with 1000 and adjust
45+
/// based on your instance size. On a Basic B1, 1000 iterations takes ~5-10ms.
46+
/// </description>
47+
/// </item>
48+
/// <item>
49+
/// <term>bufferSizeKb</term>
50+
/// <description>
51+
/// Memory allocated per request. Released after request completes.
52+
/// 5KB is lightweight; increase for memory pressure testing.
53+
/// </description>
54+
/// </item>
55+
/// <item>
56+
/// <term>softLimit</term>
57+
/// <description>
58+
/// Concurrent requests before degradation starts. Lower = earlier degradation.
59+
/// Tune based on expected normal load. 50 is good for typical web apps.
60+
/// </description>
61+
/// </item>
62+
/// <item>
63+
/// <term>degradationFactor</term>
64+
/// <description>
65+
/// Milliseconds of delay added per request OVER the soft limit.
66+
/// Higher = steeper degradation curve. 5ms is moderate.
67+
///
68+
/// Example: softLimit=50, degradationFactor=5
69+
/// - 60 concurrent: (60-50) * 5 = 50ms added delay
70+
/// - 100 concurrent: (100-50) * 5 = 250ms added delay
71+
/// - 200 concurrent: (200-50) * 5 = 750ms added delay
72+
/// </description>
73+
/// </item>
74+
/// </list>
75+
/// </remarks>
76+
public class LoadTestRequest
77+
{
78+
/*
79+
* =========================================================================
80+
* DEFAULT VALUES
81+
* =========================================================================
82+
*
83+
* These defaults are designed to create ~100ms baseline response time
84+
* on a typical Azure App Service instance (B1/S1).
85+
*
86+
* Adjust based on your target environment:
87+
* - Larger instances: Increase workIterations for similar response times
88+
* - Smaller instances: Decrease workIterations to avoid excessive load
89+
*/
90+
91+
/// <summary>
92+
/// Number of SHA256 hash iterations to perform for CPU work.
93+
/// </summary>
94+
/// <remarks>
95+
/// <para>
96+
/// <strong>DEFAULT: 1000</strong>
97+
/// </para>
98+
/// <para>
99+
/// Each iteration computes a SHA256 hash. The output of each hash
100+
/// becomes the input for the next iteration, preventing compiler
101+
/// optimization.
102+
/// </para>
103+
/// <para>
104+
/// <strong>PERFORMANCE REFERENCE:</strong>
105+
/// <list type="bullet">
106+
/// <item>1000 iterations ≈ 5-10ms on B1/S1</item>
107+
/// <item>5000 iterations ≈ 25-50ms on B1/S1</item>
108+
/// <item>10000 iterations ≈ 50-100ms on B1/S1</item>
109+
/// </list>
110+
/// </para>
111+
/// </remarks>
112+
public int WorkIterations { get; set; } = 1000;
113+
114+
/// <summary>
115+
/// Size of memory buffer to allocate in kilobytes.
116+
/// </summary>
117+
/// <remarks>
118+
/// <para>
119+
/// <strong>DEFAULT: 5 KB</strong>
120+
/// </para>
121+
/// <para>
122+
/// This memory is allocated at the start of request processing and
123+
/// released when the request completes (garbage collected).
124+
/// </para>
125+
/// <para>
126+
/// The buffer is "touched" (written to and read from) to ensure actual
127+
/// memory allocation occurs and isn't optimized away.
128+
/// </para>
129+
/// </remarks>
130+
public int BufferSizeKb { get; set; } = 5;
131+
132+
/// <summary>
133+
/// Number of concurrent requests before degradation delays begin.
134+
/// </summary>
135+
/// <remarks>
136+
/// <para>
137+
/// <strong>DEFAULT: 50</strong>
138+
/// </para>
139+
/// <para>
140+
/// When concurrent requests exceed this limit, additional delay is
141+
/// added proportional to how far over the limit we are.
142+
/// </para>
143+
/// <para>
144+
/// <strong>SOFT LIMIT CONCEPT:</strong>
145+
/// Unlike a hard limit (which would reject requests), a soft limit
146+
/// gracefully degrades performance. This mimics real application
147+
/// behavior where resources become contended under load.
148+
/// </para>
149+
/// <para>
150+
/// <strong>TUNING GUIDE:</strong>
151+
/// <list type="bullet">
152+
/// <item>Lower softLimit = Earlier degradation, better for testing thresholds</item>
153+
/// <item>Higher softLimit = Later degradation, requires more load to see effects</item>
154+
/// </list>
155+
/// </para>
156+
/// </remarks>
157+
public int SoftLimit { get; set; } = 50;
158+
159+
/// <summary>
160+
/// Milliseconds of delay added per concurrent request over the soft limit.
161+
/// </summary>
162+
/// <remarks>
163+
/// <para>
164+
/// <strong>DEFAULT: 5 ms</strong>
165+
/// </para>
166+
/// <para>
167+
/// <strong>DEGRADATION FORMULA:</strong>
168+
/// <code>
169+
/// additionalDelay = max(0, currentConcurrent - softLimit) * degradationFactor
170+
/// </code>
171+
/// </para>
172+
/// <para>
173+
/// <strong>EXAMPLES (softLimit=50, degradationFactor=5):</strong>
174+
/// <list type="bullet">
175+
/// <item>30 concurrent → 0ms added (below soft limit)</item>
176+
/// <item>60 concurrent → 50ms added ((60-50) × 5)</item>
177+
/// <item>100 concurrent → 250ms added ((100-50) × 5)</item>
178+
/// <item>200 concurrent → 750ms added ((200-50) × 5)</item>
179+
/// <item>500 concurrent → 2250ms added ((500-50) × 5)</item>
180+
/// </list>
181+
/// </para>
182+
/// <para>
183+
/// <strong>REACHING 230s TIMEOUT:</strong>
184+
/// To reach Azure's 230s timeout with these defaults:
185+
/// (230000ms - 100ms base) / 5ms = 45980 requests over soft limit
186+
/// So: 50 + 45980 = ~46000 concurrent requests
187+
///
188+
/// For faster degradation, increase degradationFactor:
189+
/// - degradationFactor=50: ~4650 concurrent requests to timeout
190+
/// - degradationFactor=100: ~2350 concurrent requests to timeout
191+
/// </para>
192+
/// </remarks>
193+
public int DegradationFactor { get; set; } = 5;
194+
}

0 commit comments

Comments
 (0)