fc94b87634
P11: AbCipUdtReadPlanner called AbCipUdtMemberLayout.TryBuild(parent.Members) for every member reference on every poll - O(members^2) per parent per tick, a dictionary allocation each time. GetOrBuild caches the layout (including a "not groupable" verdict) in a ConditionalWeakTable keyed by the member list's identity, which is immutable for the life of the tag table; a re-init's new lists replace the entries and the old ones are collected with them. Refs #737 Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT