Re[11]: Для тех, кто смеется над JavaScript
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 17.06.20 09:34
Оценка: 4 (2)
Здравствуйте, Sharov, Вы писали:

H>>Это интересно. А как там с многопоточностью, в движке ноды? Как разграничивается доступ к общему ресурсу из нескольких потоков?


S>Он однопоточных и асинхронный. Доступ по идее будет сериализуемым.


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

Например, операция доступа к ресурсу следующая —
async update(path, pattern) {
   const resource = await open(path); // доступ к ресурсу разделяемый, а не эксклюзивный !!!
   const oldHeader = await readHeader(resource); 
   const {newPattern, newHeader} = await nextStep(pattern, oldHeader);

   await writeToEnd(resource, newPattern);
   await updateHeader(resource, newHeader);
   await close(resource); 
}


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

update(path, pattern1);
update(path, pattern2);
update(path, pattern3);
update(path, pattern4);
update(path, pattern5);
update(path, pattern6);


То есть, мы здесь запустили 6 параллельных цепочек, каждая из которых работает с одним и тем же разделяемым ресурсом.

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

А если вот так:

await update(path, pattern1);
await update(path, pattern2);
await update(path, pattern3);
await update(path, pattern4);
await update(path, pattern5);
await update(path, pattern6);


Вот это сериализуемый доступ, и сделано это руками. То есть, такую гарантию, как сериализуемый доступ, в ноде приходится делать руками. И так с любым разделяемым ресурсом.

Реально вот такое чудо не встречается, что бы все опреации сами по себе шли подряд, нужно пилить чтото более приемлемое. Например, соорудить нечто навроде мутекса или семафора:

const mutex = queue(1); // 1 - количество читателей-писателей которым разрешено одновременно работать с ресурсом

// http хандлер
app.post(async (req, res) => {
  const {pattern} = resolveArgs(req);

  await mutex(() => update(path, pattern)); // все запросы автоматически становятся в очередь
  res.send('', 204);
});
Отредактировано 17.06.2020 12:13 Pauel . Предыдущая версия . Еще …
Отредактировано 17.06.2020 10:43 Pauel . Предыдущая версия .
Отредактировано 17.06.2020 9:37 Pauel . Предыдущая версия .
Отредактировано 17.06.2020 9:35 Pauel . Предыдущая версия .
Re[3]: Для тех, кто смеется над JavaScript
От: Privalov  
Дата: 17.06.20 09:41
Оценка: :)
Здравствуйте, Lazytech, Вы писали:

L>К сожалению, пока не знаю ответа на этот вопрос. Я еще не сделал ни одного HTTP-сервера на Node.js


Может, не стоит начинать?
Re[4]: Для тех, кто смеется над JavaScript
От: Lazytech Ниоткуда  
Дата: 17.06.20 14:53
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Может, не стоит начинать?


Так я больше по части фронтенда...
Re[12]: Для тех, кто смеется над JavaScript
От: Sharov Россия  
Дата: 17.06.20 19:22
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Например, операция доступа к ресурсу следующая —

I>
I>async update(path, pattern) {
I>   const resource = await open(path); // доступ к ресурсу разделяемый, а не эксклюзивный !!!
I>   const oldHeader = await readHeader(resource); 
I>   const {newPattern, newHeader} = await nextStep(pattern, oldHeader);

I>   await writeToEnd(resource, newPattern);
I>   await updateHeader(resource, newHeader);
I>   await close(resource); 
I>}
I>


I>В итоге, ресурс хранит данные всех шагов некоторого вычисления и в хидере указаны соответствующие ссылки.

I>Теперь представим, что будет, если сделаем, скажем, вот такую хрень

I>
I>update(path, pattern1);
I>update(path, pattern2);
I>update(path, pattern3);
I>update(path, pattern4);
I>update(path, pattern5);
I>update(path, pattern6);
I>


I>То есть, мы здесь запустили 6 параллельных цепочек, каждая из которых работает с одним и тем же разделяемым ресурсом.


