На прошлой неделе я работал над многопоточной реализацией JavaScript. У меня есть доказательство концепции, сделанной на C ++ с использованием JavaScriptCore и boost.
Архитектура проста: когда среда выполнения завершает оценку основного скрипта, который он запускает и присоединяется к пулу потоков, который начинает выбирать задачи из общей очереди приоритетов, если две задачи одновременно пытаются получить доступ к переменной, она помечается как атомарная и борется за доступ ,
Проблема в том, что когда я показываю этот дизайн программисту на JavaScript, я получаю крайне негативную обратную связь и не знаю почему. Даже в частном порядке они все говорят, что JavaScript должен быть однопоточным, что существующие библиотеки придется переписать, и что гремлины появятся и съедят каждое живое существо, если я продолжу работать над этим.
У меня изначально была собственная реализация сопрограмм (использующая контексты повышения), но мне пришлось отказаться от нее (JavaScriptCore педантичен в отношении стека), и я не хотел рисковать их гневом, поэтому решил не упоминать об этом.
Как вы думаете? Должен ли JavaScript быть однопоточным, и его следует оставить в покое? Почему все против идеи одновременного выполнения JavaScript?
Изменить: Сейчас проект находится на GitHub , экспериментируйте с ним сами и дайте мне знать, что вы думаете.
Ниже приведено изображение обещаний, выполняемых на всех ядрах процессора параллельно без конфликтов:
источник
Ответы:
1) Многопоточность чрезвычайно сложна, и, к сожалению, то, как вы представили эту идею, подразумевает, что вы сильно недооцениваете ее сложность.
На данный момент кажется, что вы просто «добавляете темы» к языку и беспокоитесь о том, как сделать его правильным и производительным позже. В частности:
Добавление потоков в Javascript без «решения проблемы синхронизации» было бы похоже на добавление целых чисел в Javascript без «решения проблемы добавления». Это настолько фундаментально для природы проблемы, что нет смысла даже обсуждать, стоит ли добавлять многопоточность без конкретного решения, независимо от того, насколько сильно мы этого хотим.
Кроме того, превращение всех переменных в атомарные - это то, что может заставить многопоточные программы работать хуже, чем их однопоточные аналоги, что делает еще более важным на самом деле тестировать производительность на более реалистичных программах и посмотреть, получаете ли вы что-нибудь или нет.
Мне также не ясно, пытаетесь ли вы скрыть потоки от программиста node.js или планируете в какой-то момент разоблачить их, эффективно создавая новый диалект Javascript для многопоточного программирования. Оба варианта потенциально интересны, но, похоже, вы еще не определились, к какому из них вы стремитесь.
Итак, на данный момент вы просите программистов подумать о переходе от однопоточной среды к совершенно новой многопоточной среде, у которой нет решения проблемы синхронизации, нет доказательств того, что она повышает реальную производительность, и, по-видимому, нет плана решения этих проблем.
Наверное, поэтому люди не воспринимают тебя всерьез.
2) Простота и надежность единого цикла обработки событий является огромным преимуществом.
Программисты Javascript знают, что язык Javascript "безопасен" от условий гонки и других чрезвычайно коварных ошибок, которые мешают всему действительно многопоточному программированию. Тот факт, что им нужны веские аргументы, чтобы убедить их отказаться от того, что безопасность не делает их замкнутыми, делает их ответственными.
Если вы не можете каким-то образом сохранить эту безопасность, любому, кто захочет переключиться на многопоточный node.js, вероятно, было бы лучше перейти на язык наподобие Go, который изначально разрабатывался для многопоточных приложений.
3) Javascript уже поддерживает «фоновые потоки» (WebWorkers) и асинхронное программирование без непосредственного предоставления управления потоками программисту.
Эти функции уже решают многие распространенные случаи использования, которые затрагивают программистов Javascript в реальном мире, не отказываясь от безопасности одного цикла обработки событий.
Есть ли у вас какие-то конкретные примеры использования, которые эти функции не решают, и для которых программисты Javascript хотят найти решение? Если это так, было бы неплохо представить ваш многопоточный файл node.js в контексте этого конкретного варианта использования.
PS Что бы убедило меня попробовать перейти на многопоточную реализацию node.js?
Напишите в Javascript / node.js нетривиальную программу, которая, по вашему мнению, выиграет от подлинной многопоточности. Выполните тесты производительности в этом примере программы на обычном узле и многопоточном узле. Покажите мне, что ваша версия в значительной степени повышает производительность, скорость отклика и использование нескольких ядер без каких-либо ошибок или нестабильности.
Как только вы это сделаете, я думаю, вы увидите, что люди гораздо больше заинтересованы в этой идее.
источник
Просто угадать здесь, чтобы продемонстрировать проблему в вашем подходе. Я не могу проверить это с реальной реализацией, так как нигде нет ссылки ...
Я бы сказал, что это потому, что инварианты не всегда выражаются значением одной переменной, и «одной переменной» недостаточно для того, чтобы быть областью блокировки в общем случае. Например, представьте, что у нас есть инвариант
a+b = 0
(баланс банка с двумя счетами). Две нижеприведенные функции гарантируют, что инвариант всегда сохраняется в конце каждой функции (единица выполнения в однопоточном JS).Теперь в вашем многопоточном мире, что происходит , когда два потока выполнения ,
withdraw
иdeposit
в то же время? Спасибо, Мерфи ...(Возможно, у вас есть код, который обрабатывает + = и - = специально, но это не поможет. В какой-то момент у вас будет локальное состояние в функции, и без возможности «заблокировать» две переменные одновременно ваш инвариант будет быть нарушенным.)
РЕДАКТИРОВАТЬ: Если ваш код семантически эквивалентен коду Go на https://gist.github.com/thriqon/f94c10a45b7e0bf656781b0f4a07292a , мой комментарий точен ;-)
источник
Примерно десять лет назад Брендан Эйх (изобретатель JavaScript) написал эссе под названием Threads Suck , которое определенно является одним из немногих канонических документов мифологии дизайна JavaScript.
Правильно ли это - другой вопрос, но я думаю, что это сильно повлияло на то, как сообщество JavaScript думает о параллелизме.
источник
Атомарный доступ не приводит к поточно-ориентированному поведению.
Один из примеров - когда глобальная структура данных должна быть недействительной во время обновления, такого как перефразирование хэш-карты (например, при добавлении свойства к объекту) или сортировка глобального массива. В течение этого времени вы не можете разрешить другим потокам доступ к переменной. Это в основном означает, что вам нужно обнаружить все циклы чтения-обновления-записи и заблокировать их. Если обновление не тривиально, это приведет к остановке проблемной территории.
Javascript был однопоточным и изолированным с самого начала, и весь код написан с учетом этих предположений.
Это имеет большое преимущество в отношении изолированных контекстов и позволяет двум отдельным контекстам работать в разных потоках. Я также имею в виду, что людям, пишущим javascript, не нужно знать, как справляться с условиями гонки и различными другими многопоточными питалами.
источник
Ваш подход собирается значительно улучшить производительность?
Сомнительно. Вам действительно нужно это доказать.
Ваш подход облегчит / ускорит написание кода?
Определенно нет, многопоточный код во много раз сложнее понять, чем однопоточный код.
Ваш подход будет более надежным?
Тупики, условия гонки и т. Д. - это кошмар, который нужно исправить.
источник
Ваша реализация заключается не только во введении параллелизма, но и во введении определенного способа реализации параллелизма, то есть параллелизма с помощью общего изменяемого состояния. В течение истории люди использовали этот тип параллелизма, и это приводило ко многим видам проблем. Конечно, вы можете создавать простые программы, которые прекрасно работают с использованием совместно изменяемого состояния изменяемого состояния, но реальный тест любого механизма не в том, что он может сделать, а в том, что он может масштабироваться по мере усложнения программы и добавления в программу все новых и новых функций. Помните, что программное обеспечение - это не статичная вещь, которую вы создаете один раз и делаете с ней, скорее, она продолжает развиваться со временем, и если какой-либо механизм или концепция могут это сделать »
Вы можете посмотреть на другие модели параллелизма (например, передача сообщений), чтобы выяснить, какие преимущества предоставляют эти модели.
источник
Это необходимо Отсутствие низкоуровневого механизма параллелизма в узле js ограничивает его применение в таких областях, как математика, биоинформатика и т. Д. Кроме того, параллелизм с потоками не обязательно конфликтует с моделью параллелизма по умолчанию, используемой в узле. Существует хорошо известная семантика потоков в среде с основным циклом событий, такой как пользовательские среды (и nodejs), и они определенно слишком сложны для большинства ситуаций, в которых они все еще используются.
Конечно, ваше обычное веб-приложение не будет требовать потоков, но попробуйте сделать что-нибудь немного менее традиционное, и отсутствие примитива параллелизма с низким уровнем звука быстро унесет вас к чему-то еще, что предлагает это.
источник
Я действительно верю, что это потому, что это другая и мощная идея. Вы идете против систем верований. Материал становится принятым или популярным через сеть влияет не на основе заслуг. Также никто не хочет адаптироваться к новому стеку. Люди автоматически отвергают вещи, которые слишком разные.
Если вы можете придумать способ превратить его в обычный модуль npm, что звучит маловероятно, то вы можете заставить некоторых людей использовать его.
источник