From ee112171e5c46a782c6d3ee6b03cac984cf20f7c Mon Sep 17 00:00:00 2001 From: ctruxaw Date: Tue, 20 May 2025 00:37:27 -0700 Subject: [PATCH 1/3] FIX: If sendAllArtDMX is run for a node, it results in high CPU usage When the instance is not a Controller (and hence does not use sendAllArtDMX), sendAllArtDMX runs in a tight loop without sleeps or waits. There is no need for this task to run at all for non-controllers. --- ArtNetSharp/Communication/AbstractInstance.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ArtNetSharp/Communication/AbstractInstance.cs b/ArtNetSharp/Communication/AbstractInstance.cs index ac3846e..8b893c1 100644 --- a/ArtNetSharp/Communication/AbstractInstance.cs +++ b/ArtNetSharp/Communication/AbstractInstance.cs @@ -300,7 +300,8 @@ protected AbstractInstance(ArtNet _artnet) sendPollThreadBag.SendArtPollEvent += TimerSendPoll_Elapsed; - Task.Run(sendAllArtDMX); + if (this is ControllerInstance) + Task.Run(sendAllArtDMX); KnownRDMUIDs = knownRDMUIDs.Values.ToList().AsReadOnly(); } From d04750425799f02bab5d0ab1c1087471b825dd51 Mon Sep 17 00:00:00 2001 From: ctruxaw Date: Tue, 20 May 2025 00:58:15 -0700 Subject: [PATCH 2/3] FIX: High CPU usage waiting for SendArtPollEvent Tight loop caused high CPU usage, instead simply delay until the poll period has elapsed --- ArtNetSharp/Communication/AbstractInstance.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ArtNetSharp/Communication/AbstractInstance.cs b/ArtNetSharp/Communication/AbstractInstance.cs index 8b893c1..aac87c3 100644 --- a/ArtNetSharp/Communication/AbstractInstance.cs +++ b/ArtNetSharp/Communication/AbstractInstance.cs @@ -258,6 +258,8 @@ public void Dispose() internal class SendPollThreadBag { + private static readonly TimeSpan PollPeriod = TimeSpan.FromSeconds(2.7); // Spec 1.4dd page 13 + private readonly Thread sendPollThread; public EventHandler SendArtPollEvent; public SendPollThreadBag() @@ -269,8 +271,9 @@ public SendPollThreadBag() { try { - if ((DateTime.UtcNow - lastSendPollTime).TotalSeconds < 2.7)// Spec 1.4dd page 13 - continue; + TimeSpan elapsed = DateTime.UtcNow - lastSendPollTime; + if (elapsed < PollPeriod) + await Task.Delay(PollPeriod - elapsed); SendArtPollEvent?.InvokeFailSafe(null,EventArgs.Empty); } From 1223714c8570ec8a1a504b536a50af42675c5608 Mon Sep 17 00:00:00 2001 From: ctruxaw Date: Tue, 20 May 2025 11:07:20 -0700 Subject: [PATCH 3/3] FIX: sendAllArtDMX is also called by nodes --- ArtNetSharp/Communication/AbstractInstance.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ArtNetSharp/Communication/AbstractInstance.cs b/ArtNetSharp/Communication/AbstractInstance.cs index aac87c3..0c57f17 100644 --- a/ArtNetSharp/Communication/AbstractInstance.cs +++ b/ArtNetSharp/Communication/AbstractInstance.cs @@ -303,8 +303,7 @@ protected AbstractInstance(ArtNet _artnet) sendPollThreadBag.SendArtPollEvent += TimerSendPoll_Elapsed; - if (this is ControllerInstance) - Task.Run(sendAllArtDMX); + Task.Run(sendAllArtDMX); KnownRDMUIDs = knownRDMUIDs.Values.ToList().AsReadOnly(); } @@ -606,6 +605,9 @@ private async Task sendAllArtDMX() const double dmxKeepAliveTime = 800; // Spec 1.4dh page 53 while (!(this.IsDisposing || this.IsDisposed)) { + // Prevent CPU loop + await Task.Delay(10); + if (!this.EnableDmxOutput) continue; if (this.IsDeactivated)