@@ -77,6 +77,14 @@ otopcua-twincat-cli read -n 192.168.1.40.1.1 -s "Recipe[3]" -t Real
|
||||
otopcua-twincat-cli read -n 192.168.1.40.1.1 -s GVL.sMessage -t WString
|
||||
```
|
||||
|
||||
ADS variable handles for `read` / `write` symbols are cached transparently
|
||||
inside the CLI's underlying `AdsTwinCATClient`. The first read of a symbol
|
||||
resolves a handle; repeats reuse the cached handle for smaller AMS payloads
|
||||
and skipped name resolution. The cache wipes on reconnect, on
|
||||
`DeviceSymbolVersionInvalid` (with a one-shot retry), and on CLI exit. See
|
||||
`docs/drivers/TwinCAT-Test-Fixture.md §Handle caching` for the full story
|
||||
including the staleness caveat after an online change.
|
||||
|
||||
### `write`
|
||||
|
||||
```powershell
|
||||
@@ -99,3 +107,7 @@ otopcua-twincat-cli subscribe -n 192.168.1.40.1.1 -s GVL.Counter -t DInt -i 500
|
||||
|
||||
The subscribe banner announces which mechanism is in play — "ADS notification"
|
||||
or "polling" — so it's obvious in screen-recorded bug reports.
|
||||
|
||||
`--poll-only` polls go through the same cached-handle path as `read`, so
|
||||
repeated polls of the same symbol carry only a 4-byte handle on the wire
|
||||
rather than the full symbolic path.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user