Как стать автором
Обновить

Комментарии 31

апер молодец

Опять не используются getter/setters для автоматических подписок/отписок. Опять вынужденное загрязнение кода ненужными конструкциями на ровном месте. Опять до MobX как раком до Китая.

Эээ, автора не защищаю (хотя работа отличная проделана), но он обмолвился про прокси паттерн имеет место быть, а дальше написал что получись эффективнее, но по другому

Круто, и чтобы сэкономить пару микросекунд на фронте будем писать кучу лишнего кода и подписываться на все в ручную, и вместо того что обращаться к переменным традиционным способом будем вызывать функции каждый раз чтобы получить значение, вот это конечно выше всех похвал)

Зато без «сюрпризов» - в библиотеках основанных на Proxy каждые пару лет находят по паре багов и их решение часто стоит скорости.

Не очень понятно про какой лишний код мы говорим и о каких ручных подписках...

Если отбросить функции, то кода ровно столько же будет, что на том же mobx, просто без магии Proxy, которые заставляет вас даже примитив засунуть в "объект" чтобы получить геттер, ну а тут вызывать функцию, чем и является геттер 🤷🏻‍♂️

Не очень понятно про какой лишний код мы говорим и о каких ручных подписках...

Вот лишний код и ручные подписки.
Вот лишний код и ручные подписки.
А вот тоже самое, только без ручных подписок
А вот тоже самое, только без ручных подписок

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

Вот ссылки:
https://stackblitz.com/edit/react-ts-zri1ry?file=App.tsx
https://stackblitz.com/edit/react-ts-fp26tt?file=App.tsx,index.tsx

Если отбросить функции, то кода ровно столько же будет, что на том же mobx, просто без магии Proxy,

Нет, не столько же кода из-за ручных подписок. Магии Proxy вообще нет никакой, достаточно уделить 15 минут и прочитать про то, как это работает и самому пару примеров написать. Тем более в MobX можно отключить Proxy если вы их так боитесь.
https://mobx.js.org/configuration.html

import { configure } from "mobx"

configure({
    useProxies: "never"
})

которые заставляет вас даже примитив засунуть в "объект" чтобы получить геттер, ну а тут вызывать функцию, чем и является геттер

Посмотрите код выше, MobX нужно использовать именно так. В классах.

Так у вас там makeAutoObserver, который работает с «объектом» + observer из mobx-react-lite, который является биндингом, а в статье авто же хотел показать, что акту никакие биндинги не нужны, он работает из коробки средствами самой либы.

Никто не мешал автору сделать свой observer, но опять же цель статьи в другом 💁🏻‍♂️

Кроме этого, вы говорите что код чище, но внутри у вас магия, нет реактивного примитива, есть контейнер, который при создании автоматически создаёт внутри себя геттеры/сеттеры на описанные свойства без разбору, и так каждый раз.

Можно конечно и в ручную всё это обрабатывать и бла-бла-бла, выйдет как акт и подобных в итоге, просто вместо функций, ячейкой будет объект/экземпляр класса.

PS useProxies, я про сам петтерн, а не Proxy как таковой

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

Один в один повторён пассивный режим вычисления из cellx, тот же глобальный счётчик, та же возможность лишних вычислений при тех же условиях и у меня даже то же самое оправдание для них)). На сколько я помню cellx в этом режиме действительно прилично так быстрее, чем в основном, но у меня этот режим скорее как костыль для автоматической финализации (dispose) ячейки при удалении последнего подписчика, в акте же этот режим удалось сделать основным, что тут сказать, отличная работа проделана!

UPD: а вообще смотрю я как используются reactions в коде cellx-а и понимаю, что отказаться от получаемого таким образом функционала будет очень больно, функционал тут для меня определённо важнее скорости.

Че-то с тестами то мухлеж какой-то, я решил проверить на вшивость и вот результаты:
https://perf.js.hyoo.ru/#!bench=nhg1tu_5gl6nt

Тут просто разгром в скорости в пользу MobX в разы. ВАЖНО: Консоль должна быть открыта во время тестов! Иначе по причинам известным только одному создателю теста цифры не соответствуют действительности от слова совсем, это даже видно просто по времени выполнения.

Как проверить на вшивость? Да просто добавить console.log в Setup и далее даже просто наблюдая за скоростью вывода лога в консоль сразу видно что вывод act в разы медлее чем вывод MobX'a.

1)

2)

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

Очень странное влияние открытой консоли. Бенч не мой, сказать ничего не могу. Вот мой бенч, там мобыкс достаточно сильно сливает, что там не так https://github.com/artalar/reactive-computed-bench ??

