ados-plugins.slice
cgroup. This page covers the budgets, how to spot when you blow them, and
how to profile. Unit, cgroup and log names are explained on
Agent runtime and sandbox.
Default budgets
When a plugin’s manifest does not declare resources, it gets:
Declare different caps in the manifest:
class: heavy (first-party only) raises the ceilings to 65536 MB, 3200 %
and 4096 PIDs. A third-party manifest that sets it is refused at install.
Honest declarations matter. The operator sees the requested budget in the
install dialog. Asking for far more than you use is a bad signal; asking
for too little ends with the kernel killing your process.
The caps map straight to the plugin’s unit: max_ram_mb to MemoryMax,
max_cpu_percent to CPUQuota, max_pids to TasksMax.
Find the plugin’s cgroup
The unit name carries an 8-hex hash, so ask systemd for the cgroup path rather than building it:/sys/fs/cgroup in the commands below.
Spotting cgroup throttling
max_cpu_percent is enforced by the cgroup CPU controller. A plugin that
breaches it does not crash; it gets throttled. The symptom is “everything
got slower for no reason.”
nr_throttled. If it climbs every second, your
plugin is over budget. Optimize the code or declare a higher
max_cpu_percent.
Memory pressure
max_ram_mb is enforced by MemoryMax. A breach OOM-kills the process.
The unit restarts 2 s after each kill, indefinitely, so a plugin stuck over
its cap loops rather than stopping; watch oom_kill in memory.events
climb.
memory.events shows low, high, max, oom and oom_kill counters.
Any non-zero high or max means the kernel started applying pressure.
To stay under the cap:
- Process events on a bounded queue, not an unbounded list.
- For ML models, prefer quantized weights (int8 over fp32).
- Stream files; do not load whole logs into RAM.
- Use
array.arrayornumpyover a Python list of floats.
Inspecting a running plugin
ados plugin info <id> shows the plugin’s recorded state and granted
permissions. Pair it with the cgroup counters above and the plugin’s log:
Profiling Python plugins
The SDK does not bundle a profiler; usecProfile or pyinstrument
inside your own start path:
ados plugin logs <id>.
Profiling TypeScript plugins
Open Mission Control, pick the plugin’s iframe in browser devtools (Sources tab), and use the Performance recorder. The iframe is a real browsing context with the standard devtools surface. Common GCS hot paths:- React re-renders triggered by every telemetry event. Coalesce with
requestAnimationFrameand a local ref. - Heavy SVG redraws. Switch to canvas past a few hundred paths.
- Synchronous JSON parse in the message handler. Move it off the main thread.
Event-loop discipline
The biggest cause of agent-plugin stalls is a blocked event loop. A blocked loop stalls every IPC call and subscription; nothing restarts it for you. Don’t:time.sleep(...)in async code.- Heavy CPU work directly in
on_start. - Synchronous I/O on a slow disk.
await asyncio.sleep(...).await asyncio.to_thread(heavy_work).aiofilesor chunked reads for slow I/O.
Disk and network discipline
The plugin slice runs at a low I/O weight, so a plugin that writes hard loses every contended block to the flight services and stalls itself. A plugin writing a megabyte of samples per second to an SD card is already at the sustained-write ceiling for cheap cards. Batch writes (onefsync per
second is plenty) and keep your own files bounded.
Plugins with network.outbound share the drone’s link with telemetry and
video. Pull large payloads during ground time and cache them.
Thermal behavior
Sustained high CPU on a small SoC raises its temperature, and the kernel eventually throttles the whole package, which shows up as throttle events on every plugin, not just yours. A well-behaved plugin watches the system telemetry and backs off before the kernel forces the issue.Next steps
Versioning and updates
Semver, compatibility ranges and automatic updates.
Agent runtime and sandbox
Unit names, sandbox, restart policy and logs.