Разве это параллельное исполнение? Это а-ля корутины для эмуляции многопоточности, т.е. в один момент времени с файлом будет работать только один
update(path, patternX), но мы правда не знаем какой...
Кодом людям нужно помогать!
Re[11]: Для тех, кто смеется над JavaScript
От: Ops Россия  
Дата: 17.06.20 22:46
Оценка: +1 :)
Здравствуйте, Lazytech, Вы писали:

L>На днях, делая свое первое приложение на Node.js, был приятно удивлен простотой использования CommonJS (особенно если применять деструктуризацию). А в свежую версию Node вроде добавили поддержку ECMAScript Modules (пока experimental), с которыми работать еще удобнее.


Да, у этих модулей тоже зоопарк.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[13]: Для тех, кто смеется над JavaScript
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 18.06.20 07:17
Оценка: 1 (1)
Здравствуйте, Sharov, Вы писали:

I>>То есть, мы здесь запустили 6 параллельных цепочек, каждая из которых работает с одним и тем же разделяемым ресурсом.


S>Разве это параллельное исполнение? Это а-ля корутины для эмуляции многопоточности,


Это именно параллельное исполнение. В каком порядке выполняться будут операции и их части — никому неизвестно.

async/await это не эмуляция многопоточности, это связывание кусочков одной цепочки вместе. Унутре принципиально те же колбеки.

S>т.е. в один момент времени с файлом будет работать только один update(path, patternX), но мы правда не знаем какой...


async/await это принципиально тот же коллбек. Что бы гарантировать, что с ресурсом будет работать ровно один update, нужен механизм для линеаризации, та самая queue из моего примера.

Если логическая цепочка одна — то её части выполняются последовательно, для этого и нужен async/await, это связывание. Ровно так же, как и с колбеком-продолжением.

А вот если цепочек несколько, то никаких гарантий тебе никто не даст.

Вот решение задачи — просто инкрементим содержимое файла. Попробуй поиграться, запуская от 1 до n задач.

Колбеки
http://rsdn.org/forum/flame.comp/6423076.1
Автор: Ikemefula
Дата: 20.04.16


async/await:
const {readFileSync} = require('fs');
const fs = require('fs').promises;
const fileName = 'i';

async function read_i() {
    const x = await fs.readFile(fileName, {encoding:'utf8'});
    
    return toNumber(x);
}

function write_i(i) {
    return fs.writeFile(fileName, i);
}

function toNumber(buffer) {
    return +(buffer || 0).toString();
}

async function task(n, id) {
    while(n--) {
        tap('before read_i', id);
        const i = await read_i();
        tap('after read_i', id);
        await write_i(i + 1);
        tap('after write_i', id);
    }
}

function tap(msg, id) {
    console.log(msg, readFileSync(fileName, {encoding:'utf8'}), id);
}

fs.writeFileSync(fileName,'');

task(10, 1);
task(10, 2);
task(10, 3);
task(10, 4);
task(10, 5);
task(10, 6);
Отредактировано 20.06.2020 4:59 Pauel . Предыдущая версия . Еще …
Отредактировано 18.06.2020 7:19 Pauel . Предыдущая версия .
Re[12]: Для тех, кто смеется над JavaScript
От: TimurSPB Интернет  
Дата: 18.06.20 09:30
Оценка: -1
I>А если вот так:

I>
I>await update(path, pattern1);
I>await update(path, pattern2);
I>await update(path, pattern3);
I>await update(path, pattern4);
I>await update(path, pattern5);
I>await update(path, pattern6);
I>


I>Вот это сериализуемый доступ, и сделано это руками. То есть, такую гарантию, как сериализуемый доступ, в ноде приходится делать руками. И так с любым разделяемым ресурсом.

А если из "await update(path, pattern3)" полетит exception, то будет невнятное "Unhandled blabla..." без нормального стека и отладочным адом. Там же надо .catch ещё прописать, если я ничего не путаю. Или уже придумали нового сахара?

