Re[7]: Observable calculations
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.11.19 15:55
Оценка:
Здравствуйте, igor-booch, Вы писали:

IB>Возможно пользователю не нужно подписываться на события вычисляемой коллекции. Ему просто нужно чтобы всегда "под рукой" была вычисленная коллекция. Например, если вычисление сложное и\или коллекции источники большие, каждый раз вычислять коллекцию обычным LINQ не хочется по соображениям производительности. Например, есть Dictionaring. Его можно рассматривать как самообновляемый словарь, событий у него нет. Такой выигрыш в производительности ещё один сценарий использования OC, кроме событий. Кстати забыл упомянуть этот сценарий в документации.


Ну, это как бы совсем другой сценарий, чем описанный в документации. И по-прежнему непонятно, чем плохо иметь результат с событиями, когда они не нужны. Не подписываешься — и всё.

S>>А размер памяти, потребляемой "observable" результатом select или where будет ненамного больше, чем у результата обычного linq-to-objects запроса.

IB>То же надо оценивать.
А чего там оценивать? По отношению к "голому" результату, который приезжает из Linq2objects, в нём только 2 event-а, т.е. дополнительного места на 2 указателя. Копейки.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[8]: Observable computations
От: igor-booch Россия  
Дата: 19.11.19 08:34
Оценка:
IB>>Возможно пользователю не нужно подписываться на события вычисляемой коллекции. Ему просто нужно чтобы всегда "под рукой" была вычисленная коллекция. Например, если вычисление сложное и\или коллекции источники большие, каждый раз вычислять коллекцию обычным LINQ не хочется по соображениям производительности. Например, есть Dictionaring. Его можно рассматривать как самообновляемый словарь, событий у него нет. Такой выигрыш в производительности ещё один сценарий использования OC, кроме событий. Кстати забыл упомянуть этот сценарий в документации.

S>Ну, это как бы совсем другой сценарий, чем описанный в документации.


S>И по-прежнему непонятно, чем плохо иметь результат с событиями, когда они не нужны. Не подписываешься — и всё.

Я о том же: события в любом случае нужны, принимая во внимание сценарий описанный выше. Это был контр-аргумент к

S>К примеру, можно вообще не подписываться на события "завёрнутой" коллекции до тех пор, пока на наши события никто не подписан.


S>>>А размер памяти, потребляемой "observable" результатом select или where будет ненамного больше, чем у результата обычного linq-to-objects запроса.

IB>>То же надо оценивать.
S>А чего там оценивать? По отношению к "голому" результату, который приезжает из Linq2objects, в нём только 2 event-а, т.е. дополнительного места на 2 указателя. Копейки.
Кроме 2 указателей, у меня в каждом OC вычислении ещё полно потрохов. Ситуация по памяти может значительно ухудшиться, если присутствует параметрозависимое вложенное вычисление, например

sourceCollection1.Filtering(sc1i => sourceCollection2.ContainsComputing(sc1i).Value)


Здесь на каждый элемент коллекции sourceCollection1 будет создаваться отдельное вычисление ContainsComputing.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Отредактировано 19.11.2019 10:37 igor-booch . Предыдущая версия . Еще …
Отредактировано 19.11.2019 8:35 igor-booch . Предыдущая версия .
Re[9]: Observable computations
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.11.19 12:14
Оценка:
Здравствуйте, igor-booch, Вы писали:

S>>И по-прежнему непонятно, чем плохо иметь результат с событиями, когда они не нужны. Не подписываешься — и всё.

IB>Я о том же: события в любом случае нужны, принимая во внимание сценарий описанный выше. Это был контр-аргумент к
IB>

S>>К примеру, можно вообще не подписываться на события "завёрнутой" коллекции до тех пор, пока на наши события никто не подписан.

