Auto: twincat-2.2 — handle-based access with caching

Closes #311
This commit is contained in:
Joseph Doherty
2026-04-25 22:03:20 -04:00
parent 4a071b6d5a
commit b67eb6c8d0
8 changed files with 687 additions and 15 deletions

View File

@@ -154,6 +154,36 @@ The required fixture state (1000-DINT GVL + churn POU) is documented in
`TwinCatProject/README.md §Performance scenarios`; XAE-form sources land at
`TwinCatProject/PLC/GVLs/GVL_Perf.TcGVL` + `TwinCatProject/PLC/POUs/FB_PerfChurn.TcPOU`.
### Handle caching (PR 2.2)
Per-tag reads / writes route through an in-process ADS variable-handle cache.
The first read of a symbol resolves a handle via `CreateVariableHandleAsync`;
subsequent reads / writes of the same symbol issue against the cached handle.
On the wire this trades a multi-byte symbolic path (`GVL_Perf.aTags[742]` =
20+ bytes) for a 4-byte handle, and the device server skips name resolution
on every subsequent op. Cache lifetime is process-scoped; entries are evicted
on `AdsErrorCode.DeviceSymbolVersionInvalid` (with one retry against a fresh
handle), wiped on reconnect (handles are per-AMS-session), and deleted
best-effort on driver disposal.
`TwinCATHandleCachePerfTests.Driver_handle_cache_avoids_repeat_symbol_resolution`
asserts the contract on real XAR by reading 50 symbols twice and verifying
the second pass issues zero new `CreateVariableHandleAsync` calls. It runs
under the standard `[TwinCATFact]` gate (XAR reachable; no `TWINCAT_PERF`
opt-in needed because 50 symbols is cheap).
**Staleness caveat**: handles can go stale after a TwinCAT online change
(POU edit + activate). Until PR 2.3 ships the proactive Symbol-Version
invalidation listener, the safety net is twofold: (1) the
`DeviceSymbolVersionInvalid` evict-and-retry path catches cases where the
descriptor moves but the symbol survives, and (2) operators can call
`ITwinCATClient.FlushOptionalCachesAsync` manually after a known online
change to wipe the cache without forcing a full reconnect. The bulk
Sum-read / Sum-write path remains on symbolic paths in PR 2.2 (the bulk
path's per-call symbol resolution is already amortised across N tags;
the perf delta vs. handle-batched bulk is marginal — tracked as a
follow-up for the Phase-2 perf sweep).
## Follow-up candidates
1. **XAR VM live-population** — scaffolding is in place (this PR); the