Які недоліки зробити багатопотокову реалізацію JavaScript? [зачинено]


51

Я працював над багатопотоковою реалізацією JavaScript протягом минулого тижня. У мене є доказ концепції, зробленої на C ++ за допомогою JavaScriptCore та boost.

Архітектура проста: коли час закінчення оцінювання основного сценарію він запускається та приєднується до пулу потоків, який починає вибирати завдання із спільної черги пріоритетів, якщо дві задачі намагаються отримати доступ до змінної одночасно, вона позначається атомною, і вони претендують на доступ .

Працює багатопотокове виконання node.js

Проблема полягає в тому, що коли я показую цей дизайн програмісту JavaScript, я отримую вкрай негативні відгуки, і я не знаю, чому. Навіть у приватному режимі всі вони кажуть, що JavaScript призначений для однопотокової передачі, що існуючі бібліотеки повинні бути переписані, і що гремліни будуть нереститися і їсти кожну живу істоту, якщо я продовжуватиму працювати над цим.

Спочатку я мав місце в реальному застосуванні кореневої програми (використовуючи прискорений контекст), але мені довелося її скинути (JavaScriptCore педантично стосується стека), і я не хотів ризикувати їх гнівом, тому вирішив проти згадки про це.

Що ти думаєш? Чи призначений JavaScript бути однопоточним і чи його слід залишати в спокої? Чому всі проти ідеї одночасного виконання JavaScript?

Редагувати: Проект зараз на GitHub , експериментуйте з ним самостійно і дайте мені знати, що ви думаєте.

Далі представлена ​​картина обіцянок, що виконуються на всіх ядрах процесора паралельно без суперечок:

Виконання обіцянок одночасно.


7
Це здається питанням, що викликає самовпевненість. Ви запитували людей, яким, очевидно, не сподобалася ваша ідея, чому вони думають, що це буде клопітно?
5gon12eder

26
Додавання ниток до чогось, що не має бути багатопоточним, як перетворення дороги однієї смуги на швидкісну дорогу, не надаючи водієві редакції. Він буде працювати досить добре більшу частину часу, поки люди не почнуть випадково врізатися. За допомогою багатопотокового читання у вас або виникають тонкі помилки в часі, які ви не можете відтворити, або поведінка нестабільна більшість часу. Ви повинні мати на увазі це. Вам потрібна синхронізація потоку. Просто створення змінних атомних не виключає перегонів.
mgw854

2
Як ви плануєте обробляти багатопотоковий доступ до спільного стану? "Позначений як атомний і претендує на доступ" не пояснює, як ви вважаєте, що це справді спрацювало б. Я б здогадався, що негативне ставлення до цієї ідеї полягає в тому, що люди не мають уявлення про те, як ти насправді змусив цю роботу. Або, якщо ви покладаєте всю тягар на розробника, як у Java чи C ++, щоб використовувати належні мютекси та подібні, то люди, напевно, думають, чому вони хочуть цього ризику ускладнення та програмування у вільному від нього середовищі.
jfriend00

17
Оскільки автоматичне узгодження випадкового стану між потоками вважається майже неможливою проблемою, тому у вас немає впевненості, що ви можете запропонувати все, що робить це автоматично. І якщо ви просто збираєтесь повернути тягар на розробника, як Java або C ++, тоді більшість програмістів node.js не хочуть цього тягаря - їм подобається, що node.js не повинен з цим боротися здебільшого. Якщо ви хочете більш симпатичного вуха, вам доведеться пояснити / показати, як і що ви запропонували в цьому плані і чому це було б добре і корисно.
jfriend00

3
Продовжуйте роботу. Я розглядаю мови без мультиварки як іграшкові мови. Я думаю, що більшість розробників JavaScript працює з браузером, який має однопоточну модель.
Хлоя

Відповіді:


70

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, яку, на вашу думку, виграєте від справжньої багатопотокової роботи. Зробіть тести на ефективність для цієї зразкової програми у звичайному вузлі та вашому багатопотоковому вузлі. Покажіть мені, що ваша версія значно покращує продуктивність, швидкість реагування та використання декількох ядер, не вводячи жодних помилок чи нестабільності.

Після того, як ви це зробите, я думаю, ви побачите людей набагато більше зацікавлених у цій ідеї.


