Выпустил апдейт 5.0.4. Значительно увеличена скорость работы pop / shift для простых объектов.
|
Выпустил апдейт 5.0.5.
Реализовано кеширование сгенерированных циклов в файле для node.js. Реализована оптимизация "холостых" итераций, т.е. без передачи параметров в callback. $C({a: 1, b: 2}).forEach(function () { ... }); $C({a: 1, b: 2}).forEach(function (el) { ... }); Первый вариант теперь работает почти в 3 раза быстрее. |
Цитата:
|
Цитата:
Конечно это оптимизация нужна очень редко, но все равно:) |
Сегодня приснился ещё один оптимизационный трюк, думаю смогу ускорить работы некоторых операций ещё процентов на 5-10 :)
|
не сравнивал скорость работы $C с fast.js?
|
Цитата:
А если сравнивать с точки зрения алгоритмической сложности, тот тут Collection быстрее всех аналогов в N раз (где N количество операций), например: filter1().filter2().map().slice(0, 10) // 4 операции + на slice потенциальный огромный оверхед $C(...).map(calback, {filter: 'filter1 && filter2', from: 0, count: 10}) // никаких оверхедов, т.к. всё делается в один проход и операция сбросится после достижения count: 10 UPD: в релизе 5.1 (надеюсь сегодня сделаю) реализовал бешеную оптимизацию для обхода Map / Set. При сравнении с нативным for of разница примерно в 40 раз, а при обходе с reverse: true, то в N раз (где N - количество элементов в коллекции). UPD:UPD: Глянул код fast.js, результат мне уже известен :) Вообще все классические оптимизации, которые применяются в underscore, lodash, fast.js и т.д. по природе своей ущербны, т.к. они их делают в живом цикле и поэтому они всегда будут проигрывать Collection или нативным циклам. А вот Collection основан на хитрой кодогенерации, т.е. полученный цикл лишён не нужных для каждого конкретного случая оптимизаций и проверок и поэтому работает с максимальной эффективностью. |
Выпустил апдейт v5.1.0.
1) Исправлена критическая бага в методе remove; 2) Очень сильно увеличена производительность обхода Map / Set коллекций; 3) Улучшен модуль инлайнинга, что дало в некоторых случаях дополнительный профит; 4) Добавлена новая сборка Collection.core, которая включает в себя только 2 основных метода: forEach и extend и весит примерно 8кб в gzip; 5) Добавлен параметр chain для некоторых итерационных методов, который позволяет делать цепочки вызовов: $C(...).map(..., {chain: true}).get() |
В планируемом обновление 5.2.0 добавлю новый контекстный метод yield (будет требоваться поддержка генераторов).
var result = $C({ ...очень большой объект... }).map(function (el, key, data, i) { this.$.i = this.$.i || 1; if (i === 1e6 * this.$.i) { this.$.i++; this.yield(); } }); $C.onFinish(result, function (value) { ... }); Т.е. метод this.yield(); прерывает выполнение операции и возвращает объект: { done: true / false, result: ... } Таким образом дробление сложной операции будет осуществляться очень просто. Работу над обновлением планирую начать сразу же, после окончания работа над Snakeskin 4. |
Также решил добавить 2 новых параметра для всех итеративных методов: iterations и onFinish
$C({ ...очень большой объект... }).forEach(function () { ... }, { iterations: 1e5, onFinish: function (value) { ... } }); Т.е. каждые 1e5 итераций будет делаться прерывание и дальнейшая работа продолжиться на следующем итерационном цикле, а onFinish будет вызван, когда операция закончиться. |
Хорошо подумав, решил отказаться от концепции iterations, а вычислять время активной операции на каждой итерации и прерывания будут разруливаться автоматически планировщиком. Каждой задаче можно будет задать приоритет.
Т.е. можно будет просто делать вызов $C и не думать, что он-что то там залочит. $C(...).forEach(() => { ... }, {worker: true}) $C(...).forEach(() => { ... }, {worker: true}) $C(...).forEach(() => { ... }, {worker: true}) $C(...).forEach(() => { ... }, {worker: true}) ... over 9000 операций Количество активных операций и сами операции будит рулить планировщик, т.е. программисту об этом думать не нужно. Интерфейс обратного вызова будет спроектирован для совместной работы Promise и Async. Самое приятное, что обновлённый движок Collection 5 позволит очень просто реализовать такую фичу с помощью оператора yield и у нас будет реальная альтернатива "тяжёлым потокам". |
как изнутри планируешь это делать? nextTick ?
|
Цитата:
Для браузера - setTimeout / setImmediate. Сейчас алгоритм примерно такой планируется: планировщик следит, чтобы все worker операции $C не занимали более 80мс в одном итерационном цикле. По умолчанию у всех операций будет одинаковый приоритет, но его можно будет указывать явно. |
Сегодня написал первую тестовую версию реализации "лёгких потоков" на основе прерываний (yield) и планировщика с системой приоритетов.
Видео Одновременно создаётся 50 forEach, в каждом по 1кк итераций и рандомно задаются приоритеты, т.е. общее количество итераций 50кк. Интерфейс не лочится и тормозов нет в принципе, результатом очень доволен. Думаю завтра / послезавтра зарелизю 5.2 версию с поддержкой. Плюсы лёгкий потоков: 1) Нет затрат на создание; 2) Т.к. всё крутится в рамках главного потока, то прямой доступ к DOM и переменным замыкания (но тут нужно быть аккуратным, ибо моно выстрелить себе в ногу :)); 3) Нет ограничений на количество создаваемых потоков (вернее есть, но равно количеству доступной памяти) Минусы: 1) Требуется поддержка генераторов, т.е. пока работает только в ФФ, Хроме и компании, Ноде. В ИЕ ожидается с 12-й версии. 2) Теоретически возможно залочить поток, если сама итерация в цикле будет очень тяжёлой. Алгоритм: В рамках одной итерации событийного цикла JS все асинхронные процессы Collection могут забрать не более 60мс времени суммарно. У каждой задачи есть приоритет (по умолчанию normal) var maxPriority = 40; var priority = { 'low' : maxPriority / 8, 'normal' : maxPriority / 4, 'hight' : maxPriority / 2, 'critical': maxPriority }; Чем выше приоритет, тем выше вероятность, что данная задача попадёт в исполнение конкретного событийного цикла (но не 100%). Задачи с одинаковым приоритетом выбираются случайно с линейным распределением. Определение выполняемых задач осуществляется на каждой итерации событийного цикла. PS: цифорки на видео - это количество выделенных на операцию итераций событийного цикла. |
Пописав день с лёгкими тредами, я уже не понимаю, как я жил без них - это просто чудо!)
|
Продумываю API вложенных потоков (т.е. поток созданный внутри потока).
Концепт такой: $C(...).forEach(function (el) { // Метод wait приостановит выполнение родительского потока, // пока не выполнится дочерний и в качестве ответа вернёт результат работы дочернего потока this.wait($C(el).forEach(function () { ... }, {thread: true})); }, {thread: true}); Также решил добавить метод .sleep который имеет следующий интерфейс: sleep(time, opt_test, opt_interval) *) время в мс *) функция-проверка, если вернёт true, то поток "проснётся" *) если true и opt_test вернёт false, то проверка будет проводится каждые time пока поток не проснётся |
Любопытно а зачем это?
кто и где это использует? |
Цитата:
Что касается плюсов / минусов перед тяжелыми потоками, то я писал выше. |
Я не в курсе, то что такое Collection.
мне просто любопытно посмотреть на реальный пример где это может использоваться. Прочитав описание я так и не придумал где(на каком реальном примере) это можно использовать (( |
|
Это я прочитал и для меня это пока выглядит бесполезно.
Просто думал что будет ссылка на реальный сайт где это реально используется. Хотелось посмотреть на задачи в которых это приносит пользу и попробовать решить эти задачи на JS. В общем покритиковать |
MallSerg, не надо придумывать. Просто запомни. Если как всегда внезапно в проекте понадобится что-то такое - тут и вспомнишь.)
kobezzza использует в своей разработке, и явно еслиб было не нужно - не писал бы.) |
Это библиотека на каждый день. Чтобы её любить необходимо:
*) Любить функциональное программирование (не путать с процедурным); *) Знать, что в JS помимо массивов есть ещё: Map, WeakMap, Set, WeakSet, Generator, TypedArrays, Object и т.д. Если эти 2 пункта не выполняются, то можно закрыть тред и не открывать более, т.к. данная либа покажется абсолютно бесполезной и что я теряю своё время. *** Я использую её каждый день в самых разных задачах и пишу для себя уже более 5 лет. |
Цитата:
|
Все выходные честно гамал и не написал ни строчки кода, поэтому перенёс релиз 5.2 на эту неделю :)
|
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
|
Map'ы и прочее кроме типизированных массивов эксперементальне технологии
|
Цитата:
|
ReferenceError: Map is not defined
|
несовременный чот хром :(
|
Цитата:
|
WeakMap & WeakSet есть
|
Генераторы вещь нужная, а вот мапы бесполезны
|
Аркадий Укупник, свали флудить куда-нить в другое место, пока не забанили.(снова)
|
Цитата:
*** Я не понимаю смысл твоих постов. Есть конкретные вопросы - задавай, а флудить с видом "умника" иди в другое место. |
Цитата:
|
Aetae, поясни за флуд?
|
Часовой пояс GMT +3, время: 11:52. |