Skip to content

Commit 0e8273e

Browse files
authored
performance: Reduce allocations (logger factory reuse, check enabled) (#3387)
* Performance: Reduce memory allocations (logging, etc.)
1 parent 35e03d9 commit 0e8273e

File tree

7 files changed

+108
-61
lines changed

7 files changed

+108
-61
lines changed

Libraries/Opc.Ua.Client/OpcUaClientEventSource.cs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ public void SubscriptionState(
9595
Level = EventLevel.Verbose)]
9696
public void Notification(int clientHandle, Variant value)
9797
{
98-
WriteEvent(NotificationId, clientHandle, value.ToString());
98+
if (IsEnabled())
99+
{
100+
WriteEvent(NotificationId, clientHandle, value.ToString());
101+
}
99102
}
100103

101104
/// <summary>
@@ -107,7 +110,10 @@ public void Notification(int clientHandle, Variant value)
107110
Level = EventLevel.Verbose)]
108111
public void NotificationReceived(int subscriptionId, int sequenceNumber)
109112
{
110-
WriteEvent(NotificationReceivedId, subscriptionId, sequenceNumber);
113+
if (IsEnabled())
114+
{
115+
WriteEvent(NotificationReceivedId, subscriptionId, sequenceNumber);
116+
}
111117
}
112118

113119
/// <summary>
@@ -119,7 +125,10 @@ public void NotificationReceived(int subscriptionId, int sequenceNumber)
119125
Level = EventLevel.Verbose)]
120126
public void PublishStart(int requestHandle)
121127
{
122-
WriteEvent(PublishStartId, requestHandle);
128+
if (IsEnabled())
129+
{
130+
WriteEvent(PublishStartId, requestHandle);
131+
}
123132
}
124133

125134
/// <summary>
@@ -131,7 +140,10 @@ public void PublishStart(int requestHandle)
131140
Level = EventLevel.Verbose)]
132141
public void PublishStop(int requestHandle)
133142
{
134-
WriteEvent(PublishStopId, requestHandle);
143+
if (IsEnabled())
144+
{
145+
WriteEvent(PublishStopId, requestHandle);
146+
}
135147
}
136148
}
137149
}

Libraries/Opc.Ua.Client/Subscription/MonitoredItem.cs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,11 @@ public void SaveValueInCache(IEncodeable newValue)
591591
m_eventCache.OnNotification(eventchange);
592592
}
593593

594-
m_Notification?.Invoke(this, new MonitoredItemNotificationEventArgs(newValue));
594+
var handler = m_Notification;
595+
if (handler != null)
596+
{
597+
handler.Invoke(this, new MonitoredItemNotificationEventArgs(newValue));
598+
}
595599
}
596600
}
597601

@@ -1166,15 +1170,22 @@ public IList<DataValue> Publish()
11661170
public void OnNotification(MonitoredItemNotification notification)
11671171
{
11681172
LastValue = notification.Value;
1169-
CoreClientUtils.EventLog.Notification(
1170-
(int)notification.ClientHandle,
1171-
LastValue.WrappedValue);
11721173

1173-
m_logger.LogDebug(
1174-
"Notification: ClientHandle={ClientHandle}, Value={Value}, SourceTime={SourceTime}",
1175-
notification.ClientHandle,
1176-
notification.Value.WrappedValue,
1177-
notification.Value.SourceTimestamp);
1174+
if (CoreClientUtils.EventLog.IsEnabled())
1175+
{
1176+
CoreClientUtils.EventLog.Notification(
1177+
(int)notification.ClientHandle,
1178+
LastValue.WrappedValue);
1179+
}
1180+
1181+
if (m_logger.IsEnabled(LogLevel.Debug))
1182+
{
1183+
m_logger.LogDebug(
1184+
"Notification: ClientHandle={ClientHandle}, Value={Value}, SourceTime={SourceTime}",
1185+
notification.ClientHandle,
1186+
notification.Value.WrappedValue,
1187+
notification.Value.SourceTimestamp);
1188+
}
11781189

11791190
if (m_values != null)
11801191
{
@@ -1185,11 +1196,14 @@ public void OnNotification(MonitoredItemNotification notification)
11851196
{
11861197
break;
11871198
}
1188-
m_logger.LogInformation(
1189-
"Dropped value: ClientHandle={ClientHandle}, Value={Value}, SourceTime={SourceTime}",
1190-
notification.ClientHandle,
1191-
dropped.WrappedValue,
1192-
dropped.SourceTimestamp);
1199+
if (m_logger.IsEnabled(LogLevel.Information))
1200+
{
1201+
m_logger.LogInformation(
1202+
"Dropped value: ClientHandle={ClientHandle}, Value={Value}, SourceTime={SourceTime}",
1203+
notification.ClientHandle,
1204+
dropped.WrappedValue,
1205+
dropped.SourceTimestamp);
1206+
}
11931207
}
11941208
}
11951209
}

Libraries/Opc.Ua.Client/Subscription/Subscription.cs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
* ======================================================================*/
2929