1
1) Гаразд, я визнаю, що я вже певний час відкладаю питання синхронізації. Коли я кажу, що "дві задачі будуть суперечити", це не моя конструкція, це в основному спостереження: dl.dropboxusercontent.com/u/27714141/… - я не впевнений, який тип чаклунства JavaScriptCore виконує тут, але не повинен " t ця струна не зіпсується, якщо вона по суті не була атомною? 2) Я категорично не згоден. Це причина, на яку JS розглядається як іграшкова мова. 3) ES6 обіцянки були б набагато ефективнішими, якщо їх реалізувати за допомогою планувальника пулових потоків.
voodooattack

13
@voodooattack "Це причина, на яку JS розглядається як іграшкова мова". Ні, це причина, що ви вважаєте це іграшкою мовою. Мільйони людей користуються JS щодня і цілком задоволені нею, недоліками і всім. Переконайтеся, що ви вирішуєте проблему, яку насправді має достатньо інших людей, що не краще вирішується просто зміною мов.
Кріс Хейс

@ChrisHayes Питання в тому, чому миритися зі своїми недоліками, коли я можу їх виправити? Чи поліпшить паралельність як функцію поліпшення JavaScript?
voodooattack

1
@voodooattack Це питання. Чи покращить паралельність як функцію Javascript? Якщо ви зможете отримати відповідь громади на те, що це не «ні», то, можливо, ви щось вирішили. Однак, здається, ніби цикл подій та власне делегування Node в робочих потоках для блокування подій достатньо для більшості того, що потрібно зробити людям. Я думаю, що якщо людям дійсно потрібен потоковий Javascript, вони використовуватимуть Javascript працівників. Якщо ви можете знайти спосіб змусити працівників працювати з першокласними функціями замість JS-файлів, однак .... тоді ви дійсно можете щось вдіяти.
lunchmeat317

7
@voodooattack Люди, які називають JavaScript іграшкою мовою, не знають, про що говорять. Це мова для всього? Звичайно, ні, але відкидати це так, безумовно, є помилкою. Якщо ви хочете розвіяти уявлення про те, що JS є іграшкою мовою, то зробіть у ній нетривіальну, виробничу заявку або вкажіть на існуючу. Просто додавання одночасності не змінить розум людей.
jpmc26

16

Тут просто здогадуються, щоб продемонструвати проблему у вашому підході. Я не можу перевірити це на реальній реалізації, оскільки ніде немає посилання ...

Я б сказав, що це тому, що інваріанти не завжди виражаються значенням однієї змінної, а "однієї змінної" недостатньо, щоб бути загальним випадком блокування. Наприклад, уявіть, що ми маємо інваріант a+b = 0(баланс банку з двома рахунками). Дві функції нижче забезпечують, що інваріант завжди утримується в кінці кожної функції (одиниця виконання в однопотоковому JS).

function withdraw(v) {
  a -= v;
  b += v;
}
function deposit(v) {
  b -= v;
  a += v;
}

Тепер у вашому багатопотоковому світі, що відбувається , коли два потоки виконання , withdrawі depositв той же час? Дякую, Мерфі ...

(У вас може бути код, який розглядає + = і - = спеціально, але це не допомагає. У якийсь момент у вас буде функція локального стану, і жодний спосіб одночасно "заблокувати" дві змінні ваш інваріант не буде бути порушеним.)


EDIT: Якщо ваш код семантично еквівалентний коду Go за адресою https://gist.github.com/thriqon/f94c10a45b7e0bf656781b0f4a07292a , мій коментар точний ;-)


Цей коментар не має значення, але філософи здатні зафіксувати кілька об'єктів, але вони голодують, оскільки вони фіксують їх у непослідовному порядку.
Дітріх Епп

3
@voodooattack "Я щойно перевірив ..." Ви ніколи не стикалися з неузгодженим порядком виконання з плануванням потоків? Він змінюється від запуску до запуску, від машини до машини. Сидіти та виконувати єдиний тест (а то й сотню тестів!) Без визначення механізму того, як плануються операції, марно.
jpmc26

4
@voodooattack Проблема полягає в тому, що просто перевірити паралельність не корисно. Вам потрібно вміти довести, що інваріант буде дотримуватися, інакше механізму не можна довіряти у виробництві.
сапі

1
Але ви не надали користувачеві жодних інструментів, щоб "відповідально користуватися системою", оскільки немає абсолютно ніякого механізму блокування. Створення всього атомного дає ілюзію безпеки потоку (і ви приймаєте на себе ефективність того, що є атомним, навіть коли вам не потрібен атомний доступ), але це насправді не вирішує більшості проблем з одночасністю, як це дає триксон. Для іншого прикладу спробуйте ітерацію над масивом на одному потоці, тоді як інший потік додає або видаляє елементи з масиву. З цього питання, чому ви вважаєте, що реалізація Array в двигуні безпечна навіть для потоків?
Зак Ліптон

