Feature request: async LiveAPI / batched LOM reads for performance-critical M4L devices

Daniel Mooney's icon

I'm building a Max for Live device that walks the Live Object Model on set load — reading every track, device, and device parameter to maintain a live session mirror over a local WebSocket. On heavy sets (30+ tracks, 80+ devices, thousands of parameters), the initial walk beachballs Ableton for ~45 seconds.

The root cause is well-understood: every new LiveAPI(...), .get(), .call(), and .property from the js object is a synchronous round-trip to Live's main thread. The js engine runs on the low-priority thread, but that doesn't help — the LiveAPI calls still block Live's UI thread while they complete. There's no way to batch reads or issue them asynchronously.

I've thrown every optimization I can at this from the M4L side:

- Retargeting hot handles instead of constructing new LiveAPI objects (each new LiveAPI registers in a per-device table that never shrinks, and its lookup degrades to a linked-list crawl at scale)

- Per-tick operation budgets with resume cursors so periodic sweeps have constant main-thread cost

- Dirty-flag gating so reconcile passes only read what actually changed

- Deferring parameter attachment out of observer callbacks into coalesced Tasks

- Caching stable facts (property names, track types) to avoid redundant probes

These help with steady-state performance, but the initial walk is irreducible — you genuinely need to read every track, every device, and every parameter at least once, and each read is a synchronous IPC to Live's main thread.

What would help enormously:

1. Batched reads — a single call that takes an array of LOM paths + property names and returns all values in one round-trip, instead of one IPC per .get().

2. Async LiveAPI — .getAsync() / .callAsync() that return Promises and don't block Live's main thread while the js engine waits. Even if the reads themselves are still serialized on Live's side, decoupling the js wait from the main thread would eliminate the beachball.

3. Bulk snapshot — something like LiveAPI.snapshot(path, depth) that returns a JSON tree of an object and its children's properties in one call.

Any one of these would be transformative for M4L devices that need to read the session state comprehensively. The current model — one synchronous IPC per property read, no batching, no async — makes it effectively impossible to build responsive M4L tools for large sessions.

Is there any interest in this direction, or any workarounds I've missed? Happy to provide profiling data or a minimal repro.