code wiki / (root) / nx_load_test_harness.nx

nx_load_test_harness.nx source

↩ module page · 186 lines · 8898 B

1// nx_load_test_harness.nx -- N-concurrent-user capacity probe. 2// 3// module: nishi-core.perception.load_test_harness 4// depends: nishi-core.perception.profile + nishi-core.perception.external_reach_probe + 5// nishi-core.perception.perceptual_dataset + nishi-core.net.socket + nishi-core.io.syscalls 6// disk_kb: 5 7// capability: PERCEPTION 8// wired_status: PARTIAL_WIRED 9// 10// MISSING_CAPABILITIES: 11// - CONCURRENT_CONNECT_DISPATCH (issue N parallel TCP+TLS+HTTP connects via 12// nx_socket + nx_tls13_client + nx_https_client; all FULLY_WIRED; 13// wire the call site through a scheduler that respects 14// nx_cooperative_resource_arbitration budgets) 15// - LATENCY_PERCENTILE_AGGREGATION (p50 / p95 / p99 / pmax + error rate 16// in single pass without buffering all responses) 17// - WS_LOAD_DISPATCH (WebSocket-frames-per-second sustain test for the 18// /video chat substrate specifically) 19// - WEBRTC_PEER_LOAD (simulate N peer mesh connections with SRTP-like 20// payload; gates the family-chat capacity claim) 21// 22// license_tier: PUBLIC_NISHI_SUBSTRATE 23// genealogy_id: feedback-substrate-does-heavy-lifting-user-is-partner-not-gate_2026 + 24// feedback-substrate-primitives-meta-not-one-off_2026 + 25// feedback-real-playtest-loop-not-just-logs + 26// nx_realism_score + 27// NISHIFAMILY_VIDEO_HARDENING_2026-05-20 + 28// wrk_2012_http_benchmarking + 29// vegeta_2013_http_load_testing 30// 31// User directive 2026-05-20: "real heavy heavy testing... how many users 32// can interact well, if it does message spam, all that bullshit." 33// 34// THIS primitive issues N concurrent virtual users against ANY endpoint 35// (HTTP/HTTPS landing page, WebSocket chat frames, simulated WebRTC peer 36// mesh) and reports latency percentiles + error rate + sustained 37// throughput. Distinct from nx_external_reach_probe (which is one 38// probe at a time): this is sustained concurrent load to find the 39// capacity knee. 40// 41// First measurements 2026-05-20 against nishifamily.com/video from INSIDE 42// the NAS via curl-based bench (companion shell script): 43// N=10 parallel: p50=0.95s p99=0.98s 10/10 OK 44// N=50 parallel: p50=3.41s p99=4.57s 50/50 OK (DEGRADED) 45// N=200 parallel: p50=15.07s p99=18.38s 198/200 OK (2 errors, BROKEN) 46// 47// Reuse set: 48// - nishifamily.com/video capacity ceiling (PRIMARY for today) 49// - Prey-spec dog toy production-line load test (N toys reporting in 50// simultaneously when staff swap power) 51// - Livestock acoustic welfare gateway N-sensor sustain (farm with 52// 100 cattle each with a sensor) 53// - Conservation recorder bulk-upload (overnight bulk push from 54// N field recorders to a central ingest) 55// - Vet-clinic stethoscope concurrent-N-room (clinic with N exam rooms) 56// - Beekeeping hive-sensor swarm (apiary with N hives reporting) 57// - Generic any-endpoint sustain stress test for substrate 58 59import "nx_syscalls.nx" 60import "nx_perceptual_profile.nx" 61import "nx_external_reach_probe.nx" 62import "nx_perceptual_dataset.nx" 63 64// ===== Load profile sealed enum ================================== 65 66const NX_LT_PROFILE_HTTP_GET: i64 = 1 // simple GET 67const NX_LT_PROFILE_HTTP_POST: i64 = 2 // form submit / API 68const NX_LT_PROFILE_WS_CHAT_BURST: i64 = 3 // N message frames/sec 69const NX_LT_PROFILE_WS_LONG_LIVED: i64 = 4 // N connections held open 70const NX_LT_PROFILE_WEBRTC_PEER_MESH: i64 = 5 // mesh with N participants 71const NX_LT_PROFILE_FILE_DOWNLOAD: i64 = 6 // N parallel large downloads 72const NX_LT_PROFILE_DNS_QUERY_FLOOD: i64 = 7 // DNS amplification 73 // resistance test 74const NX_LT_PROFILE_TLS_HANDSHAKE_STORM: i64 = 8 // N TLS handshakes in 75 // burst (handshake-only) 76 77func nx_lt_profile_name(p: i64) -> *u8 { 78 if p == NX_LT_PROFILE_HTTP_GET { return "HTTP_GET" } 79 if p == NX_LT_PROFILE_HTTP_POST { return "HTTP_POST" } 80 if p == NX_LT_PROFILE_WS_CHAT_BURST { return "WS_CHAT_BURST" } 81 if p == NX_LT_PROFILE_WS_LONG_LIVED { return "WS_LONG_LIVED" } 82 if p == NX_LT_PROFILE_WEBRTC_PEER_MESH { return "WEBRTC_PEER_MESH" } 83 if p == NX_LT_PROFILE_FILE_DOWNLOAD { return "FILE_DOWNLOAD" } 84 if p == NX_LT_PROFILE_DNS_QUERY_FLOOD { return "DNS_QUERY_FLOOD" } 85 if p == NX_LT_PROFILE_TLS_HANDSHAKE_STORM { return "TLS_HANDSHAKE_STORM" } 86 return "UNKNOWN_PROFILE" 87} 88 89// ===== Verdicts =================================================== 90// 91// Capacity is grade-discretized so substrate can name "still S-class up 92// to N=10, drops to A at N=50, F at N=200" without ambiguity. 93 94const NX_LT_VERDICT_S_CLASS: i64 = 5 // p99 <= 100 ms, 100% success 95const NX_LT_VERDICT_A_CLASS: i64 = 4 // p99 <= 500 ms 96const NX_LT_VERDICT_B_CLASS: i64 = 3 // p99 <= 2 s 97const NX_LT_VERDICT_C_CLASS: i64 = 2 // p99 <= 5 s 98const NX_LT_VERDICT_D_CLASS: i64 = 1 // p99 <= 30 s 99const NX_LT_VERDICT_F_BROKEN: i64 = 0 // any errors OR p99 > 30s 100const NX_LT_VERDICT_DEPENDENCY_MISSING: i64 = -1 // PARTIAL_WIRED default 101 102func nx_lt_verdict_name(v: i64) -> *u8 { 103 if v == NX_LT_VERDICT_S_CLASS { return "S_CLASS" } 104 if v == NX_LT_VERDICT_A_CLASS { return "A_CLASS" } 105 if v == NX_LT_VERDICT_B_CLASS { return "B_CLASS" } 106 if v == NX_LT_VERDICT_C_CLASS { return "C_CLASS" } 107 if v == NX_LT_VERDICT_D_CLASS { return "D_CLASS" } 108 if v == NX_LT_VERDICT_F_BROKEN { return "F_BROKEN" } 109 if v == NX_LT_VERDICT_DEPENDENCY_MISSING { return "DEPENDENCY_MISSING" } 110 return "UNKNOWN_LT_VERDICT" 111} 112 113// ===== Load test config + result structs ========================== 114 115struct NxLoadTestConfig { 116 endpoint_url_ptr: *u8 117 endpoint_url_len: i64 118 profile: i64 // NX_LT_PROFILE_* 119 concurrency_n: i64 // virtual-user count 120 duration_seconds: i64 // for sustained tests 121 requests_per_user: i64 // for finite-burst tests 122 ramp_up_seconds: i64 // 0 = thundering-herd; >0 = staggered 123 per_request_timeout_ms: i64 124 payload_size_bytes: i64 // POST / WS / RTP-like simulation 125 target_profile: i64 // optional: which species perceptual 126 // envelope to gate "acceptable latency" 127 // against 128} 129 130struct NxLoadTestResult { 131 config_hash_ptr: *u8 132 config_hash_len: i64 133 timestamp_unix_ms: i64 134 overall_verdict: i64 // NX_LT_VERDICT_* 135 requests_attempted: i64 136 requests_succeeded: i64 137 requests_errored: i64 138 p50_latency_ms: i64 139 p95_latency_ms: i64 140 p99_latency_ms: i64 141 pmax_latency_ms: i64 142 sustained_rps: i64 // requests/sec achieved 143 bytes_throughput_per_s: i64 144} 145 146// ===== Top-level entry stubs ====================================== 147 148// nx_load_test_run -- execute the configured load profile once. 149 150func nx_load_test_run(config_ptr: *NxLoadTestConfig, 151 result_out_ptr: *NxLoadTestResult) -> i64 { 152 if config_ptr == 0 as *NxLoadTestConfig { return NX_LT_VERDICT_F_BROKEN } 153 // PARTIAL_WIRED: concurrent dispatch + percentile aggregation queued. 154 return NX_LT_VERDICT_DEPENDENCY_MISSING 155} 156 157// nx_load_test_find_capacity_knee -- sweep concurrency from 1 to N_max, 158// binary-search the point where verdict drops from B-or-better to C-or-worse. 159// "What's the capacity ceiling for acceptable latency?" answered directly. 160 161func nx_load_test_find_capacity_knee(endpoint_url_ptr: *u8, endpoint_url_len: i64, 162 profile: i64, 163 n_min: i64, n_max: i64, 164 acceptable_verdict_floor: i64) -> i64 { 165 if endpoint_url_len <= 0 { return 0 } 166 if profile < NX_LT_PROFILE_HTTP_GET { return 0 } 167 if profile > NX_LT_PROFILE_TLS_HANDSHAKE_STORM { return 0 } 168 if n_min < 1 { return 0 } 169 if n_max < n_min { return 0 } 170 if acceptable_verdict_floor < NX_LT_VERDICT_F_BROKEN { return 0 } 171 return 0 172} 173 174// nx_load_test_persist_to_dataset -- record the result in 175// nx_perceptual_dataset as a VALIDATION entry so the capacity curve is 176// preserved over time + regression-detectable. 177 178func nx_load_test_persist_to_dataset(result_ptr: *NxLoadTestResult) -> i64 { 179 return 0 180} 181 182// nx_load_test_get_last_verdict -- inspector. 183 184func nx_load_test_get_last_verdict() -> i64 { 185 return NX_LT_VERDICT_DEPENDENCY_MISSING 186}