Хм. Я пока что плаваю в понимании этого раздела — примеров и документации нет, поэтому я не вполне представляю себе сценарий использования этого Dictionaring.
На своём уровне я понимаю так, что это можно было бы разделить: т.е. отдельно есть этакий Dictionaring(), который "отслеживает изменения в исходной коллекции" с тем, чтобы менять своё внутреннее состояние.
А его можно инициализировать не только ObservableCollection, но и произвольным результатом linq-2-observable, который сам порождает события с учётом критериев отбора/проекции и прочего.

IB>Кроме 2 указателей, у меня в каждом OC вычислении ещё полно потрохов. Ситуация по памяти может значительно ухудшиться, если присутствует параметрозависимое вложенное вычисление, например


IB>
IB>sourceCollection1.Filtering(sc1i => sourceCollection2.ContainsComputing(sc1i).Value)
IB>


IB>Здесь на каждый элемент коллекции sourceCollection1 будет создаваться отдельное вычисление ContainsComputing.

А можете поподробнее объяснить, что значит эта строчка кода? Что такое ContainsComputing и вообще смысл такого Filtering?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Observable computations
От: igor-booch Россия  
Дата: 19.11.19 13:39
Оценка: 76 (1)
S>А его можно инициализировать не только ObservableCollection, но и произвольным результатом linq-2-observable, который сам порождает события с учётом критериев отбора/проекции и прочего.
Так и есть.


IB>>Кроме 2 указателей, у меня в каждом OC вычислении ещё полно потрохов. Ситуация по памяти может значительно ухудшиться, если присутствует параметрозависимое вложенное вычисление, например


IB>>
IB>>sourceCollection1.Filtering(sc1i => sourceCollection2.ContainsComputing(sc1i).Value)
IB>>


IB>>Здесь на каждый элемент коллекции sourceCollection1 будет создаваться отдельное вычисление ContainsComputing.

S>А можете поподробнее объяснить, что значит эта строчка кода? Что такое ContainsComputing и вообще смысл такого Filtering?

Перевожу на linq-2-objects дополнив примером из реальной жизни:
IEnumerable<Order> filteredOrders =  orders.Where(o => 
    selectedOrderTypes.Contains(
        o.Type))


Вот OC верcия:
ObservableCollection<Order> filteredOrders =  orders.Filtering(o => 
    selectedOrderTypes.ContainsComputing<OrderType>(
        Expr.Is(() => o.Type).Computing()).Value);



selectedOrderTypes тоже должна быть ObservableCollection<OrderType>. Order должен реализовать INotifyPropertyChanged.
Далее можно менять selectedOrderTypes (add, remove), можно менять свойство Type у любого Order, можно менять коллекцию orders:
filteredOrders всегда будет содержать свежий результат.

Заметь что, в ContainsComputing аргумент o.Type передаётся не как значение (как в случае linq-2-objects), а как OC вычисление. (Похоже как передача аргументов по значению и по ссылке.) Это нужно чтобы во вложенном вычислении отслеживалось значение свойства Order.Type. Вот тебе ещё одна причина почему нельзя так просто использовать перегруженные linq-2-objects методы, как ты предлагал.

Expr.Is просто возвращает выражение переданное ему в аргументе. Иначе в C# не прицепить экстеншен метод к выражению.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Отредактировано 19.11.2019 15:01 igor-booch . Предыдущая версия . Еще …
Отредактировано 19.11.2019 14:56 igor-booch . Предыдущая версия .
Отредактировано 19.11.2019 14:35 igor-booch . Предыдущая версия .
Отредактировано 19.11.2019 14:31 igor-booch . Предыдущая версия .
Отредактировано 19.11.2019 14:24 igor-booch . Предыдущая версия .
Отредактировано 19.11.2019 14:19 igor-booch . Предыдущая версия .
Отредактировано 19.11.2019 14:16 igor-booch . Предыдущая версия .
Отредактировано 19.11.2019 14:07 igor-booch . Предыдущая версия .
Отредактировано 19.11.2019 14:04 igor-booch . Предыдущая версия .
Re[11]: Observable computations
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.11.19 16:42
Оценка:
Здравствуйте, igor-booch, Вы писали:

IB>Перевожу на linq-2-objects дополнив примером из реальной жизни:

IB>
IB>IEnumerable<Order> filteredOrders =  orders.Where(o => 
IB>    selectedOrderTypes.Contains(
IB>        o.Type))
IB>


IB>Вот OC верcия:

IB>
IB>ObservableCollection<Order> filteredOrders =  orders.Filtering(o => 
IB>    selectedOrderTypes.ContainsComputing<OrderType>(
IB>        Expr.Is(() => o.Type).Computing()).Value);
IB>



IB>selectedOrderTypes тоже должна быть ObservableCollection<OrderType>. Order должен реализовать INotifyPropertyChanged.

IB>Далее можно менять selectedOrderTypes (add, remove), можно менять свойство Type у любого Order, можно менять коллекцию orders:
IB>filteredOrders всегда будет содержать свежий результат.

IB>Заметь что, в ContainsComputing аргумент o.Type передаётся не как значение (как в случае linq-2-objects), а как OC вычисление. (Похоже как передача аргументов по значению и по ссылке.) Это нужно чтобы во вложенном вычислении отслеживалось значение свойства Order.Type. Вот тебе ещё одна причина почему нельзя так просто использовать перегруженные linq-2-objects методы, как ты предлагал.


Ага, интересно. Гляну на устройство ContainsComputing и как вообще это всё работает.
Магия задействована очень могучая, смущает, конечно, громоздкость синтаксиса. Не за то наши деды воевали, чтобы мы писали Expr.Is(() => o.Type).Computing().Value
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: Observable computations
От: igor-booch Россия  
Дата: 20.11.19 08:42
Оценка:
S>Не за то наши деды воевали, чтобы мы писали Expr.Is(() => o.Type).Computing().Value

Можно убрать Expr.Is в случае необходимости передать аргумент как вычисление. Нужно просто добавить перегрузки методов. Передаваться будет выражение, а вычисление выражения будет создаваться в теле перегруженного метода. Будет так:

ObservableCollection<Order> filteredOrders =  orders.Filtering(o => 
    selectedOrderTypes.ContainsComputing<OrderType>(() => o.Type).Value);


В остальных случаях, когда нужно создать вычисление можно будет писать так

new Computation(() => exprBody)


Если не сложно, создай мне issue на GitHub. Это нужно для популяризации проекта.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Re[13]: Observable computations
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.11.19 09:36
Оценка:
Здравствуйте, igor-booch, Вы писали:
IB>Можно убрать Expr.Is в случае необходимости передать аргумент как вычисление. Нужно просто добавить перегрузки методов. Передаваться будет выражение, а вычисление выражения будет создаваться в теле перегруженного метода.
Я по-прежнему считаю, что кошерный метод работы — это чистый linq синтаксис, а всю машинерию нужно прятать.

IB>
IB>ObservableCollection<Order> filteredOrders =  orders.Filtering(o => 
IB>    selectedOrderTypes.ContainsComputing<OrderType>(() => o.Type).Value);
IB>

Все эти Сomputing пользователю не нужны, и должны быть скрыты.
IB>В остальных случаях, когда нужно создать вычисление можно будет писать так
IB>
IB>new Computation(() => exprBody)
IB>

Не вижу смысла "создавать вычисление". Вот задача "собрать INotify*Changed как выражение из других INotify*Changed" — понятная задача. А вычисление само по себе — ненужная штука.

IB>Если не сложно, создай мне issue на GitHub. Это нужно для популяризации проекта.

