Сообщение Re[23]: Почему Эрланг от 17.06.2015 8:39
Изменено 17.06.2015 8:51 vdimas
Здравствуйте, Sinclair, Вы писали:
V>>Я предпочитаю озвучить ТЗ, потому что это иначе спекуляции.
S>Какое ТЗ? Речь идёт о целом классе задач, у которых есть характерные общие черты.
Это слишком широкая трактовка. Конкретно мы с Ikemefula спорим о таком феномене, как "гонки". А это вполне конкретное событие, не допускающее столь широкого толкования, как ты попытался.
V>>Потому как иначе получается, что ты тоже умудрился много чего проигнорировать, например, то, что сама операция SetRemoteResource должна быть атомарной, например, для случая, когда тип I представлен значением, которое не записывается в своё хранилище за одну операцию процессора. Как эту атомарность обеспечивать будем в случае жабасрипта?
S>Ну, если у нас есть готовое решение для обеспечения атомарности всего блока, то уж наверное можно его применить и к отдельной операции, нет?
Ну конечно. Тут можно рассуждать сколько угодно далеко, всё дальше от сути спора о "гонках".
Вот это меня и возмутило в твоём примере... бо он настолько абстрактен, что в него можно впихнуть Всю Сущность Мироздания даже в любимом твоём том самом физическом смысле, бо физические процессы именно таковы и есть — происходят во времени и пространстве, да еще и одновременно (параллельно) ). Вот и всё что ты сказал в том посте. ))
V>>Вопрос, нужны ли в случае жабасрипта критические секции, мьютексы и т.д. для этой задачи?
S>Всё зависит от того, есть ли у нас гарантия единственности системного потока, в котором бегут эти логические потоки.
Золотые слова. ))
Об этом уже 3-й год идет спор.
Ну не то, чтобы прям всё время идет... но просто вернулись к одному эпическому спору.
Я однажды ляпнул, что если вся кооперативная многозадачность сидит на одном потоке ОС, типа как в ГУИ или в жабаскрипте, то можно построить код так, чтобы критические секции (и прочие мьютексы/семафоры) были не нужны. Теперь Ikemefula бегает за мной по всем форумам, вызывая на продолжение того спора. Но я уже, если честно, пожалел о том, что поддался на провокации. )) Потому что еще в тот раз было дано объяснение с намного большей степенью подробности, чем сейчас.
S>Потому что если вдруг VM начала использовать N потоков (или если мы тупо запустили 2 инстанса VM на одной машине), то без примитивов мы получаем гарантию мусора.
Да. Вот именно поэтому я уделил приличную часть этого поста
S>Да, это так. Но вот эту уверенность лучше основывать на чём-то надёжнее, чем "я пока ни разу такого не видел".
Дык, у нас любой код пляшет от неких гарантий. Например, GUI-поток в виндах. Это же тоже гарантия, не? Ты же наверняка поупражнялся достаточно в GUI на клиентских приложениях в своё время? Думаю, ты пользовался знанием о том, где у тебя GUI-поток, а где нет. Более того, даже если в приложении было больше одного GUI-потока, ты всё-равно понимал детали происходящего. Например такие, что к некоторому окошку придут сообщения только из того потока, в котором это окошко создано.
С дотнетом 4.0 и выше идут 3 шедуллера Task-ов в комплекте, и об одном из них так и говорится — вот этот шедуллер основан на GUI-очереди сообщений, со всеми сопутствующими гарантиями. Пользуйтесь, если желаете.
S>Потому что я видел много "многопоточного" кода, который уверенно работал ровно до момента запуска на многоядерной машине.
Ну значит, он не работал и на одноядерной. ))
Потому что прерывания ядра — они такие, беспощадные, сцуко.
Бывают даже посреди операции i++.
Просто вероятность проявления ошибок на одноядерной машине была низка. Низкая вероятность проявления ошибки и отсутствие ошибки — это две большие разницы. Я же веду рассуждения именно об отсутствии ошибки в том, чтобы полагаться на однопоточный доступ к "контексту" жабаскрипта. Это как окно GUI — для каждого отдельного окна GUI гарантируется вызов событий только в одном системном потоке в один момент времени... Даже если этот поток переползет на другое ядро в процессе своей жизни. Точно так же и Node.js, даже если событие к некоему контексту будет обработано потоком из пула потоков, гарантируется, что в один момент времени контекст будет выполнять свой скриптовый код только из одного потока.
S>Ну, для этого придётся специально постараться. Но это будет ожидаемым поведением — важное выделено. В наивной реализации блокируюшего IO заблокируется вообще весь мир, а не только зависимые таски.
Традиционно блокирующее IO используется только в приватных потоках. Поэтому весь мир прекрасно живет даже в случае блокирующих потоков. И я не хочу спорить тут о сценариях, когда это плохо (твои 10тыщ соединений к серваку), бо намного больше сценариев, когда это работает намного-намного эффективней асинхронного ввода-вывода (раза в 2-3). Я как раз по работе этим занят. Кароч, под разные сценарии подходят разные решения.
В любом случае, это всё ушло далеко от первоначального спора. Потому что тому, что ты утверждаешь, у меня нет поля для возражения — только для уточнения. В общем, здравствуй переливание из пустого в порожнее.
S>Просто обычно вытесняющая многозадачность — адски дорогая. Поэтому лучше иметь кооперативную многозадачность с примитивами синхронизации.
Ну, стоимость вытесняющей многозадачности уровня ОС в точности равна стоимости пользования примитивами синхронизации уровня ОС.
Потому что дороговизна "традиционной" вытесняющей многозадачности складывается из следующих составляющих:
— смена юзверского контекста на ядерный;
— "тупой шедулер"; тупой, потому что ему недоступны прикладные зависимости м/у потоками, поэтому системный шедуллер каждый божий раз пробегается по ВСЕМ ожидающим примитивам синхронизации в надежде отыскать поток, который уже пора разбудить;
Поэтому-то CRITICAL_SECTION в 99.9% случаев обходится простым InterlockedCompareExchange и InterlockedIncrement, а создаёт ядерный семафор только в случае относительно долгого конфликта на ресурсе (такого, который не успел рассосаться за время spin-wait).
Вернемся к кооперативной асинхронщие.
Если использовать "асинхронные мьютексы", как предлагает Ikemefula, то мы поимеем аналог описанного "тупого шедулера" в полный рост.
Именно поэтому в асинхронщине более принято явно обозначать зависимости м/у задачами, а не "огораживать" ресурсы.
Например, в моём ТЗ относительно "одновременных" записей сообщений в файл, этот файл НЕ НАДО лочить никаким асинхронным мьютексом, надо просто создать выделенный асинхронный процесс записи в файл, т.е. назначить файлу одного "владельца" и создать очередь из объектов-сообщений для записи в файл (или же из их сериализованных в байты тел — на вкус и цвет, как грится), где выделенный процесс будет эту очередь разгребать. Вот так решаются подобные задачи в асинхронщине — через зависимости. Потому что, если очередь пуста, то операция записи в такую очередь породит зависимость
V>>Я предпочитаю озвучить ТЗ, потому что это иначе спекуляции.
S>Какое ТЗ? Речь идёт о целом классе задач, у которых есть характерные общие черты.
Это слишком широкая трактовка. Конкретно мы с Ikemefula спорим о таком феномене, как "гонки". А это вполне конкретное событие, не допускающее столь широкого толкования, как ты попытался.
V>>Потому как иначе получается, что ты тоже умудрился много чего проигнорировать, например, то, что сама операция SetRemoteResource должна быть атомарной, например, для случая, когда тип I представлен значением, которое не записывается в своё хранилище за одну операцию процессора. Как эту атомарность обеспечивать будем в случае жабасрипта?
S>Ну, если у нас есть готовое решение для обеспечения атомарности всего блока, то уж наверное можно его применить и к отдельной операции, нет?
Ну конечно. Тут можно рассуждать сколько угодно далеко, всё дальше от сути спора о "гонках".
Вот это меня и возмутило в твоём примере... бо он настолько абстрактен, что в него можно впихнуть Всю Сущность Мироздания даже в любимом твоём том самом физическом смысле, бо физические процессы именно таковы и есть — происходят во времени и пространстве, да еще и одновременно (параллельно) ). Вот и всё что ты сказал в том посте. ))
V>>Вопрос, нужны ли в случае жабасрипта критические секции, мьютексы и т.д. для этой задачи?
S>Всё зависит от того, есть ли у нас гарантия единственности системного потока, в котором бегут эти логические потоки.
Золотые слова. ))
Об этом уже 3-й год идет спор.
Ну не то, чтобы прям всё время идет... но просто вернулись к одному эпическому спору.
Я однажды ляпнул, что если вся кооперативная многозадачность сидит на одном потоке ОС, типа как в ГУИ или в жабаскрипте, то можно построить код так, чтобы критические секции (и прочие мьютексы/семафоры) были не нужны. Теперь Ikemefula бегает за мной по всем форумам, вызывая на продолжение того спора. Но я уже, если честно, пожалел о том, что поддался на провокации. )) Потому что еще в тот раз было дано объяснение с намного большей степенью подробности, чем сейчас.
S>Потому что если вдруг VM начала использовать N потоков (или если мы тупо запустили 2 инстанса VM на одной машине), то без примитивов мы получаем гарантию мусора.
Да. Вот именно поэтому я уделил приличную часть этого поста
Автор: vdimas
Дата: 12.06.15
рассуждениям о том, что есть "контекст" в жабаскрипте и почему к одному "контексту" обязательно будет только один системный поток в один момент времени... даже если у нас VM многопоточная, как Node.js. Эти гарантии даются языком ECMAScript в неявном и явном виде.Дата: 12.06.15
S>Да, это так. Но вот эту уверенность лучше основывать на чём-то надёжнее, чем "я пока ни разу такого не видел".
Дык, у нас любой код пляшет от неких гарантий. Например, GUI-поток в виндах. Это же тоже гарантия, не? Ты же наверняка поупражнялся достаточно в GUI на клиентских приложениях в своё время? Думаю, ты пользовался знанием о том, где у тебя GUI-поток, а где нет. Более того, даже если в приложении было больше одного GUI-потока, ты всё-равно понимал детали происходящего. Например такие, что к некоторому окошку придут сообщения только из того потока, в котором это окошко создано.
С дотнетом 4.0 и выше идут 3 шедуллера Task-ов в комплекте, и об одном из них так и говорится — вот этот шедуллер основан на GUI-очереди сообщений, со всеми сопутствующими гарантиями. Пользуйтесь, если желаете.
S>Потому что я видел много "многопоточного" кода, который уверенно работал ровно до момента запуска на многоядерной машине.
Ну значит, он не работал и на одноядерной. ))
Потому что прерывания ядра — они такие, беспощадные, сцуко.
Бывают даже посреди операции i++.
Просто вероятность проявления ошибок на одноядерной машине была низка. Низкая вероятность проявления ошибки и отсутствие ошибки — это две большие разницы. Я же веду рассуждения именно об отсутствии ошибки в том, чтобы полагаться на однопоточный доступ к "контексту" жабаскрипта. Это как окно GUI — для каждого отдельного окна GUI гарантируется вызов событий только в одном системном потоке в один момент времени... Даже если этот поток переползет на другое ядро в процессе своей жизни. Точно так же и Node.js, даже если событие к некоему контексту будет обработано потоком из пула потоков, гарантируется, что в один момент времени контекст будет выполнять свой скриптовый код только из одного потока.
S>Ну, для этого придётся специально постараться. Но это будет ожидаемым поведением — важное выделено. В наивной реализации блокируюшего IO заблокируется вообще весь мир, а не только зависимые таски.
Традиционно блокирующее IO используется только в приватных потоках. Поэтому весь мир прекрасно живет даже в случае блокирующих потоков. И я не хочу спорить тут о сценариях, когда это плохо (твои 10тыщ соединений к серваку), бо намного больше сценариев, когда это работает намного-намного эффективней асинхронного ввода-вывода (раза в 2-3). Я как раз по работе этим занят. Кароч, под разные сценарии подходят разные решения.
В любом случае, это всё ушло далеко от первоначального спора. Потому что тому, что ты утверждаешь, у меня нет поля для возражения — только для уточнения. В общем, здравствуй переливание из пустого в порожнее.
S>Просто обычно вытесняющая многозадачность — адски дорогая. Поэтому лучше иметь кооперативную многозадачность с примитивами синхронизации.
Ну, стоимость вытесняющей многозадачности уровня ОС в точности равна стоимости пользования примитивами синхронизации уровня ОС.
Потому что дороговизна "традиционной" вытесняющей многозадачности складывается из следующих составляющих:
— смена юзверского контекста на ядерный;
— "тупой шедулер"; тупой, потому что ему недоступны прикладные зависимости м/у потоками, поэтому системный шедуллер каждый божий раз пробегается по ВСЕМ ожидающим примитивам синхронизации в надежде отыскать поток, который уже пора разбудить;
Поэтому-то CRITICAL_SECTION в 99.9% случаев обходится простым InterlockedCompareExchange и InterlockedIncrement, а создаёт ядерный семафор только в случае относительно долгого конфликта на ресурсе (такого, который не успел рассосаться за время spin-wait).
Вернемся к кооперативной асинхронщие.
Если использовать "асинхронные мьютексы", как предлагает Ikemefula, то мы поимеем аналог описанного "тупого шедулера" в полный рост.
Именно поэтому в асинхронщине более принято явно обозначать зависимости м/у задачами, а не "огораживать" ресурсы.
Например, в моём ТЗ относительно "одновременных" записей сообщений в файл, этот файл НЕ НАДО лочить никаким асинхронным мьютексом, надо просто создать выделенный асинхронный процесс записи в файл, т.е. назначить файлу одного "владельца" и создать очередь из объектов-сообщений для записи в файл (или же из их сериализованных в байты тел — на вкус и цвет, как грится), где выделенный процесс будет эту очередь разгребать. Вот так решаются подобные задачи в асинхронщине — через зависимости. Потому что, если очередь пуста, то операция записи в такую очередь породит зависимость
Автор: netch80
Дата: 16.06.15
(см function onKeyboard(nextChar) в сниппете по ссылке), — считай "разбудит" тот самый выделенный процесс, который пишет в файл. В этом и суть — что не шедуллер каждый раз проверяет "асинхронный мьютекс", (а на деле — вхолостую запускает задачу, а она, после обнаружения холостого запуска ставит сама себя в конец очереди, ы-ы-ы), вместо этого тупого алгоритма мы по-умному должны "разбудить" асинхронный процесс тогда и только тогда, когда ему есть что делать. И я вижу тут замечательнейшую на 100% надежную детерминированность и отсутствие всяких гонок. ))Дата: 16.06.15
Re[23]: Почему Эрланг
Здравствуйте, Sinclair, Вы писали:
V>>Я предпочитаю озвучить ТЗ, потому что это иначе спекуляции.
S>Какое ТЗ? Речь идёт о целом классе задач, у которых есть характерные общие черты.
Это слишком широкая трактовка. Конкретно мы с Ikemefula спорим о таком феномене, как "гонки". А это вполне конкретное событие, не допускающее столь широкого толкования, как ты попытался.
V>>Потому как иначе получается, что ты тоже умудрился много чего проигнорировать, например, то, что сама операция SetRemoteResource должна быть атомарной, например, для случая, когда тип I представлен значением, которое не записывается в своё хранилище за одну операцию процессора. Как эту атомарность обеспечивать будем в случае жабасрипта?
S>Ну, если у нас есть готовое решение для обеспечения атомарности всего блока, то уж наверное можно его применить и к отдельной операции, нет?
Ну конечно. Тут можно рассуждать сколько угодно далеко, всё дальше от сути спора о "гонках".
Вот это меня и возмутило в твоём примере... бо он настолько абстрактен, что в него можно впихнуть Всю Сущность Мироздания даже в любимом твоём том самом физическом смысле, бо физические процессы именно таковы и есть — происходят во времени и пространстве, да еще и одновременно (параллельно) ). Вот и всё что ты сказал в том посте. ))
V>>Вопрос, нужны ли в случае жабасрипта критические секции, мьютексы и т.д. для этой задачи?
S>Всё зависит от того, есть ли у нас гарантия единственности системного потока, в котором бегут эти логические потоки.
Золотые слова. ))
Об этом уже 3-й год идет спор.
Ну не то, чтобы прям всё время идет... но просто вернулись к одному эпическому спору.
Я однажды ляпнул, что если вся кооперативная многозадачность сидит на одном потоке ОС, типа как в ГУИ или в жабаскрипте, то можно построить код так, чтобы критические секции (и прочие мьютексы/семафоры) были не нужны. Теперь Ikemefula бегает за мной по всем форумам, вызывая на продолжение того спора. Но я уже, если честно, пожалел о том, что поддался на провокации. )) Потому что еще в тот раз было дано объяснение с намного большей степенью подробности, чем сейчас.
S>Потому что если вдруг VM начала использовать N потоков (или если мы тупо запустили 2 инстанса VM на одной машине), то без примитивов мы получаем гарантию мусора.
Да. Вот именно поэтому я уделил приличную часть этого поста
S>Да, это так. Но вот эту уверенность лучше основывать на чём-то надёжнее, чем "я пока ни разу такого не видел".
Дык, у нас любой код пляшет от неких гарантий. Например, GUI-поток в виндах. Это же тоже гарантия, не? Ты же наверняка поупражнялся достаточно в GUI на клиентских приложениях в своё время? Думаю, ты пользовался знанием о том, где у тебя GUI-поток, а где нет. Более того, даже если в приложении было больше одного GUI-потока, ты всё-равно понимал детали происходящего. Например такие, что к некоторому окошку придут сообщения только из того потока, в котором это окошко создано.
С дотнетом 4.0 и выше идут 3 шедуллера Task-ов в комплекте, и об одном из них так и говорится — вот этот шедуллер основан на GUI-очереди сообщений, со всеми сопутствующими гарантиями. Пользуйтесь, если желаете.
S>Потому что я видел много "многопоточного" кода, который уверенно работал ровно до момента запуска на многоядерной машине.
Ну значит, он не работал и на одноядерной. ))
Потому что прерывания ядра — они такие, беспощадные, сцуко.
Бывают даже посреди операции i++.
Просто вероятность проявления ошибок на одноядерной машине была низка. Низкая вероятность проявления ошибки и отсутствие ошибки — это две большие разницы. Я же веду рассуждения именно об отсутствии ошибки в том, чтобы полагаться на однопоточный доступ к "контексту" жабаскрипта. Это как окно GUI — для каждого отдельного окна GUI гарантируется вызов событий только в одном системном потоке в один момент времени... Даже если этот поток переползет на другое ядро в процессе своей жизни. Точно так же и Node.js, даже если событие к некоему контексту будет обработано потоком из пула потоков, гарантируется, что в один момент времени контекст будет выполнять свой скриптовый код только из одного потока.
S>Ну, для этого придётся специально постараться. Но это будет ожидаемым поведением — важное выделено. В наивной реализации блокируюшего IO заблокируется вообще весь мир, а не только зависимые таски.
Традиционно блокирующее IO используется только в приватных потоках. Поэтому весь мир прекрасно живет даже в случае блокирующих потоков. И я не хочу спорить тут о сценариях, когда это плохо (твои 10тыщ соединений к серваку), бо намного больше сценариев, когда это работает намного-намного эффективней асинхронного ввода-вывода (раза в 2-3). Я как раз по работе этим занят. Кароч, под разные сценарии подходят разные решения.
В любом случае, это всё ушло далеко от первоначального спора. Потому что тому, что ты утверждаешь, у меня нет поля для возражения — только для уточнения. В общем, здравствуй переливание из пустого в порожнее.
S>Просто обычно вытесняющая многозадачность — адски дорогая. Поэтому лучше иметь кооперативную многозадачность с примитивами синхронизации.
Ну, стоимость вытесняющей многозадачности уровня ОС в точности равна стоимости пользования примитивами синхронизации уровня ОС.
Потому что дороговизна "традиционной" вытесняющей многозадачности складывается из следующих составляющих:
— смена юзверского контекста на ядерный;
— "тупой шедулер"; тупой, потому что ему недоступны прикладные зависимости м/у потоками, поэтому системный шедуллер каждый божий раз пробегается по ВСЕМ ожидающим примитивам синхронизации в надежде отыскать поток, который уже пора разбудить;
Поэтому-то CRITICAL_SECTION в 99.9% случаев обходится простым InterlockedCompareExchange и InterlockedIncrement, а создаёт ядерный семафор только в случае относительно долгого конфликта на ресурсе (такого, который не успел рассосаться за время spin-wait).
Вернемся к кооперативной асинхронщие.
Если использовать "асинхронные мьютексы", как предлагает Ikemefula, то мы поимеем аналог описанного "тупого шедулера" в полный рост.
Именно поэтому в асинхронщине более принято явно обозначать зависимости м/у задачами, а не "огораживать" ресурсы.
Например, в моём ТЗ относительно "одновременных" записей сообщений в файл, этот файл НЕ НАДО лочить никаким асинхронным мьютексом, надо просто создать выделенный асинхронный процесс записи в файл, т.е. назначить файлу одного "владельца" и создать очередь из объектов-сообщений для записи в файл (или же из их сериализованных в байты тел — на вкус и цвет, как грится), где выделенный процесс будет эту очередь разгребать. Вот так решаются подобные задачи в асинхронщине — через зависимости. Потому что, если очередь пуста, то операция записи в такую очередь породит зависимость
V>>Я предпочитаю озвучить ТЗ, потому что это иначе спекуляции.
S>Какое ТЗ? Речь идёт о целом классе задач, у которых есть характерные общие черты.
Это слишком широкая трактовка. Конкретно мы с Ikemefula спорим о таком феномене, как "гонки". А это вполне конкретное событие, не допускающее столь широкого толкования, как ты попытался.
V>>Потому как иначе получается, что ты тоже умудрился много чего проигнорировать, например, то, что сама операция SetRemoteResource должна быть атомарной, например, для случая, когда тип I представлен значением, которое не записывается в своё хранилище за одну операцию процессора. Как эту атомарность обеспечивать будем в случае жабасрипта?
S>Ну, если у нас есть готовое решение для обеспечения атомарности всего блока, то уж наверное можно его применить и к отдельной операции, нет?
Ну конечно. Тут можно рассуждать сколько угодно далеко, всё дальше от сути спора о "гонках".
Вот это меня и возмутило в твоём примере... бо он настолько абстрактен, что в него можно впихнуть Всю Сущность Мироздания даже в любимом твоём том самом физическом смысле, бо физические процессы именно таковы и есть — происходят во времени и пространстве, да еще и одновременно (параллельно) ). Вот и всё что ты сказал в том посте. ))
V>>Вопрос, нужны ли в случае жабасрипта критические секции, мьютексы и т.д. для этой задачи?
S>Всё зависит от того, есть ли у нас гарантия единственности системного потока, в котором бегут эти логические потоки.
Золотые слова. ))
Об этом уже 3-й год идет спор.
Ну не то, чтобы прям всё время идет... но просто вернулись к одному эпическому спору.
Я однажды ляпнул, что если вся кооперативная многозадачность сидит на одном потоке ОС, типа как в ГУИ или в жабаскрипте, то можно построить код так, чтобы критические секции (и прочие мьютексы/семафоры) были не нужны. Теперь Ikemefula бегает за мной по всем форумам, вызывая на продолжение того спора. Но я уже, если честно, пожалел о том, что поддался на провокации. )) Потому что еще в тот раз было дано объяснение с намного большей степенью подробности, чем сейчас.
S>Потому что если вдруг VM начала использовать N потоков (или если мы тупо запустили 2 инстанса VM на одной машине), то без примитивов мы получаем гарантию мусора.
Да. Вот именно поэтому я уделил приличную часть этого поста
Автор: vdimas
Дата: 12.06.15
рассуждениям о том, что есть "контекст" в жабаскрипте и почему к одному "контексту" обязательно будет только один системный поток в один момент времени... даже если у нас VM многопоточная, как Node.js. Эти гарантии даются языком ECMAScript в неявном и явном виде.Дата: 12.06.15
S>Да, это так. Но вот эту уверенность лучше основывать на чём-то надёжнее, чем "я пока ни разу такого не видел".
Дык, у нас любой код пляшет от неких гарантий. Например, GUI-поток в виндах. Это же тоже гарантия, не? Ты же наверняка поупражнялся достаточно в GUI на клиентских приложениях в своё время? Думаю, ты пользовался знанием о том, где у тебя GUI-поток, а где нет. Более того, даже если в приложении было больше одного GUI-потока, ты всё-равно понимал детали происходящего. Например такие, что к некоторому окошку придут сообщения только из того потока, в котором это окошко создано.
С дотнетом 4.0 и выше идут 3 шедуллера Task-ов в комплекте, и об одном из них так и говорится — вот этот шедуллер основан на GUI-очереди сообщений, со всеми сопутствующими гарантиями. Пользуйтесь, если желаете.
S>Потому что я видел много "многопоточного" кода, который уверенно работал ровно до момента запуска на многоядерной машине.
Ну значит, он не работал и на одноядерной. ))
Потому что прерывания ядра — они такие, беспощадные, сцуко.
Бывают даже посреди операции i++.
Просто вероятность проявления ошибок на одноядерной машине была низка. Низкая вероятность проявления ошибки и отсутствие ошибки — это две большие разницы. Я же веду рассуждения именно об отсутствии ошибки в том, чтобы полагаться на однопоточный доступ к "контексту" жабаскрипта. Это как окно GUI — для каждого отдельного окна GUI гарантируется вызов событий только в одном системном потоке в один момент времени... Даже если этот поток переползет на другое ядро в процессе своей жизни. Точно так же и Node.js, даже если событие к некоему контексту будет обработано потоком из пула потоков, гарантируется, что в один момент времени контекст будет выполнять свой скриптовый код только из одного потока.
S>Ну, для этого придётся специально постараться. Но это будет ожидаемым поведением — важное выделено. В наивной реализации блокируюшего IO заблокируется вообще весь мир, а не только зависимые таски.
Традиционно блокирующее IO используется только в приватных потоках. Поэтому весь мир прекрасно живет даже в случае блокирующих потоков. И я не хочу спорить тут о сценариях, когда это плохо (твои 10тыщ соединений к серваку), бо намного больше сценариев, когда это работает намного-намного эффективней асинхронного ввода-вывода (раза в 2-3). Я как раз по работе этим занят. Кароч, под разные сценарии подходят разные решения.
В любом случае, это всё ушло далеко от первоначального спора. Потому что тому, что ты утверждаешь, у меня нет поля для возражения — только для уточнения. В общем, здравствуй переливание из пустого в порожнее.
S>Просто обычно вытесняющая многозадачность — адски дорогая. Поэтому лучше иметь кооперативную многозадачность с примитивами синхронизации.
Ну, стоимость вытесняющей многозадачности уровня ОС в точности равна стоимости пользования примитивами синхронизации уровня ОС.
Потому что дороговизна "традиционной" вытесняющей многозадачности складывается из следующих составляющих:
— смена юзверского контекста на ядерный;
— "тупой шедулер"; тупой, потому что ему недоступны прикладные зависимости м/у потоками, поэтому системный шедуллер каждый божий раз пробегается по ВСЕМ ожидающим примитивам синхронизации в надежде отыскать поток, который уже пора разбудить;
Поэтому-то CRITICAL_SECTION в 99.9% случаев обходится простым InterlockedCompareExchange и InterlockedIncrement, а создаёт ядерный семафор только в случае относительно долгого конфликта на ресурсе (такого, который не успел рассосаться за время spin-wait).
Вернемся к кооперативной асинхронщие.
Если использовать "асинхронные мьютексы", как предлагает Ikemefula, то мы поимеем аналог описанного "тупого шедулера" в полный рост.
Именно поэтому в асинхронщине более принято явно обозначать зависимости м/у задачами, а не "огораживать" ресурсы.
Например, в моём ТЗ относительно "одновременных" записей сообщений в файл, этот файл НЕ НАДО лочить никаким асинхронным мьютексом, надо просто создать выделенный асинхронный процесс записи в файл, т.е. назначить файлу одного "владельца" и создать очередь из объектов-сообщений для записи в файл (или же из их сериализованных в байты тел — на вкус и цвет, как грится), где выделенный процесс будет эту очередь разгребать. Вот так решаются подобные задачи в асинхронщине — через зависимости. Потому что, если очередь пуста, то операция записи в такую очередь породит зависимость
Автор: vdimas
Дата: 13.06.15
(см function onKeyboard(nextChar) в сниппете по ссылке), — считай "разбудит" тот самый выделенный процесс, который пишет в файл. В этом и суть — что не шедуллер каждый раз проверяет "асинхронный мьютекс", (а на деле — вхолостую запускает задачу, а она, после обнаружения холостого запуска ставит сама себя в конец очереди и так бесконечно по кругу), вместо этого тупого алгоритма мы по-умному должны "разбудить" асинхронный процесс тогда и только тогда, когда ему есть что делать. И я вижу тут замечательнейшую на 100% надежную детерминированность и отсутствие всяких гонок. Дата: 13.06.15