I>Реально вот такое чудо не встречается, что бы все опреации сами по себе шли подряд, нужно пилить чтото более приемлемое. Например, соорудить нечто навроде мутекса или семафора:

Грозились же в ноде сделать мьютексы и потоки.

I>
I>const mutex = queue(1); // 1 - количество читателей-писателей которым разрешено одновременно работать с ресурсом
I>// http хандлер
I>app.post(async (req, res) => {
I>  const {pattern} = resolveArgs(req);

I>  await mutex(() => update(path, pattern)); // все запросы автоматически становятся в очередь
I>  res.send('', 204);
I>});
I>

Опять же с обработкой ошибок не понятно, и внутренний голос говорит что однажды всё зависнет в строчке "await mutex(() => update(path, pattern))" из-за хрен пойми чего.

Как только нужно будет всё сделать в продуктовом качестве, так сразу всё обрастёт соплями и затычками. Нужно очень хорошее понимание принципов работы всего под капотом ноды, знание всех бест практикс и развитый мозг. Где взять таких программистов? Это рушит концепцию быстрого тайм ту маркет, одного языка для бэкенда и фронта. Не получается дёшево и эффективно, как это нередко утверждается про nodejs.
Make flame.politics Great Again!
Re[2]: Для тех, кто смеется над JavaScript
От: Ops Россия  
Дата: 18.06.20 09:40
Оценка: +1
Здравствуйте, Maniacal, Вы писали:

M>Один опытный JavaScript-программист ещё во времена DHTML 4.0 мне тогда ещё неопытному в 1998 году говорил, что на JS можно сделать всё. И это реально правда даже по меркам того времени.


Это для любого тьюринг-полного языка правда.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[13]: Для тех, кто смеется над JavaScript
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 18.06.20 09:53
Оценка:
Здравствуйте, TimurSPB, Вы писали:

I>>Вот это сериализуемый доступ, и сделано это руками. То есть, такую гарантию, как сериализуемый доступ, в ноде приходится делать руками. И так с любым разделяемым ресурсом.

TSP>А если из "await update(path, pattern3)" полетит exception, то будет невнятное "Unhandled blabla..." без нормального стека и отладочным адом. Там же надо .catch ещё прописать, если я ничего не путаю. Или уже придумали нового сахара?

Обычный сахар — try...catch, и не надо ничего придумывать.

I>>Реально вот такое чудо не встречается, что бы все опреации сами по себе шли подряд, нужно пилить чтото более приемлемое. Например, соорудить нечто навроде мутекса или семафора:

TSP>Грозились же в ноде сделать мьютексы и потоки.

При чем здесь это? Увидел слово мутекс и решил вспомнить потоки? Мутекс нужен в любой многозадачности, даже однопоточной, как ноде.
Да, в ноде многозадачность на одном потоке.

TSP>Опять же с обработкой ошибок не понятно, и внутренний голос говорит что однажды всё зависнет в строчке "await mutex(() => update(path, pattern))" из-за хрен пойми чего.


Однажды у тебя и в потоке может случиться бесконечный цикл или дедлок. Что с того?
Async/await как и промисы, это обычные колбеки унутре, никакой магии.
Потерял маленький кусочек и никогда не дождешься окончания задачи. Чем это отличается от кода в дотнете на асинк-авейтах? Ничем. Потерял — недождешься.


TSP>Как только нужно будет всё сделать в продуктовом качестве, так сразу всё обрастёт соплями и затычками.


У меня ничего не обрастает и работает как положено. Собственно, у большинства примерно так же. Обрастает соплями и затычками в любом стеке, хоть дотнет, хоть нод, хоть джава, по самым разным причинам — в основном из за особого отношения к работе "и так сойдет".
Отредактировано 18.06.2020 9:57 Pauel . Предыдущая версия .
Re[3]: Для тех, кто смеется над JavaScript
От: Maniacal Россия  
Дата: 18.06.20 11:41
Оценка: 1 (1)
Здравствуйте, Ops, Вы писали:

Ops>Здравствуйте, Maniacal, Вы писали:


M>>Один опытный JavaScript-программист ещё во времена DHTML 4.0 мне тогда ещё неопытному в 1998 году говорил, что на JS можно сделать всё. И это реально правда даже по меркам того времени.


Ops>Это для любого тьюринг-полного языка правда.


Он имел в виду связку Винда+IE в те времена. Полноценный GUI со всякими прогрессбарами, статусбарами, листбоксами, выпадающими меню и другими интерактивными самописными элементами (DHTML), 2D и 3D анимация (DirectAnimation), работа со звуком, джойстиком (DirectInput), работа с сетью (DirectPlay). Про работу с "БД" тоже что-то было написано в учебнике (с файлами на стороне сервера).
Re[14]: Для тех, кто смеется над JavaScript
От: TimurSPB Интернет  
Дата: 18.06.20 12:01
Оценка:
I>Обычный сахар — try...catch, и не надо ничего придумывать.
Так?
try {
    await update(path, pattern1);
    await update(path, pattern2);
    await update(path, pattern3);
    await update(path, pattern4);
    await update(path, pattern5);
    await update(path, pattern6);
} catch(e) {
    console.log(e);
}

Тогда непонятно будет откуда оно полетело.

I>У меня ничего не обрастает и работает как положено. Собственно, у большинства примерно так же. Обрастает соплями и затычками в любом стеке, хоть дотнет, хоть нод, хоть джава, по самым разным причинам — в основном из за особого отношения к работе "и так сойдет".

У тебя будет, но сколько ты стоишь и где найти команду таких как ты? В суровой реальности с этим проблемы.
Make flame.politics Great Again!
Re[15]: Для тех, кто смеется над JavaScript
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 18.06.20 13:49
Оценка:
Здравствуйте, TimurSPB, Вы писали:

TSP>Тогда непонятно будет откуда оно полетело.


Бывает.

I>>У меня ничего не обрастает и работает как положено. Собственно, у большинства примерно так же. Обрастает соплями и затычками в любом стеке, хоть дотнет, хоть нод, хоть джава, по самым разным причинам — в основном из за особого отношения к работе "и так сойдет".

TSP>У тебя будет, но сколько ты стоишь и где найти команду таких как ты? В суровой реальности с этим проблемы.

Проблема аналогична тем, что в других стеках. Единственно, где сливает именно жээс, это числодробилки. Это особенность такой его многозадачности.
Re[14]: Для тех, кто смеется над JavaScript
От: Мирный герцог Ниоткуда  
Дата: 18.06.20 15:32
Оценка: 1 (1) +3 -1
Здравствуйте, Ikemefula, Вы писали:

I>Это именно параллельное исполнение. В каком порядке выполняться будут операции и их части — никому неизвестно.


пожалуйста изучите термины, прежде чем их использовать. Это не параллельное исполнение, это асинхронное исполнение continuation'ов (в случае с js — генераторов, в других языках, как уже упомянули выше — это могли бы быть корутины). Параллельное исполнение подразумевает два+ вычислителя(две+ машины тьюринга — два+ процессора, две+ виртуальные машины, два+ стека), работающих одновременно. В node.js исполнительный поток один (хотя есть и воркеры). Грубо говоря у вас например никогда не будет гонки при инкременте глобального счётчика, т.к. параллельно код инкремента исполнится не может в принципе.
нормально делай — нормально будет
Re[3]: Для тех, кто смеется над JavaScript
От: RonWilson Россия  
Дата: 18.06.20 15:33
Оценка: :)
Здравствуйте, Lazytech, Вы писали:

L>К сожалению, пока не знаю ответа на этот вопрос. Я еще не сделал ни одного HTTP-сервера на Node.js


не стоит этого делать, а то еще в backend затянет, а это заразно
Re[15]: Для тех, кто смеется над JavaScript
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 18.06.20 16:59
Оценка:
Здравствуйте, Мирный герцог, Вы писали:

МГ>Здравствуйте, Ikemefula, Вы писали:


I>>Это именно параллельное исполнение. В каком порядке выполняться будут операции и их части — никому неизвестно.


МГ>пожалуйста изучите термины, прежде чем их использовать. Это не параллельное исполнение, это асинхронное исполнение continuation'ов (в случае с js — генераторов, в других языках, как уже упомянули выше — это могли бы быть корутины).


В Windows файберы https://docs.microsoft.com/en-us/windows/win32/procthread/fibers
и солнце б утром не вставало, когда бы не было меня
Re[15]: Для тех, кто смеется над JavaScript
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 18.06.20 18:09
Оценка: 1 (1)
Здравствуйте, Мирный герцог, Вы писали:

МГ>пожалуйста изучите термины, прежде чем их использовать. Это не параллельное исполнение, это асинхронное исполнение continuation'ов (в случае с js — генераторов, в других языках, как уже упомянули выше — это могли бы быть корутины). Параллельное исполнение подразумевает два+ вычислителя(две+ машины тьюринга — два+ процессора, две+ виртуальные машины, два+ стека), работающих одновременно. В node.js исполнительный поток один (хотя есть и воркеры). Грубо говоря у вас например никогда не будет гонки при инкременте глобального счётчика, т.к. параллельно код инкремента исполнится не может в принципе.


Ты путаешь логическое и физическое выполнение. Физическое как раз интересует меньше всего, т.к. ты никогда не знаешь, сколько у тебя физических вычислителей. Все что ты можешь сказать, что их больше нуля. Раз код выполняется, есть минимум 1

Соответственно, у меня в коде показаны логически 6 параллельных задач.

Гонки это свойство многозадачности, а не только потоков. Абсолютно любая многозадачность имеет гонки в соответствии со своей природой.

Гонки при инкременте глобального счетчика — раскрой глаза, я именно этот вариант показал. Все определяет протокол доступа к ресурсу. Если операция над ресурсом в рамках конкретной многозадачности неатомарна, то она будут давать те самые гонки если запустить параллельно несколько таких операций.
Re[9]: Для тех, кто смеется над JavaScript
От: Sheridan Россия  
Дата: 19.06.20 06:52
Оценка: -1
Здравствуйте, Reset, Вы писали:

R>Асинхронные фреймворки есть почти на всем, но в NodeJS асинхронщина изначально закладывалась как обязательная возможность.

Нет. жс тупо по другому не умеет. Приходится изворачиваться.
Matrix has you...
Re[16]: Для тех, кто смеется над JavaScript
От: Мирный герцог Ниоткуда  
Дата: 19.06.20 07:43
Оценка: +2 -1
Здравствуйте, Ikemefula, Вы писали:

I>Ты путаешь логическое и физическое выполнение.

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

I>Гонки это свойство многозадачности, а не только потоков. Абсолютно любая многозадачность имеет гонки в соответствии со своей природой.

я смотрю ты не понимаешь что такое гонки. Гонки, это когда у тебя выполняется 10 инкрементов, а в результате переменная инкрементируется на 9, или вообще на 1, вот это гонки. А то что ты называешь "гонками" это обычное асинхронное исполнение. Оно по определению не упорядоченно, но это не гонки и не "параллелизм".

I>Гонки при инкременте глобального счетчика — раскрой глаза, я именно этот вариант показал.

Я ещё раз говорю, давай код в котором в ноде будет гонка с инкрементом счётчика. То что ты можешь растекаться по древу мыслями используя собственное понимание общепринятой терминологию я уже понял.
нормально делай — нормально будет
Re[17]: Для тех, кто смеется над JavaScript
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 19.06.20 09:30
Оценка:
Здравствуйте, Мирный герцог, Вы писали:

МГ>Здравствуйте, Ikemefula, Вы писали:


I>>Ты путаешь логическое и физическое выполнение.

МГ>нет, я ничего не путаю, я вообще не говорил о "логическом" и "физическом" выполнении, особенно странно слышать о "физическом" выполнении когда я явно упомянул виртуальную машину как вычислитель.