2
@voodooattack Отже, якщо користувачі можуть використовувати ваші потоки лише для функцій, що не мають спільних даних або побічних ефектів (і краще не використовувати їх для чого-небудь іншого, оскільки, як ми вже бачили тут, немає способу забезпечити безпеку потоку), Тоді яке значення ви надаєте для Web Workers (або однієї з багатьох бібліотек, які надають більш корисний API навколо Web Workers)? А веб-робітники набагато безпечніші, оскільки вони унеможливлюють використання користувачем системи "безвідповідально".
Зак Ліптон

15

Десятиліття тому Брендан Ейх (винахідник JavaScript) написав есе під назвою Threads Suck , що, безумовно, є одним з небагатьох канонічних документів міфології дизайну JavaScript.

Чи правильно це - інше питання, але я думаю, що це мало великий вплив на те, як спільнота JavaScript думає про одночасність.


31
Остання людина, від якої я б взяв поради, - це Брендан Ейх. Вся його кар'єра заснована на створенні JavaScript, що так погано, що у нас є маса інструментів, створених для того, щоб спробувати обійти його вроджену лайно. Подумайте, скільки годин розробника було витрачено в світі через нього.
Філ Райт

12
Хоча я розумію, чому ви взагалі відкинете його думку і навіть нехтуєте JavaScript, я не розумію, як ваша перспектива дозволила б нехтувати його досвідом у цій галузі.
Біллі Крейвенс

4
@BillyCravens ха-ха, навіть канонічна книга про Javascript: "Javascript the good parts " від Крокфорда дає гру в назві. Так само ставитесь до поглядів
Ейха

13
@PhilWright: Першою його реалізацією Javascript був варіант Lisp. Що мені заслуговує величезної поваги. Рішення його начальника змусити його замінити синтаксис Ліспа на синтаксис подібний С, не є його виною. Javascript в його основі - все ще час Lisp.
slebetman

7
@PhilWright: Ви не повинні звинувачувати Айха в лукавстві мови. Це помилки в ранніх впровадженнях та необхідність зворотної сумісності для веб-мови, яка не дозволила JS дозрівати. Основні поняття все ще утворюють чудову мову.
Бергі

8

Атомний доступ не перетворюється на безпечну поведінку.

Одним із прикладів є те, що глобальна структура даних повинна бути недійсною під час оновлення, як, наприклад, повторне переміщення хешмапу (наприклад, додавання властивості до об'єкта) або сортування глобального масиву. За цей час ви не можете дозволити жодному іншому потоку отримати доступ до змінної. Це в основному означає, що вам потрібно виявити всі цикли читання-оновлення-запису та заблокувати це. Якщо оновлення нетривіальне, це перетвориться на зупинку проблемної території.

Javascript з однієї нитки був з ниткими та пісочницями, і весь код записується з урахуванням цих припущень.

Це має велику перевагу щодо ізольованих контекстів і дозволу 2 окремим контекстам працювати в різних потоках. Я також означає, що людям, які пишуть javascript, не потрібно знати, як боротися з умовами перегонів та різними іншими підводними клопами.


Ось чому я вважаю, що API планувальника повинен бути більше на передовій стороні і використовувати його внутрішньо для обіцянок та функцій, які не мають побічних ефектів.
voodooattack

6

Чи буде ваш підхід значно покращити ефективність роботи?

Сумнівні. Вам справді потрібно це довести.

Чи буде ваш підхід полегшити / швидше писати код?

Безумовно, ні, багатопотоковий код набагато складніше отримати правильно, ніж однопотоковий код.

Чи буде ваш підхід більш надійним?

Тупики, умови перегонів тощо - це кошмар, який потрібно виправити.


2
Спробуйте створити raytracer за допомогою node.js, тепер спробуйте ще раз з потоками. Багатопроцесорність - це не все.
voodooattack

8
@voodooattack, ніхто з належним розумом не запише промінь-прослідковувач, використовуючи javascript, з нанизуванням або без нього, оскільки це порівняно простий, але обчислювальний алгоритм, який краще писати повністю складеною мовою, бажано, з підтримкою SIMD . Для проблем, для яких використовується JavaScript, багатопроцесорний процес більш ніж достатній.
Ян Худек

@JanHudec: Хех, JS збирається отримати підтримку SIMD а :-) hacks.mozilla.org/2014/10/introducing-simd-js
Берги

