Browse Source

Remove `List<IObserver<T>>.ToArray()` allocations in `LightweightObservableBase` (#18316)

* Remove `List<IObserver<T>>.ToArray()` allocations in `LightweightObservableBase`

* Cleanup code

* Remove unused code

* Remove space
pull/18331/head
Alexandre Mutel 12 months ago
committed by GitHub
parent
commit
85ffed056a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 53
      src/Avalonia.Base/Reactive/LightweightObservableBase.cs

53
src/Avalonia.Base/Reactive/LightweightObservableBase.cs

@ -1,7 +1,7 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Threading;
using Avalonia.Threading;
namespace Avalonia.Reactive
{
@ -118,32 +118,59 @@ namespace Avalonia.Reactive
if (Volatile.Read(ref _observers) != null)
{
IObserver<T>[]? observers = null;
IObserver<T>? singleObserver = null;
int count = 0;
// Optimize for the common case of 1/2/3 observers.
IObserver<T>? observer0 = null;
IObserver<T>? observer1 = null;
IObserver<T>? observer2 = null;
lock (this)
{
if (_observers == null)
{
return;
}
if (_observers.Count == 1)
{
singleObserver = _observers[0];
}
else
count = _observers.Count;
switch (count)
{
observers = _observers.ToArray();
case 3:
observer0 = _observers[0];
observer1 = _observers[1];
observer2 = _observers[2];
break;
case 2:
observer0 = _observers[0];
observer1 = _observers[1];
break;
case 1:
observer0 = _observers[0];
break;
case 0:
return;
default:
{
observers = ArrayPool<IObserver<T>>.Shared.Rent(count);
_observers.CopyTo(observers);
break;
}
}
}
if (singleObserver != null)
if (observer0 != null)
{
singleObserver.OnNext(value);
observer0.OnNext(value);
observer1?.OnNext(value);
observer2?.OnNext(value);
}
else
else if (observers != null)
{
foreach (var observer in observers!)
for(int i = 0; i < count; i++)
{
observer.OnNext(value);
observers[i].OnNext(value);
}
ArrayPool<IObserver<T>>.Shared.Return(observers);
}
}
}

Loading…
Cancel
Save