В том то и дело, что не говорил, а надо бы Логически в моем примере целых 6 задач выполняются параллельно. Физически — однопоточный интерпретатор управляет состоянием и работой многопоточной виртуальной машины.
Из букваря по Node.js — физически отдельные части операций или даже операции целиком выполняются на отдельных вычислителях, ядрах, процессорах или потоках. Например, чтение из файла может выполняться буквально одновременно — два разных потока вычитывают все что надо, а по окончании готовый результат прокидывают в интерпретатор. Возможности параллелизма ограничены в данном случае не количеством ядер-процессоров, а возможностями системной шины.
Даже если под капотом нода ничего не будет(гипотетически), все равно есть операционка, и она точно может делать несколько дисковых операций одновременно.

Даже если ограничить node, теоретически, одним ядром-потоком на все его активности, логически всё равно будет 6 параллельных задач. С т.з. физического параллелизма будет использоваться другая стратегия распределения времени.

I>>Гонки это свойство многозадачности, а не только потоков. Абсолютно любая многозадачность имеет гонки в соответствии со своей природой.

МГ>я смотрю ты не понимаешь что такое гонки. Гонки, это когда у тебя выполняется 10 инкрементов, а в результате переменная инкрементируется на 9, или вообще на 1, вот это гонки. А то что ты называешь "гонками" это о бычное асинхронное исполнение. Оно по определению не упорядоченно, но это не гонки и не "параллелизм".

Тут надо вспомнить, что гонки и есть отсутствие упорядочения доступа к разделяемому ресурсу из за неконтролируемых событий, таймингов и тд. Поскольку асинхронное исполнение неупорядочено по времени, то при доступе к разделяемому ресурсу будет плодить гонки. И так вне зависимости от вида многозадачности.
Например — мы знаем, что запросы open выполняются одним за другим, это гарантирует интерпретатор, а вот ответы ядра нода, операционки, могут приходить как им вздумается, в любом порядке, упорядочения нет, правильно? Отсюда и возникают гонки, что и демонстрируется примерами кода.

I>>Гонки при инкременте глобального счетчика — раскрой глаза, я именно этот вариант показал.

МГ>Я ещё раз говорю, давай код в котором в ноде будет гонка с инкрементом счётчика. То что ты можешь растекаться по древу мыслями используя собственное понимание общепринятой терминологию я уже понял.

Ты хочешь увидеть частный случай — гонки из за многопоточности. Объект в другой воркер или даже поток можно передавать как по значению, так и по ссылке.

Гонки возможны на всех без исключения видах многозадачности. Собственно, от них в любой многозадачности никуда не деться.
Отредактировано 19.06.2020 10:05 Pauel . Предыдущая версия .
Re[10]: Для тех, кто смеется над JavaScript
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 19.06.20 10:17
Оценка: +1
Здравствуйте, Sheridan, Вы писали:

R>>Асинхронные фреймворки есть почти на всем, но в NodeJS асинхронщина изначально закладывалась как обязательная возможность.

S>Нет. жс тупо по другому не умеет. Приходится изворачиваться.

Нод принципиально делался асинхронным — именно эта асинхронность и стала причиной появления Нода.
По другому — умеет, например, есть синхронные, т.е. блокирующие вызовы, запросто. Есть воркеры, есть потоки, есть возможность передать туда как по значению, так и по ссылке.
Там где надо, в ноде используются и потоки, и воркеры.

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

На самом деле большинство задач в веб-приложениях никакой тяжелой логики не выполняют, просто передают данные с минимальными изменениями. То есть, CPU не является узким местом. Большинство это примерно 8..9 из 10.
То есть, потоки фактически заняты на 80-90% времени ожиданием ответа другой системы, бд, нетворка и тд. Это было уже задолго до Нода.
Именно эта особенность побудила разных людей взяться за эксперименты — разные платформы, разные языки.
Один из этих людей был автор Нода.
Отредактировано 19.06.2020 10:48 Pauel . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.