Part of #753.
Goal
Migrate the PerfTest Workshop server sample to AsyncCustomNodeManager. It builds a large address space by hand (no generated model), so Step 2 (Fluent) does not apply. This sample is performance-sensitive — the migration should demonstrate the benefit of the async two-tier locking model.
Scope
Workshop/PerfTest/Server/PerfTestNodeManager.cs — PerfTestNodeManager : CustomNodeManager2
Workshop/PerfTest/Server/PerfTest Server.csproj and its node-manager registration
Do not touch the client project.
Step 1 — AsyncCustomNodeManager
- Base class
CustomNodeManager2 → AsyncCustomNodeManager; constructor base(server, configuration, <namespaceUri>).
CreateAddressSpace → override async ValueTask CreateAddressSpaceAsync(...); bulk-create the large node set with await AddPredefinedNodeAsync / await AddNodeAsync.
- Remove the global
lock (Lock) around reads — rely on per-node read locking so the many simulated variables can be read in parallel. Keep writes under the base write semaphore.
- If values are produced independently of writes (timer/simulation), consider
useSamplingGroups: true on the base constructor; otherwise keep the default change-triggered manager and push updates via await ClearChangeMasksAsync.
- Register via
IAsyncNodeManagerFactory.
Acceptance criteria
PerfTestNodeManager derives from AsyncCustomNodeManager; no CustomNodeManager2 / global lock (Lock) on the read path remains.
- PerfTest Server builds/starts; the PerfTest client runs its read/subscribe workload with results at least on par with the pre-migration baseline.
References
docs/AsyncServerSupport.md (UA-.NETStandard) — locking model and monitored-item manager selection (useSamplingGroups).
Part of #753.
Goal
Migrate the PerfTest Workshop server sample to
AsyncCustomNodeManager. It builds a large address space by hand (no generated model), so Step 2 (Fluent) does not apply. This sample is performance-sensitive — the migration should demonstrate the benefit of the async two-tier locking model.Scope
Workshop/PerfTest/Server/PerfTestNodeManager.cs—PerfTestNodeManager : CustomNodeManager2Workshop/PerfTest/Server/PerfTest Server.csprojand its node-manager registrationDo not touch the client project.
Step 1 — AsyncCustomNodeManager
CustomNodeManager2→AsyncCustomNodeManager; constructorbase(server, configuration, <namespaceUri>).CreateAddressSpace→override async ValueTask CreateAddressSpaceAsync(...); bulk-create the large node set withawait AddPredefinedNodeAsync/await AddNodeAsync.lock (Lock)around reads — rely on per-node read locking so the many simulated variables can be read in parallel. Keep writes under the base write semaphore.useSamplingGroups: trueon the base constructor; otherwise keep the default change-triggered manager and push updates viaawait ClearChangeMasksAsync.IAsyncNodeManagerFactory.Acceptance criteria
PerfTestNodeManagerderives fromAsyncCustomNodeManager; noCustomNodeManager2/ globallock (Lock)on the read path remains.References
docs/AsyncServerSupport.md(UA-.NETStandard) — locking model and monitored-item manager selection (useSamplingGroups).