Информация об изменениях

Сообщение Re[14]: Observable computations от 20.11.2019 10:56

Изменено 20.11.2019 12:09 igor-booch

Re[14]: Observable computations
S>2. Можно ли обойтись без порождения N врапперов для N элементов исходной коллекции — это ж реально адский перерасход по памяти. ObservableCollection<int> из миллиона элементов потребляет памяти почти столько же, сколько голый int[1000000]. А приделывание к ней банального "filtering" у нас что — порождает миллион экземпляров Computing() в куче?
Миллион экземпляров Computing() будет порождаться если только если
1) Computing() вложен в предикат
2) Computing() должен зависеть от параметра предиката.
Я бы не сказал, что это банальный filtering.

Вычисление можно сделать плоским (то есть убрать вложенные параметрозависимые вычисления). Наше вычисление можно переписать так:

ObservableCollection<Order> filteredOrders = orders
    .Joining(selectedOrderTypes, (o, ot) => o.Type == ot)
    .Selecting(oot => oot.OuterItem);


Выглядит менее очевидно, но зато с памятью будет значительно лучше. И без вложенных Computing'ов.

S>3. Что делать с зависимыми коллекциями, которые больше не нужны?

S>Ведь сейчас они подписываются на события оригинала, и, таким образом, "привязываются" к нему. Если я буду в цикле создавать new Filtering() от ObservableCollection, то GC их никогда не соберёт, из-за наличия ссылок на обработчики в событиях observableCollection.
Эта проблема не стоит. Используются слабые события.

[Test, Combinatorial]
public void Selecting_Dispose(
    [Range(0, 4, 1)] int index,
    [Range(-1, 5)] int newValue)
{
    ObservableCollection<Item> items = new ObservableCollection<Item>(
        new[]
        {
            new Item(),
            new Item(),
            new Item(),
            new Item(),
            new Item()
        }

    );

    WeakReference<Selecting<Item, int>> selectingWeakReference = null;

    Action action = () =>
    {
        Selecting<Item, int> selecting = items.Selecting(item => item.Num);
        selectingWeakReference = new WeakReference<Selecting<Item, int>>(selecting);
    };

    action();
    GC.Collect();
    Assert.IsFalse(selectingWeakReference.TryGetTarget(out Selecting<Item, int> s));
}
Re[14]: Observable computations
S>2. Можно ли обойтись без порождения N врапперов для N элементов исходной коллекции — это ж реально адский перерасход по памяти. ObservableCollection<int> из миллиона элементов потребляет памяти почти столько же, сколько голый int[1000000]. А приделывание к ней банального "filtering" у нас что — порождает миллион экземпляров Computing() в куче?
Миллион экземпляров Computing() будет порождаться если только если
1) Computing() вложен в предикат
2) Computing() должен зависеть от параметра предиката.
Я бы не сказал, что это банальный filtering.

Вычисление можно сделать "плоским" (то есть убрать вложенные параметрозависимые вычисления). Наше вычисление можно переписать так:

ObservableCollection<Order> filteredOrders = orders
    .Joining(selectedOrderTypes, (o, ot) => o.Type == ot)
    .Selecting(oot => oot.OuterItem);


Выглядит менее очевидно, но зато с памятью будет значительно лучше. И без вложенных Computing'ов.

S>3. Что делать с зависимыми коллекциями, которые больше не нужны?

S>Ведь сейчас они подписываются на события оригинала, и, таким образом, "привязываются" к нему. Если я буду в цикле создавать new Filtering() от ObservableCollection, то GC их никогда не соберёт, из-за наличия ссылок на обработчики в событиях observableCollection.
Эта проблема не стоит. Используются слабые события.

[Test, Combinatorial]
public void Selecting_Dispose(
    [Range(0, 4, 1)] int index,
    [Range(-1, 5)] int newValue)
{
    ObservableCollection<Item> items = new ObservableCollection<Item>(
        new[]
        {
            new Item(),
            new Item(),
            new Item(),
            new Item(),
            new Item()
        }

    );

    WeakReference<Selecting<Item, int>> selectingWeakReference = null;

    Action action = () =>
    {
        Selecting<Item, int> selecting = items.Selecting(item => item.Num);
        selectingWeakReference = new WeakReference<Selecting<Item, int>>(selecting);
    };

    action();
    GC.Collect();
    Assert.IsFalse(selectingWeakReference.TryGetTarget(out Selecting<Item, int> s));
}