bcde93056a
Since #855 condition events are queued to folder event items under the node manager Lock. At a full DiscardOldest queue the SDK's EventQueueHandler dequeues the head of EventMonitoredItemQueue, a List.RemoveAt(0) shift of the whole queue (~1 us/item at QueueSize 1000, ~10 us at 10000). OtOpcUaSdkServer.CreateMonitoredItemQueueFactory now wraps the SDK factory in RingEventQueueFactory: event queues are RingEventMonitoredItemQueue (O(1) discard), data-change queues, durable requests and disposal go to the SDK factory unchanged. A factory set through StandardServer.MonitoredItemQueueFactory is used as-is. The SDK queue is storage only (decompiled 2.0.1): DiscardOldest, overflow-event positions and discarded/overflow counters live in EventQueueHandler, which is unchanged. The ring reproduces QueueSize 0 initial + BadInternalError enqueue, drop-oldest at Count == QueueSize, FIFO dequeue, SetQueueSize keep-newest / keep-oldest, the newest-1000 duplicate window via IsEventRaisedFor, no-op Dispose. RingEventMonitoredItemQueueParityTests drive both queues, and the SDK EventQueueHandler over both factories, with the same random sequences. FolderEventDeliveryPerfTests gains Ring_vs_sdk_event_queue (A/B in one process via the internal OtOpcUaSdkServer.RingEventQueues switch). Claude-Session: https://claude.ai/code/session_01GT67AD99zQQqpLCVm3p7xk