У Карловского странное всё, даже бенчмарки) Им вообще верить нельзя, надо всё самому проверять. Я набросал свой, но прям супер простой кейс, добавил сюда ещё CellX и да, ваш вариант быстрее конечно.
Вот ссылка - https://stackblitz.com/edit/react-ts-1wcwyz?file=App.tsx,index.tsx

Но всё же на 100тыс синхронных итерациях на клиентской стороне вообще без разницы 20ms или 5ms )) Учитывая то, что сам по себе код с использованием MobX более чистый и нативный, я ему прощаю проигрыш в эти несколько миллисекунд)

ВАЖНОКонсоль должна быть открыта во время тестов!

Вы всех своих пользователей заставляете открывать отладчик и ставить там логпоинты с выводом в консоль бессмысленных цифр? Или думаете вывод в консоль ничего не стоит?

цифры не соответствуют действительности от слова совсем, это даже видно просто по времени выполнения.

Время выполнения замера зависит от многих факторов, но слабо зависит от скорости работы конкретного кейса. Сетап отрабатывает один раз на замер. Число итераций в замере подбирается таким образом, чтобы замер был не слишком коротким, но и не слишком длинным.

ВАЖНОКонсоль должна быть открыта во время тестов! Иначе по причинам известным только одному создателю теста цифры не соответствуют действительности от слова совсем, это даже видно просто по времени выполнения.

А есть аргументы в пользу того, что при открытой консоли цифры не соответствуют действительности, а не при закрытой, или в пользу того что они в обоих случаях не соответствуют дествительности?

С вставка console.log и замер скорости вывода на глаз - слабый и странный аргумент, т.к. глаз не славится точностью, а один прогон занимает миллисекунды. К тому же не ясно, как коррелирует количество запускав одного прогона и кода целиком вместе с импортом(который ассинхронный)

НЛО прилетело и опубликовало эту надпись здесь

Открытие консоли запускает отладочную сессию, что весьма не бесплатно, поэтому бенчмарки нельзя гонять с открытой консолью. У меня, например, просто открытая пустая консоль, в которую ничего не выводится, приводит к просадке кейсов с либами, не слишком аккуратно работающими с памятью:

Открытие консоли запускает отладочную сессию, что весьма не бесплатно, поэтому бенчмарки нельзя гонять с открытой консолью. У меня, например, просто открытая пустая консоль, в которую ничего не выводится, приводит к просадке кейсов с либами, не слишком аккуратно работающими с памятью

Так почему MobX в таком случае начинает работать быстрее, а cellX и arc медленнее? Если с закрытой консолью они были быстрее или примерно на ровне с MobX в ваших тестах. Логика тут напрочь отсутствует. Если консоль замедляет, то она замедляет всех, а так что кого-то замедляет в разы, а кого-то ускоряет на 40% это просто ерись. Это анти инженерный подход, когда погода в Австралии влияет на результаты измерений уровня радиации в разы, это значит что вы не умеете измерять радиацию. Вот банальный тест и он показывает стабильную разницу в скорости вне зависимости от того, открыта консоль или нет. https://stackblitz.com/edit/react-ts-1wcwyz?file=App.tsx,index.tsx

Что творится на вашей машине мне не ведомо, но на моей MobX колеблется возле 120 микросекунд в обоих случаях, а act проседает с 80 до 140. Стоит иметь также ввиду погрешность в 10-20 микросекунд.

Ну а ваш бенчмарк стабильно сравнивает тёплое с мягким. Для MobX у вас замеряется 1 реакция на 100к изменений одной и той же переменной. Для Act - 0 реакций. А для CellX - 1 реакция на каждое изменение. Вам бы сперва теорию подучить, прежде чем бросаться громкими заявлениями.

Ну и откройте уже для себя performance.now() или хотя бы Date.now().

Что творится на вашей машине мне не ведомо, но на моей MobX колеблется возле 120 микросекунд в обоих случаях, а act проседает с 80 до 140. Стоит иметь также ввиду погрешность в 10-20 микросекунд.

Обычная машина, проц Ryzen 9 5950x вот попробовал в Mozilla Firefox

Такая же фигня, адское проседание arc почему-то, а MobX гораздо быстрее.

Для MobX у вас замеряется 1 реакция на 100к изменений одной и той же переменной. Для Act - 0 реакций. А для CellX - 1 реакция на каждое изменение. Вам бы сперва теорию подучить, прежде чем бросаться громкими заявлениями.

1) Как бы в Act идет отложенное выполнение реакций(автобатчинг)
2) В MobX runInAction батчит
3) В CellX вообще синхронно реакции отрабатывают без батчинга и их как раз 200к и при этом он самый быстрый.

Ну а ваш бенчмарк стабильно сравнивает тёплое с мягким

