W0016: budget_advisory
W0016 budget_advisory — a memory budget whose proof is incomplete.
A warning of soma check, the checker of the Soma programming language (soma explain W0016).
The rule
When a cell declares a memory budget (scale { memory: "128Mi" }), soma check tries to prove the cell's peak memory stays under it; W0016 is the advisory it prints when a handler allocates something with no static bound, so the proof is incomplete. It names each such call site, here http_get, whose response size is not bounded. Bound the allocation, here with the max_bytes option (http_get(url, map("max_bytes", 65536))), and check then reports that the budget holds.
A program that triggers it
wrong.cell
cell RateFeed {
memory {
fetched: Map<String, Int> [persistent, capacity(200)]
}
on refresh(currency: String) {
let reply = http_get("https://api.example.com/rates/{currency}")
fetched.set(currency, now())
return reply
}
scale {
replicas: 1
memory: "128Mi"
}
}What soma check prints:
$ soma check wrong.cell
advisory: cell 'RateFeed' declares budget 128.00 MiB; bounded portion is 16.84 MiB, but these handler allocations have no bound, so the proof is incomplete:
→ http_get at call site — HTTP response size is not statically bounded
✓ 1 warning(s), no errors.The fix field of soma check --json: Review and address the reported warning.
The fix
On line 6, let reply = http_get("https://api.example.com/rates/{currency}") becomes let reply = http_get("https://api.example.com/rates/{currency}", map("max_bytes", 65536)).
wrong.cell → right.cell
--- wrong.cell
+++ right.cell
@@ -4,5 +4,5 @@
}
on refresh(currency: String) {
- let reply = http_get("https://api.example.com/rates/{currency}")
+ let reply = http_get("https://api.example.com/rates/{currency}", map("max_bytes", 65536))
fetched.set(currency, now())
return replyWith the fix, soma check accepts the program:
$ soma check right.cell
✓ budget holds for cell 'RateFeed' while its slots stay within their assumed sizes: peak ≤ 24.91 MiB ≤ declared 128.00 MiB
breakdown: slots 862.50 KiB + max-handler 8.06 MiB + state 0 B + runtime 16.00 MiB
assumed: each slot within [capacity(N)] / [max_key_bytes(N)] / [max_value_bytes(N)] (else 10 000 entries of 256-byte keys and 4 KiB values) — not enforced at run time
✓ All checks passed (1 note above).