ados-plugins.slice cgroup. This page covers the budgets, how to spot
when you blow them, and how to profile.
Default budgets
When a plugin’s manifest does not declare resources, it gets:
Declare different caps in the manifest:
max_ram_mb to
MemoryMax, max_cpu_percent to CPUQuota, max_pids to TasksMax.
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.”
Read the throttle stats from the unit’s cgroup (the unit name is
ados-plugin-<id> with the dots in your plugin id replaced by hyphens):
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 on failure, and repeated kills that exceed the start
limit move the plugin to failed.
memory.events shows low, high, max, oom, 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, granted
permissions, and recent events. Pair it with the cgroup stat files above
and the durable log query for a full picture:
Profiling Python plugins
The SDK does not bundle a profiler; usecProfile or pyinstrument
inside your own start path:
/var/log/ados/plugins/<id>.log, so
profiler output lands there (or read it with
journalctl -u ados-plugin-<id>.service).
Profiling TypeScript plugins
Open the GCS in developer mode, 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 plugin that blocks the loop stops responding and the supervisor restarts it. 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
Disk I/O is a common cause of throttling. A plugin writing a megabyte of samples per second to an SD card is already at the sustained-write ceiling for the cheap end of the market. Batch writes (onefsync per
second is plenty), compress logs, and rotate them.
Plugins with network.outbound share the drone’s link with telemetry and
video. Pulling large payloads in flight is a UX bug; pull during ground
time and cache.