Closed friuns2 closed 5 years ago
From the stack trace that you posted, you are using the non-incremental interface. This is just a wrapper around traditional Linq to Objects. You can achieve few allocations when reading the collection if you switch to an incremental mode. Zero allocations is usually not possible as soon as you start iterating a collection because you need to create an iterator.
Show me your query (or a broken down version of it) and I can explain you in a bit more detail how things work.
i think its incremental mode there is ObserableExtensions.FirstOrDefault() called and its using way less resources compared to linq
public class Test2 : MonoBehaviour
{
ObservableCollection<Test> cc = new ObservableCollection<Test>();
void Start()
{
for (int i = 0; i < 1000; i++)
cc.Add(new Test { a = Random.value });
INotifyCollection<Test> dd = cc.WithUpdates();
ff = dd.OrderByDescending(a => a.a);
}
IOrderableNotifyEnumerable<Test> ff;
void Update()
{
ff.FirstOrDefault();
}
}
[Serializable]
public class Test : INotifyPropertyChanged
{
public float a;
public void SetA(float a)
{
this.a = a;
OnPropertyChanged(nameof(a));
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string PropertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
public override string ToString()
{
return a.ToString();
}
}
Actually, FirstOrDefault
is executed in batch mode, but OrderByDescending
is executed in incremental mode. That is, if you execute FirstOrDefault
, it computes the value every time, but based on cached collection of OrderByDescending
, which simply uses a SortedDictionary
internally. So unlike Linq to Objects, you would not sort your collection all over again, but maintain a binary search tree. The reason you see a SelectManySingleSelectorIterator
in your stack trace is that that sorted dictionary stores a list of values (because multiple elements could have the same key).
So essentially, this sorted dictionary already is a buffered collection, but with a little bit of structure by the keys that you use for sorting. I don't see how this can be omitted.
Is it possible to make zero allocations when reading collection? some wrapper like BufferedCollection that would be updated when collection changed