Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Collection v5 (https://javascript.ru/forum/project/47717-collection-v5.html)

kobezzza 22.07.2016 00:09

Цитата:

Сообщение от cyber (Сообщение 422853)
kobezzza, я переодически заглядую в твой код, и интересно в чем преймущество использования https://github.com/kobezzza/Collecti...tors/thread.js
все такси всеравно выполняются на одном потоке, или я не так понял?

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

Плюсы легковесных потоков Collection:

1) Они гарантируют, что сколько бы потоков ты не создал - ты не залочишь главный поток.

Т.е. допустим у тебя сервак на ноде, и у тебя есть синхронная задачка, например, валидация файлов, а файлы большие, то ты рискуешь занимать слишком много времени главного потока и от этого пострадают твои пользователи. Тебе придётся руками дробить задачу на setImmediate и делать кусочками, а твой код превратится в какашку. С Collection тебе просто думать об этом не надо, завернул задачу в поток и всё, а т.к. потоки реализует интерфейс промисов, то с async/await твой код остаётся синхронным. Задач миллион.

Пример на клиенте: у тебя сложный СПА, куча виджетов который что-то там делают и в какойто момент времени их совместная деятельность начинает фризить UI, ну например, у тебя есть селект с автокомплитом и список данных на пару тыщ элементов и ты делаешь поиск по мере заполнения, а т.к. по мимо этого виджета у тебя там целое приложение, которое живёт своей жизнью, то фризы по 50-100 мс вообще обычное дело, но они заметны и это реально напрягает. С Collection ты вообще не думаешь много данных или нет, просто оборачиваем узкое место в поток и всё, никаких фризов.

2) Async-flow

Collection предоставляет API для создания дочерних потоков (потоков в потоке и т.д.), а также поддерживает промисы, что позволяет ловко манипулировать асинхронными потоками данных без награмаждений в коде.

$C(['file1.json', 'file2.json']).thread().reduce(async (map, file) => Object.assign(map, await fs.readFile(file)), {})


3) Доступ к переменным замыкания и DOM.

Тут конечно спорный момент, ибо легко сделать гонку :D Но при аккуратном подходе - это удобно.

4) Потоков может быть много: если Worker-ы ограничины на вкладку (по моему не больше 15 или 20-ти), то потоков Collection можно создавать пока память не кончиться) На практике это сотни тысяч.

Минусы:

1) Скорость - потоки заоптимизированы на неблокирующее выполнение, но при этом страдает скорость, т.к. всё в одном реальном потоке.

2) Можно легко устроить гонку.

***

В общем относится нужно к таким потокам, как к очень удобной абстракции.

kobezzza 22.07.2016 00:14

Готовлю новый бета релиз Collection 6. Из главных нововведений - это поддержка промисов на уровне самого Collection, т.е. теперь можно делать асинхронные фильтры:

$C(...)
  .thread()
  .filter(async () => await doSomething())
  .filter(async () => await doSomethingAgain())
  .map(...)


А также появилась поддержка нового типа данных - асинхронная коллекция. Теперь если Collection работает в режиме потока и элемент итерируемой коллекции является промисом, то Collection будет ожидать его выполнения.

Реальный кейз: читаем в NodeReadable потоке огромный файл и сразу по мере получения данных отдаём в Collection, который их как то мапит и т.д. Экономия памяти и универсальность интерфейса.

cyber 22.07.2016 09:16

kobezzza, т.е ты по сути розбиваешся каждую задачу на отдельный setImmediate?

kobezzza 22.07.2016 11:17

Цитата:

Сообщение от cyber (Сообщение 422985)
kobezzza, т.е ты по сути розбиваешся каждую задачу на отдельный setImmediate?

Да, никакой магии. Есть допуcтим forEach с приоритетом normal: за один раз он может потратить не более 10 мс, поэтому после каждой итерации я сравниваю затраченное время и если оно уже превышает лимит, то делаю yield, т.е. всё операция обёрнута в генератор, а со следующего итерационного цикла, если задача конечно туда попадёт по приоритету, продолжу с места, где закончил.

Всего за один так событийного цикла Collection тратит не более 40 мс.

cyber 22.07.2016 11:39

kobezzza, спасибо, интересно))

Vlasenko Fedor 22.07.2016 12:04

kobezzza,
$C(document.querySelectorAll('.foo')).forEach((el) => {
  ...
}

почему не написать так ?
HTMLCollection.prototype.forEach = NodeList.prototype.forEach = Array.prototype.forEach;
// ................
document.querySelectorAll('.foo').forEach((el) => {
  ...
}

то-же самое с get, map
как по мне без $C выглядит красивее, переопределив прототип

kobezzza 22.07.2016 12:27

Poznakomlus, определение методов в прототипе для встраиваемой функциональной библиотеки не самая лучшая идея, особенно учитывая что Collection поддерживает работу с Object, Map, Set, TypedArrays, Array, Generator и Promise.

В TS и JS stage-0 есть более правильные способы:

function forEach(cb, params) {
  return $C(this).forEach(cb, params);
}

[1, 2, 3]::forEach(() => {
   ...
});

Vlasenko Fedor 22.07.2016 12:58

Цитата:

Сообщение от kobezzza
В TS и JS stage-0 есть более правильные способы

честно, это наверое дело вкуса, если разработчики не реализовали forEach для списков элементов, то одной строкой можно забыть их не доработки не смотря на код транслитераторов

cyber 22.07.2016 13:48

Poznakomlus, в Collection есть разные плюшки, один из примеров http://javascript.ru/forum/project/4...tml#post422959

Vlasenko Fedor 22.07.2016 14:37

А где модель потоков с использованием динамически созданных worker? :)


Часовой пояс GMT +3, время: 08:46.