Нет, он сравнивает как раз таки в лоб, сколько стоит 2 раза по 100к заинкрементить реактивную переменную, насколько быстро при этом все работает под капотом. А то что Act и MobX батчат изменения, а CellX вызывает реакции синхронно, это уже особенности дизайна данных библиотек, но при этом CellX быстрее всех хоть и 200к реакций заодно выдал, в то время как act и mobx 1 и 2. Но это не суть важно, важно то, что открытая консоль на это НЕ ВЛИЯЕТ НИКАК в отличии от вашей поделки непонятной, где просто тот же Act в 10 раз медленнее начинает работать, а MobX на 40% быстрее.

А если брать цифры, то в реальной жизни 100к итераций на постоянной основе приложения не делаю в 99.99999% случаев, и даже если и сделают, то это <30ms, ну на доисторических устройствах пусть 200ms, но это опять же не реальный кейс тем более на постоянной основе, отсюда не важно сколько наносекунд будет сэкономлено в реальной эксплуатации и сколько килобайт памяти сэкономлено, это просто сущие копейки, даже для мобильных устройство в которых самое дно устройство имеет 2гб оперативы.

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

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

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

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

А если у вас есть сомнения в корректности работы наиболее продвинутого на текущий момент тула бенчмаркинга JS в браузере, то предлагаю вам не сотрясать байты в интернете попусту, а помочь с его улучшением. Исходники открыты. Мерж-реквестам всегда рады.

Не знаю зачем вы запускаете бенчмарки с активным отладчиком, но я настоятельно рекомендую вам этого не делать больше никогда

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

чтобы над вами не смеялись более прошаренные коллеги.

Более прошаренные? Это кто? Те, которые говорят не разбираешься - не лезь, просто закрой консоль и всё и т.п., они прошаренные да? :D:D:D

А если у вас есть сомнения в корректности работы наиболее продвинутого на текущий момент тула бенчмаркинга JS в браузере, то предлагаю вам не сотрясать байты в интернете попусту, а помочь с его улучшением. Исходники открыты. Мерж-реквестам всегда рады.

1) Претензии есть и они вполне конкретные и обоснованные, они для вас не удобные, потому что вы не понимаете почему натворили такую дичь, вот и пытаетесь их игнорировать и отбрыкиваться всеми способами.
2) Править такой код и разбираться в проблемах его кривой работоспособности - нет, спасибо, кровь из глаз будет мешать печатать.
3) Продвинутого? Это который не удовлетворяет самое фундаментальное требование к бенчмарку - повторяемость результатов(хотя бы в небольшом разбеге погрешности) в не зависимости от погоды в Австралии и открыта ли консоль в браузере. Но нет же, у вас просто в разы и десятки раз разнятся результаты из-за вещи, которая на это не влияет - консоль. Отсюда вывод, то что у вас там твориться, это просто неведомая дичь которая не несет ничего общего с реальным тестом тех или иных библиотек.


Вот так и быть ваш бенчмарк MobX vs Act по скорости (спойлер разница слабая), прям код скопировал у вас, только в нативном исполнении и где консоль не влияет на результат:
https://codesandbox.io/s/angry-currying-5ehe0v?file=/src/index.js
https://5ehe0v.csb.app/

Ну а отсутствие мозга очистки массива между итерациями и даже кейсами - это пять.

Ну а отсутствие мозга очистки массива между итерациями и даже кейсами - это пять

Аахха нашли к чему придраться. Это не влияет на цифры в результате, можете легко в этом убедиться(я то проверял разумеется), поэтому отношения к делу не имеет.

Зато имеет прямое отношение отсутствие вашего мозга варианта валидных тестов в отличии от этого, ибо здесь открытая/закрытая консоль на результат не влияет в отличии от вашего недоразумения)

На результат влияет миллион разных факторов.

https://stackblitz.com/edit/react-ts-1wcwyz?file=App.tsx,index.tsx
В результатах нет разницы открыта консоль или нет. О чем это говорит?

Есть претензии к платформе бенчмарков?

Да, т.к. результаты плавающие и здравого смысла в них нет. Т.к. открытая консоль: 1) Некоторые результаты делает очень медленные
2) Некоторые результаты наоборот делает ощутимо быстрее (например MobX и не только)

А если не разбираешься - не лезь.

Я то как раз разбираюсь, но с таким как ты пытаться что-то доказать - себя не уважать. Ибо всё и так очевидно, а если для тебя нет, то это твои проблемы.

Всем привет, меня зовут Артём Арутюнян

Я почему-то ожидал здесь увидеть "Дмитрий Карловский"

вы промахнулись на 1 уровень комментов

Спасибо за интересный материал. Вопрос к автору библиотеки - поддерживает ли она в каком-либо виде асинхронность?

Нет, библиотека максимально простая :) все доп плюшки в реатом, например reatom.dev/packages/async

Зарегистрируйтесь на Хабре, чтобы оставить комментарий