Bound application-owned resources.
No single value defines an application capacity plan. Bound each resource that the application owns and set latency limits at operation boundaries. Then measure the complete configuration under representative peak load.
- Concurrency
- Use a structured server or
Connections.Servercapacity to limit owned connections. A structured server creates exactlyCapacityhandler tasks for the completeServeoperation, including idle periods. - Stack memory
- For homogeneous lightweight tasks, multiply peak live tasks by the measured effective bytes per task. Use
Reserved_Bytesfor guarded virtual address space. Measure RSS for resident memory. - Task-owned regions
- Region storage grows on demand and has no built-in quota. Limit the number and size of admitted phases. Sample
Statisticsand callReleaseat the earliest valid lifetime boundary. - Dormant stacks
- Choose
Minimum_Waitfrom tolerated wake latency and representative host measurements. Accepted cold or page-out advice does not reduce the configured stack capacity. - Parallelism
FLYOLOGY_LOOP_POOL_SIZEselects the initial automatic shared groups, not the task count. Start near the usable CPU parallelism of the workload. Grow withGrow_Configured_Poolwhen measurements support the change. Each created group adds an OS thread, poller, scheduler, and kernel-queue resources.- Latency
- Use finite I/O deadlines, a bounded shutdown drain, and checkpoints in CPU loops. These controls are separate. Cancellation is not a timeout. A fairness quantum is not a hard execution deadline.
Bound admission, not just the listen backlog
The structured-server capacity limits active handlers and reserves the handler task resources. Excess work remains in the kernel listen backlog. It does not create an unbounded user-space task or connection queue.
Handler_Capacity : constant Positive := 256;
Server : aliased HTTP.Server (Capacity => Handler_Capacity);
HTTP.Serve
(Server, Listener, State, Drain_Timeout => 5.0);
Use one deadline for the complete operation
Receive_Exactly and Send_All apply one timeout to the complete multi-step operation. Partial transfers do not restart the timeout. DNS resolution also applies one timeout to family queries, retry rounds, and transport fallback.
Prefer finite deadlines at service boundaries. If the scope does not have an explicit shutdown and cancellation path, do not use Infinite.
Add checkpoints to bounded units of CPU work
A CPU-bound lightweight task can occupy its group until it suspends, executes delay 0.0, or calls a fairness checkpoint. Priorities select among ready fibers in a group, but they do not preempt arbitrary lightweight instructions.
A new Yield_Budget uses a 2 ms quantum. Configure a different quantum when the service requires a different cooperative interval.
Budget : Flyology.Fairness.Yield_Budget;
Budget.Configure (Ada.Real_Time.Microseconds (250));
while More_Work loop
Process_One_Item;
Budget.Checkpoint;
end loop;
Choose a quantum below the tolerated same-group scheduling delay, then measure it. The value is elapsed wall-clock time between eligible yields, not reserved CPU time.
Put Checkpoint after a bounded unit of work. For example, a 250 µs quantum cannot interrupt a Process_One_Item call that runs for 50 ms. The checkpoint takes effect after the call returns. Very small quanta also increase clock reads and scheduler transfers.