2
@voodooattack Якщо ви їх не знаєте, подивіться на SharedArrayBuffers . JavaScript отримує більше конструкцій одночасності, але їх додають надзвичайно обережно, звертаючись до конкретних больових точок, намагаючись мінімізувати прийняття поганих дизайнерських рішень, з якими нам доведеться жити роками.
ВІДНОВЛЕННЯ MONICA -Березень Банки

2

Ваша реалізація стосується не лише введення паралельності, а, скоріше, про введення конкретного способу реалізації паралельності, тобто паралельності за допомогою спільного стану, що змінюється. Протягом історії люди використовували цей тип одночасності, і це призвело до багатьох видів проблем. Звичайно, ви можете створити прості програми, які чудово працюють із використанням спільної сумісної кон'юнктури, але справжній тест будь-якого механізму - це не те, що він може зробити, але може масштабувати, коли програма набуває складніші можливості, і все більше і більше функцій додаються до програми. Пам'ятайте, що програмне забезпечення - це не статична річ, яку ви будуєте один раз, і робите з нею, скоріше вона розвивається з часом, і якщо якийсь механізм чи концепція може "

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


1
Я думаю, що обіцянки ES6 виграють від моделі моєї реалізації, оскільки вони не претендують на доступ.
voodooattack

Погляньте на специфікацію WebWorkers. Є пакети npm, які забезпечують їх реалізацію, але ви можете реалізувати їх як ядро ​​вашого двигуна, а не як пакет
Ankur

JavaScriptCore (реалізація веб-програм JS, який я використовую) вже реалізує їх, це лише прапор компіляції.
voodooattack

Гаразд. WebWorkers узгоджуються з передачею повідомлень. Ви можете спробувати ваш приклад Raytracer з ними та порівняти його із підходом до змінного стану.
Анкур

4
Передача повідомлень завжди реалізується поверх стану, що змінюється, а це означає, що це буде повільніше. Я не бачу вашої суті тут. : - /
voodooattack

1

Це потрібно. Відсутність механізму сумісності низького рівня в вузлі js обмежує його застосування в таких галузях, як математика та біоінформатика тощо. Крім того, паралельність з потоками не обов'язково суперечить моделі дефіциту за замовчуванням, що використовується у вузлі. Існує добре відома семантика для нанизування різьби в середовищі з основним циклом подій, таких як фреймворки ui (та nodejs), і вони, безумовно, надмірно складні для більшості ситуацій, у яких все ще є дійсне використання.

Звичайно, для вашого середнього веб-додатка не потрібні теми, але спробуйте робити щось трохи менш звичайне, а відсутність звуку примітиву з низьким рівнем швидкості швидко розбудить вас до чогось іншого, що все-таки пропонує.


4
Але "математику та біоінформатику" краще писати на C #, JAVA або C ++
Ян

Насправді Python та Perl є домінуючими мовами в цих областях.
dryajov

1
Власне, головна причина, по якій я це втілюю, - це програми машинного навчання. Отже, у вас є пункт.
voodooattack

@dryajov Будь раді, що ти не знаєш, наскільки великий FORTRAN в деяких сферах обчислювальної науки ...
cmaster

@dryajov Оскільки вони доступніші людям, які, можливо, не є програмістами повний робочий день, а не тому, що їм по суті краще в послідовності геномів - ми створили цілеспрямовані мови, такі як R, і склали для цього наукові мови, як Fortran.
кіт

0

Я дуже вірю, що це інша і потужна ідея. Ви йдете проти систем вірування. Речі стають прийнятими або популярними через мережу впливає не на підставі заслуг. Також ніхто не хоче адаптуватися до нового стека. Люди автоматично відкидають надто різні речі.

Якщо ви можете придумати спосіб перетворити його в звичайний модуль npm, що здається малоймовірним, то, можливо, деякі користувачі можуть його використовувати.


Ви маєте на увазі, що програмісти JS заблоковані до npm?
voodooattack

3
Питання про нову систему виконання, а не про якийсь модуль npm, а також про зміну одночасності спільного стану - це справді стара ідея.
Анкур

1
@voodooattack Я маю на увазі, що вони замикаються на підході, який вже є популярним, і це буде поруч із неможливим подоланням упередженості статусного кво.
Jason Livesay
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.