Обновить
3
0
Алексей Плехов@LaoAx

Пользователь

Отправить сообщение

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

Спасибо за пояснение. Я так и подумал, но почему-то засомневался.

Дочитал до конца. Хотел было спросить, как же передаётся данные отправляются обрано в основной поток, как в пред. примере (worker.postMessage),

но внимательно всё сопоставив, кажется, понял. Как вы и написали, вместо события on('message'), поток дожидается освобождения блокировки.

Прекрасные статьи, спасибо большое!

Спасибо за статью!

Прочитал пока только первую часть. И вопрос к ней:

А почему remain не в области разделяемой памяти? Когда мы делаем --remain, тут не может быть неопределённого состояния счетчика?

Очень интересно и очень сложно. На потоке-координаторе я сломался.

Что, куда, откуда? port1 и port2 и там и тут. Какой порт на что подписан? И вообще потерял что такое parentPort :) Читать очень сложно. На чтение только этой части ушло почти 1,5 часа.

Тем не менее всё интересно, спасибо!

В итоге, я надеюсь, что остался с примерно правильным пониманием:

  1. сначала создаётся координатор, с ним создаётся канал для сигналов (и какой-то части данных). Координатору добавляется св-во "порт сигналов".

  2. затем создаются обычные рабочие, с каждым создаётся канал для сигналов (и какой-то части данных). Также добавляется св-во "порт сигналов".

  3. затем между ними создаётся канал данных. И через доступные порты сигналов (из св-тв объекта), созданные ранее, отправляются порты данных. В каждый по одному.

  4. дальше клубок подписок. Рабочий, получив по сигнальному порту информацю о порте данных сразу его подписывает на обработчик. И магическим образом сразу что-то сигнализирует куда-то.

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

  6. потом появляется "парент порт". Это обработчик вызовов из основнова потока. куда мы кидаем пары {id, message}. Координатор в случае получения задания должен сразу попытаться его кому-то назначить (видимо, не дожидаясь готовности потоков), а если некому - сохранить сообщение в очереди.

Восхитительная статья!

Потребовалось рзаве тольно немного времени, чтобы вспомнить к чему эти << и |0. Кстати, а зачем так писать? Почему не просто десятичным числом? Это какие-то трюки?

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

Спасибо больше за сатью. Написано интересно!

Задам только тупой вопрос: подход применим только и именно для потоков? Я имею в виду, если я создам n промисов, которые будут читать/писать каку-то глоб. переменную, ситуация гонок ведь тоже будет? И Аtomics с семафором это дело порешают?

А подскажите дилетанту, вот нашли вы ошибку в памяти. А дальше что? Это как-то чинится в домашних условиях?

Спасибо. А для ленивых ссылку на офф доку или блог не добавите?) Вы сделали потрясающий и очень ценный анализ. Ссылка на источник - просто бонус)

Спасибо! Отличная статья! Осталось написать таки свою опенсорс либу а-ля этот сегметер, чтобы на ноде и можно было)

Интересная статья, спасибо.

Надо будет прочитать предыдущие.

Я так понял, вы разработали свой инструмент нагрузочного тестирования?

Подскажите, в предыдущих статьях цикла есть примеры генерации нагрузки (ну, не как в этой статье с единичкой :))?

Я в первые читаю про оконные функции, до этого только слышал обрывки. Благодарен за эту вводную статью.

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

Просто сложилось впечатление, что тогда будет одна большая портиция и корректно на стыке имён функция не отработает, особенно если добавлять строки непоследовательно (Маша, Петя, Маша,...)

Спасибо за статью.

А сможете добавить пару слов о том как пофиксить случай из самого первого примера?

Который перед словами

Помимо создания функции при каждом вызове компонента теперь дополнительно создаётся массив зависимостей...

Там в примере

export const createCatName = () => 'fluffy'

//...

// @filename: app.ts
import type { createCatName } from './animal.js'

Это не ошибка? или можно писать imort type незаморачиваясь?

Ну а дальше что сделали?

Хотя, посмотрев внимательнее, я, вроде, догадался.

А как был посчитан поправочный коэффициент? Просто интересно)

А в чем смысл?

type MessageOf<T> = T extends { message: unknown } ? T['message'] : never
...
type DogMessageContents = MessageOf<Dog>

Зачем такое может понадобиться?

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

onChange вызывает обработчик события с аргументом value, который и установит в стейт value и isValid

вот как ф-ия onChange установит в стейт что-либо? Прокидывать в неё ф-ии setState аргументами?

Или так

onChange = (value) => { 
  setValue(value);
  setIsValid(validate(value));
}

что, вроде, тоже антипаттерн, каждый рендер реакт будет создавать новую функцию.

Контекстуальная типизация (contextual typing), основанная на void, не запрещает функции что-либо возвращать.

А если почти везде стрелочные ф-ии вместо function someName() {} как указать, что они void? Переписывать всё на const myFunc = function(): void {}?

А зачем делать у ф-ии тип возвращаемого значения unknown?

Потом же результат работы такой ф-ии TS не даст использовать, разве нет?

Информация

В рейтинге
Не участвует
Откуда
Ижевск, Удмуртия, Россия
Дата рождения
Зарегистрирован
Активность