3030
using System;
31+
using System.Collections.Concurrent;
3132
using System.Collections.Generic;
3233
using System.Diagnostics;
3334
using System.Linq;
@@ -1549,7 +1550,7 @@ public void RemoveItem(MonitoredItem monitoredItem)
15491550

15501551
lock (m_cache)
15511552
{
1552-
if (!m_monitoredItems.Remove(monitoredItem.ClientHandle))
1553+
if (!m_monitoredItems.TryRemove(monitoredItem.ClientHandle, out _))
15531554
{
15541555
return;
15551556
}
@@ -1583,7 +1584,7 @@ public void RemoveItems(IEnumerable<MonitoredItem> monitoredItems)
15831584
{
15841585
foreach (MonitoredItem monitoredItem in monitoredItems)
15851586
{
1586-
if (m_monitoredItems.Remove(monitoredItem.ClientHandle))
1587+
if (m_monitoredItems.TryRemove(monitoredItem.ClientHandle, out _))
15871588
{
15881589
monitoredItem.Subscription = null;
15891590

@@ -2680,7 +2681,7 @@ private void TransferItems(
26802681
{
26812682
int count = clientHandles.Count;
26822683
itemsToModify = new List<MonitoredItem>(count);
2683-
var updatedMonitoredItems = new Dictionary<uint, MonitoredItem>(count);
2684+
var updatedMonitoredItems = new ConcurrentDictionary<uint, MonitoredItem>(1, count);
26842685
foreach (MonitoredItem monitoredItem in m_monitoredItems.Values)
26852686
{
26862687
int index = serverHandles.FindIndex(
@@ -2771,19 +2772,14 @@ private void SaveDataChange(
27712772
{
27722773
MonitoredItemNotification notification = notifications.MonitoredItems[ii];
27732774

2774-
// lookup monitored item,
2775-
MonitoredItem? monitoredItem;
2776-
lock (m_cache)
2775+
if (!m_monitoredItems.TryGetValue(notification.ClientHandle, out var monitoredItem))
27772776
{
2778-
if (!m_monitoredItems.TryGetValue(notification.ClientHandle, out monitoredItem))
2779-
{
2780-
m_logger.LogWarning(
2781-
"Publish response contains invalid MonitoredItem. " +
2782-
"SubscriptionId={SubscriptionId}, ClientHandle = {ClientHandle}",
2783-
Id,
2784-
notification.ClientHandle);
2785-
continue;
2786-
}
2777+
m_logger.LogWarning(
2778+
"Publish response contains invalid MonitoredItem. " +
2779+
"SubscriptionId={SubscriptionId}, ClientHandle = {ClientHandle}",
2780+
Id,
2781+
notification.ClientHandle);
2782+
continue;
27872783
}
27882784

27892785
// save the message.
@@ -2927,7 +2923,7 @@ private void PublishingStateChanged(
29272923
private readonly Lock m_cache = new();
29282924
private readonly LinkedList<NotificationMessage> m_messageCache = new();
29292925
private IList<uint>? m_availableSequenceNumbers;
2930-
private Dictionary<uint, MonitoredItem> m_monitoredItems = [];
2926+
private ConcurrentDictionary<uint, MonitoredItem> m_monitoredItems = new();
29312927
private readonly AsyncAutoResetEvent m_messageWorkerEvent = new();
29322928
private CancellationTokenSource? m_messageWorkerCts;
29332929
private Task? m_messageWorkerTask;

Libraries/Opc.Ua.Server/Server/OpcUaServerEventSource.cs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,13 @@ internal sealed class OpcUaServerEventSource : EventSource
6666
Level = EventLevel.Informational)]
6767
public void ServerCall(RequestType requestType, uint requestId)
6868
{
69-
string requestTypeString = Enum.GetName(
70-
#if !NET8_0_OR_GREATER
71-
typeof(RequestType),
72-
#endif
73-
requestType);
7469
if (IsEnabled())
7570
{
71+
string requestTypeString = Enum.GetName(
72+
#if !NET8_0_OR_GREATER
73+
typeof(RequestType),
74+
#endif
75+
requestType);
7676
WriteEvent(kServerCallId, requestTypeString, requestId);
7777
}
7878
}
@@ -91,13 +91,16 @@ public void SessionState(
9191
string secureChannelId,
9292
string identity)
9393
{
94-
WriteEvent(
95-
kSessionStateId,
96-
context,
97-
sessionId,
98-
sessionName,
99-
secureChannelId,
100-
identity);
94+
if (IsEnabled())
95+
{
96+
WriteEvent(
97+
kSessionStateId,
98+
context,
99+
sessionId,
100+
sessionName,
101+
secureChannelId,
102+
identity);
103+
}
101104
}
102105

103106
/// <summary>
@@ -109,7 +112,10 @@ public void SessionState(
109112
Level = EventLevel.Verbose)]
110113
public void MonitoredItemReady(uint id, string state)
111114
{
112-
WriteEvent(kMonitoredItemReadyId, id, state);
115+
if (IsEnabled())
116+
{
117+
WriteEvent(kMonitoredItemReadyId, id, state);
118+
}
113119
}
114120
}
115121
}

Libraries/Opc.Ua.Server/Subscription/MonitoredItem/QueueHandler/DataChangeQueueHandler.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ public bool PublishSingleValue(
259259
m_overflow = null;
260260
}
261261

262-
if (!noEventLog)
262+
if (!noEventLog && m_logger.IsEnabled(LogLevel.Trace))
263263
{
264264
m_logger.LogTrace(
265265
"DEQUEUE VALUE: Value={Value} CODE={Code}<{Code:X8}> OVERFLOW={Overflow}",
@@ -279,7 +279,10 @@ private void Enqueue(DataValue value, ServiceResult error)
279279
// check for empty queue.
280280
if (m_dataValueQueue.ItemsInQueue == 0)
281281
{
282-
m_logger.LogTrace("ENQUEUE VALUE: Value={Value}", value.WrappedValue);
282+
if (m_logger.IsEnabled(LogLevel.Trace))
283+
{
284+
m_logger.LogTrace("ENQUEUE VALUE: Value={Value}", value.WrappedValue);
285+
}
283286

284287
m_dataValueQueue.Enqueue(value, error);
285288

@@ -330,7 +333,7 @@ private void Enqueue(DataValue value, ServiceResult error)
330333
//set overflow bit in oldest value
331334
m_overflow = m_dataValueQueue.PeekOldestValue();
332335
}
333-
else
336+
else if (m_logger.IsEnabled(LogLevel.Trace))
334337
{
335338
m_logger.LogTrace("ENQUEUE VALUE: Value={Value}", value.WrappedValue);
336339
}

Libraries/Opc.Ua.Server/Subscription/SubscriptionManager.cs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,10 @@ private async ValueTask DoConditionRefreshAsync(ISubscription subscription, Canc
630630
{
631631
try
632632
{
633-
m_logger.LogTrace("Subscription ConditionRefresh started, Id={SubscriptionId}.", subscription.Id);
633+
if (m_logger.IsEnabled(LogLevel.Trace))
634+
{
635+
m_logger.LogTrace("Subscription ConditionRefresh started, Id={SubscriptionId}.", subscription.Id);
636+
}
634637
await subscription.ConditionRefreshAsync(cancellationToken)
635638
.ConfigureAwait(false);
636639
}
@@ -647,10 +650,13 @@ private async ValueTask DoConditionRefresh2Async(ISubscription subscription, uin
647650
{
648651
try
649652
{
650-
m_logger.LogTrace(
651-
"Subscription ConditionRefresh2 started, Id={SubscriptionId}, MonitoredItemId={MonitoredItemId}.",
652-
subscription.Id,
653-
monitoredItemId);
653+
if (m_logger.IsEnabled(LogLevel.Trace))
654+
{
655+
m_logger.LogTrace(
656+
"Subscription ConditionRefresh2 started, Id={SubscriptionId}, MonitoredItemId={MonitoredItemId}.",
657+
subscription.Id,
658+
monitoredItemId);
659+
}
654660
await subscription.ConditionRefresh2Async(monitoredItemId, cancellationToken)
655661
.ConfigureAwait(false);
656662
}
@@ -1038,7 +1044,10 @@ public async Task<PublishResponse> PublishAsync(
10381044

10391045
try
10401046
{
1041-
m_logger.LogTrace("Publish #{ClientHandle} ReceivedFromClient", context.ClientHandle);
1047+
if (m_logger.IsEnabled(LogLevel.Trace))
1048+
{
1049+
m_logger.LogTrace("Publish #{ClientHandle} ReceivedFromClient", context.ClientHandle);
1050+
}
10421051

10431052
// check for any pending status messages that need to be sent.
10441053
if (ReturnPendingStatusMessage(context, out NotificationMessage statusMessage, out uint statusSubscriptionId))
@@ -1115,9 +1124,12 @@ public async Task<PublishResponse> PublishAsync(
11151124
}
11161125

11171126
requeue = true;
1118-
m_logger.LogTrace(
1119-
"Publish False Alarm - Request #{ClientHandle} Requeued.",
1120-
context.ClientHandle);
1127+
if (m_logger.IsEnabled(LogLevel.Trace))
1128+
{
1129+
m_logger.LogTrace(
1130+
"Publish False Alarm - Request #{ClientHandle} Requeued.",
1131+
context.ClientHandle);
1132+
}
11211133
}
11221134
finally
11231135
{

Stack/Opc.Ua.Core/Types/Utils/LoggerUtils.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,14 @@ public static class Fallback
8989
#endif
9090
}
9191

92+
/// <summary>
93+
/// Shared telemetry context instance (singleton)
94+
/// </summary>
95+
private static readonly TraceLoggerTelemetry s_sharedTelemetry = new();
96+
9297
static Utils()
9398
{
94-
TelemetryExtensions.InternalOnly__TelemetryHook =
95-
() => new TraceLoggerTelemetry();
99+
TelemetryExtensions.InternalOnly__TelemetryHook = () => s_sharedTelemetry;
96100
}
97101

98102
/// <summary>

0 commit comments

Comments
 (0)