Я пока не готов его сформулировать.
Для начала хочу понять
1. Можно ли обойтись анализом сырого Expression<>, без искусственных Computing-врапперов, при анализе зависимостей.
2. Можно ли обойтись без порождения N врапперов для N элементов исходной коллекции — это ж реально адский перерасход по памяти. ObservableCollection<int> из миллиона элементов потребляет памяти почти столько же, сколько голый int[1000000]. А приделывание к ней банального "filtering" у нас что — порождает миллион экземпляров Computing() в куче?
3. Что делать с зависимыми коллекциями, которые больше не нужны?
Ведь сейчас они подписываются на события оригинала, и, таким образом, "привязываются" к нему. Если я буду в цикле создавать new Filtering() от ObservableCollection, то GC их никогда не соберёт, из-за наличия ссылок на обработчики в событиях observableCollection.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[14]: Observable computations
От: igor-booch Россия  
Дата: 20.11.19 10:56
Оценка: 76 (1)
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));
}
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Отредактировано 20.11.2019 12:09 igor-booch . Предыдущая версия . Еще …
Отредактировано 20.11.2019 11:00 igor-booch . Предыдущая версия .
Отредактировано 20.11.2019 10:58 igor-booch . Предыдущая версия .
Отредактировано 20.11.2019 10:57 igor-booch . Предыдущая версия .
Re[13]: Observable computations
От: vorona  
Дата: 20.11.19 11:10
Оценка: 10 (1) +2
Здравствуйте, igor-booch, Вы писали:

IB>Если не сложно, создай мне issue на GitHub. Это нужно для популяризации проекта.


Напиши статью на хабре и объявление на reddit.
Re: Update
От: igor-booch Россия  
Дата: 04.04.21 14:06
Оценка: 108 (1)
Выпустил версию 2.1.0
Появилось 3 демо проекта
Покрытие тестами почти 100%
Подробности в документации
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Re: ObservableComputations - новая версия
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.02.22 13:11
Оценка:
Здравствуйте, igor-booch, Вы писали:

IB>3) Русский вариант документации хочу выложить на https://habr.com/ru/. Что посоветуете?


Можешь оформить в виде статьи
Автор(ы): Брусенцев Виталий, Чистяков Владислав Юрьевич
Дата: 22.06.2011
Статья описывает шаблон для Microsoft Word предназначенный для верстки статей и преобразования их в формат RSDN ML. В статье рассматриваются вопросы использования шаблона.
. Выложим у нас.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Observable calculations
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.02.22 16:47
Оценка:
Здравствуйте, igor-booch, Вы писали:

IB>Написано в разделе Use cases and benefits


UI binding
WPF, Xamarin, Blazor...


Примеры приведи. Это единственное где твой фрэймворк имеет смысл, но примеры в консольных приложениях. Сделай примеры WPF и Blazor. Что-нить простенькое и демонстративное.

Ну, и еще интересно как твоя либа сможет справиться с огромным числом элементов. Скажем список файлов разметом больше 10_000 элементов. Лучше миллион, чтобы уж точно материализовывать было затруднительно. Скажем сделай пример находящий файлы в заданном каталоге(с подкаталогами) и их отображение вместе сконками и т.п.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Observable calculations
От: igor-booch Россия  
Дата: 18.02.22 14:53
Оценка:
VD>Примеры приведи. Это единственное где твой фрэймворк имеет смысл, но примеры в консольных приложениях. Сделай примеры WPF и Blazor. Что-нить простенькое и демонстративное.
Примеры приложений есть: https://github.com/IgorBuchelnikov/ObservableComputations#demo-applications
В документации примеры на консольных приложениях сделал, чтобы можно было запустить по-быстрому и изолированно показать назначение отдельно взятого оператора.


VD>Ну, и еще интересно как твоя либа сможет справиться с огромным числом элементов. Скажем список файлов разметом больше 10_000 элементов.

В https://github.com/IgorBuchelnikov/Dynamic.Trader частые вычисления по нескольким тысячам элементов, работает шустро даже в однопоточном варианте
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Re[5]: Observable calculations
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.02.22 21:24
Оценка:
Здравствуйте, igor-booch, Вы писали:

IB>В https://github.com/IgorBuchelnikov/Dynamic.Trader частые вычисления по нескольким тысячам элементов, работает шустро даже в однопоточном варианте


