А я правильно понял, что до пункта 9 - наш кенгуру фронтенд и бэкенд были недоступны для пользователей? И их можно было... А как вообще их можно было открыть в кластере? Глянуть на фронт в браузере, отправить запросик на бэк?
Очень интересно и очень сложно. На потоке-координаторе я сломался.
Что, куда, откуда? port1 и port2 и там и тут. Какой порт на что подписан? И вообще потерял что такое parentPort :) Читать очень сложно. На чтение только этой части ушло почти 1,5 часа.
Тем не менее всё интересно, спасибо!
В итоге, я надеюсь, что остался с примерно правильным пониманием:
сначала создаётся координатор, с ним создаётся канал для сигналов (и какой-то части данных). Координатору добавляется св-во "порт сигналов".
затем создаются обычные рабочие, с каждым создаётся канал для сигналов (и какой-то части данных). Также добавляется св-во "порт сигналов".
затем между ними создаётся канал данных. И через доступные порты сигналов (из св-тв объекта), созданные ранее, отправляются порты данных. В каждый по одному.
дальше клубок подписок. Рабочий, получив по сигнальному порту информацю о порте данных сразу его подписывает на обработчик. И магическим образом сразу что-то сигнализирует куда-то.
координатор же, получив по сигнальному порту информацию о порте данных, сначала записывает его в пул. А потом уже подписывает на него обработчик. И тоже магически что-то отправляет по сигнальному порту кому-то.
потом появляется "парент порт". Это обработчик вызовов из основнова потока. куда мы кидаем пары {id, message}. Координатор в случае получения задания должен сразу попытаться его кому-то назначить (видимо, не дожидаясь готовности потоков), а если некому - сохранить сообщение в очереди.
Потребовалось рзаве тольно немного времени, чтобы вспомнить к чему эти << и |0. Кстати, а зачем так писать? Почему не просто десятичным числом? Это какие-то трюки?
Задам только тупой вопрос: подход применим только и именно для потоков? Я имею в виду, если я создам n промисов, которые будут читать/писать каку-то глоб. переменную, ситуация гонок ведь тоже будет? И Аtomics с семафором это дело порешают?
Я в первые читаю про оконные функции, до этого только слышал обрывки. Благодарен за эту вводную статью.
А можете подсказать, что было бы в последнем примере с функциями смещения, если бы там был не только Петя, но и Маша, как в других примерах?
Просто сложилось впечатление, что тогда будет одна большая портиция и корректно на стыке имён функция не отработает, особенно если добавлять строки непоследовательно (Маша, Петя, Маша,...)
А я правильно понял, что до пункта 9 - наш кенгуру фронтенд и бэкенд были недоступны для пользователей? И их можно было... А как вообще их можно было открыть в кластере? Глянуть на фронт в браузере, отправить запросик на бэк?
Спасибо за пояснение. Я так и подумал, но почему-то засомневался.
Дочитал до конца. Хотел было спросить, как же передаётся данные отправляются обрано в основной поток, как в пред. примере (worker.postMessage),
но внимательно всё сопоставив, кажется, понял. Как вы и написали, вместо события on('message'), поток дожидается освобождения блокировки.
Прекрасные статьи, спасибо большое!
Спасибо за статью!
Прочитал пока только первую часть. И вопрос к ней:
А почему
remainне в области разделяемой памяти? Когда мы делаем--remain, тут не может быть неопределённого состояния счетчика?Очень интересно и очень сложно. На потоке-координаторе я сломался.
Что, куда, откуда? port1 и port2 и там и тут. Какой порт на что подписан? И вообще потерял что такое parentPort :) Читать очень сложно. На чтение только этой части ушло почти 1,5 часа.
Тем не менее всё интересно, спасибо!
В итоге, я надеюсь, что остался с примерно правильным пониманием:
сначала создаётся координатор, с ним создаётся канал для сигналов (и какой-то части данных). Координатору добавляется св-во "порт сигналов".
затем создаются обычные рабочие, с каждым создаётся канал для сигналов (и какой-то части данных). Также добавляется св-во "порт сигналов".
затем между ними создаётся канал данных. И через доступные порты сигналов (из св-тв объекта), созданные ранее, отправляются порты данных. В каждый по одному.
дальше клубок подписок. Рабочий, получив по сигнальному порту информацю о порте данных сразу его подписывает на обработчик. И магическим образом сразу что-то сигнализирует куда-то.
координатор же, получив по сигнальному порту информацию о порте данных, сначала записывает его в пул. А потом уже подписывает на него обработчик. И тоже магически что-то отправляет по сигнальному порту кому-то.
потом появляется "парент порт". Это обработчик вызовов из основнова потока. куда мы кидаем пары {id, message}. Координатор в случае получения задания должен сразу попытаться его кому-то назначить (видимо, не дожидаясь готовности потоков), а если некому - сохранить сообщение в очереди.
Восхитительная статья!
Потребовалось рзаве тольно немного времени, чтобы вспомнить к чему эти << и |0. Кстати, а зачем так писать? Почему не просто десятичным числом? Это какие-то трюки?
Спасибо большое за развернутый ответ. Ваша статья побудила меня самого сегодня написать ряд тестов, чтобы наконец-то уже разобраться в этом деле :)
Спасибо больше за сатью. Написано интересно!
Задам только тупой вопрос: подход применим только и именно для потоков? Я имею в виду, если я создам n промисов, которые будут читать/писать каку-то глоб. переменную, ситуация гонок ведь тоже будет? И Аtomics с семафором это дело порешают?
А подскажите дилетанту, вот нашли вы ошибку в памяти. А дальше что? Это как-то чинится в домашних условиях?
Спасибо. А для ленивых ссылку на офф доку или блог не добавите?) Вы сделали потрясающий и очень ценный анализ. Ссылка на источник - просто бонус)
Спасибо! Отличная статья! Осталось написать таки свою опенсорс либу а-ля этот сегметер, чтобы на ноде и можно было)
Интересная статья, спасибо.
Надо будет прочитать предыдущие.
Я так понял, вы разработали свой инструмент нагрузочного тестирования?
Подскажите, в предыдущих статьях цикла есть примеры генерации нагрузки (ну, не как в этой статье с единичкой :))?
Я в первые читаю про оконные функции, до этого только слышал обрывки. Благодарен за эту вводную статью.
А можете подсказать, что было бы в последнем примере с функциями смещения, если бы там был не только Петя, но и Маша, как в других примерах?
Просто сложилось впечатление, что тогда будет одна большая портиция и корректно на стыке имён функция не отработает, особенно если добавлять строки непоследовательно (Маша, Петя, Маша,...)
Спасибо за статью.
А сможете добавить пару слов о том как пофиксить случай из самого первого примера?
Который перед словами
Там в примере
export const createCatName = () => 'fluffy'
//...
// @filename: app.ts
import type { createCatName } from './animal.js'
Это не ошибка? или можно писать imort type незаморачиваясь?
Ну а дальше что сделали?
Хотя, посмотрев внимательнее, я, вроде, догадался.
А как был посчитан поправочный коэффициент? Просто интересно)
А в чем смысл?
Зачем такое может понадобиться?
Я только начинаю учить этот стек, и вот статья без примеров кода вызывает вопросы.
вот как ф-ия onChange установит в стейт что-либо? Прокидывать в неё ф-ии setState аргументами?
Или так
что, вроде, тоже антипаттерн, каждый рендер реакт будет создавать новую функцию.
А если почти везде стрелочные ф-ии вместо
function someName() {}как указать, что они void? Переписывать всё наconst myFunc = function(): void {}?А зачем делать у ф-ии тип возвращаемого значения unknown?
Потом же результат работы такой ф-ии TS не даст использовать, разве нет?