Тысячи, по нашим временам, ни о чем. Для демонстрации возможностей лучше миллионы. Ну хотя бы десятки тысяч пушистых объектов, чтобы видно было, что данные не материализуются в памяти.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Observable calculations
От: igor-booch Россия  
Дата: 19.02.22 19:44
Оценка:
VD>Тысячи, по нашим временам, ни о чем. Для демонстрации возможностей лучше миллионы.
В UI?
(ObservableComputations прежде всего для UI. В backend имеет применение только для некоторых отдельных случаев)



VD>Ну хотя бы десятки тысяч пушистых объектов, чтобы видно было, что данные не материализуются в памяти.

Что подразумеваешь под материализацией?
Любые дополнительные расходы памяти по сравнению с операторами LINQ? Они конечно есть.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Re[7]: Observable calculations
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.02.22 12:50
Оценка:
Здравствуйте, igor-booch, Вы писали:

IB>В UI?


Да. Вот не давно нужно было такое. Поиск по файлам системы. Пришлось отсекать первую тысячу в выдаче. Если бы в гриде поддерживалась виртуализация, и это же поддерживали коллекции не пришлось делать отсечения и прочих приседаний.

IB>(ObservableComputations прежде всего для UI. В backend имеет применение только для некоторых отдельных случаев)


Это понятно. Но когда люди выбирают некую либу для использования, то выбирают (в том числе) отталкиваясь от минимума ограничений.

IB>Что подразумеваешь под материализацией?


То и подразумевается. Если брать обратный Observable поход, то хороши пример Linq. В нем данные не материализуются до их запроса (например, через foreach). Но это как общий пример. С WPF все несколько хреново. Там виртуализация делается на IList и подобных интерфейсах и просто считается, что данные запрашиваются по индексу. Это подход хреновый. Работая Observable хочется не думать о том сколько данных будет, а чтобы либа предоставляла прозрачную виртуализацию. Пользователь перешел к последним записям, подкачались еще несколько страниц.

IB>Любые дополнительные расходы памяти по сравнению с операторами LINQ? Они конечно есть.


А почему "конечно". В тории их быть не должно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Observable calculations
От: igor-booch Россия  
Дата: 21.02.22 14:40
Оценка: 78 (1)
VD>Поиск по файлам системы. Пришлось отсекать первую тысячу в выдаче. Если бы в гриде поддерживалась виртуализация, и это же поддерживали коллекции не пришлось делать отсечения и прочих приседаний.
По поводу виртуализации был вопрос: https://github.com/IgorBuchelnikov/ObservableComputations/discussions/11
Кратко: ObservableComputations это не про виртуализацию.
Хотя есть оператор Paging, может пригодится

VD>Это понятно. Но когда люди выбирают некую либу для использования, то выбирают (в том числе) отталкиваясь от минимума ограничений.

Здесь сложно сказать о каких-либо ограничениях. Данных может не много, но вычисление может быть сложное, а данные будут меняться часто и многопоточные вычисления по каким-то причинам не подходят. Упомянутый DynamicTrader при 50000 уже тормозит

IB>>Любые дополнительные расходы памяти по сравнению с операторами LINQ? Они конечно есть.

VD>А почему "конечно". В тории их быть не должно.
Объясняю. Каждый оператор ObservableComputations делает материализацию.
Если в вычислении несколько операторов в цепочке,
будет несколько материализаций + внутренние служебные коллекции.
Знаю это не есть хорошо. Но даже при таком подходе алгоритмы достаточно сложные (сам не ожидал).
В теории можно сделать 1 материализацию на всё вычисление состоящее из нескольких операторов, через генерацию кода. Но это будет сложно. Ещё нужно учитывать, что могут быть вложенные операторы (в предикат, в селектор).
Пока вдохновения делать такое нет, так как к текущему проекту интереса мало. Но я не жалею, получил удовольствие от кодинга.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания
http://rsdn.ru/Info/rules.xml
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.