#javascript #java #node.js #multithreading #v8
#javascript #java #node.js #многопоточность #v8
Вопрос:
Эта тема была у меня в голове долгое время.
Давайте предположим, что у нас есть обычный веб-сервер, один на Node.js
, а другой на Java
(или любом другом языке с потоками).
Почему узел должен работать лучше (обрабатывать больше запросов ввода-вывода / сетевых запросов в секунду), чем сервер Java, только потому, что он использует async / await? Разве это не просто синтаксический сахар, который использует те же потоки, которые java / c # / c используют за кулисами?
Комментарии:
1. Я рекомендую прочитать это: подписка. packtpub.com/book/web_development/9781783287314/1 /…
2. «Почему node будет работать лучше, чем сервер Java» — я думаю, что это не так. Вы запускали тест? И можно написать асинхронный Java-сервер без async / await, но который работает параллельно.
Ответ №1:
Нет причин ожидать, что узел будет быстрее сервера, написанного на Java. Как вы думаете, почему это может быть?
Похоже, что другие ответы здесь (пока) объясняют преимущества асинхронного программирования на JS по сравнению с однопоточными синхронными операциями — это очевидно, но не в этом вопрос.
Ключевой момент, с которым все согласны, заключается в том, что определенные операции по своей сути медленные (например: ожидание сетевых запросов, ожидание доступа к диску / базе данных), и эффективно позволить процессору делать что-то еще, пока такие операции выполняются. Использование нескольких потоков в вашем приложении — один из хорошо зарекомендовавших себя способов сделать это; но, конечно, это возможно только в языках, которые предоставляют вам потоки. Многие традиционные серверные реализации (в Java, C, C , …) используют один поток на запрос (или, что эквивалентно, пул потоков для распределения входящих запросов). Эти потоки могут блокировать ожидание, скажем, базы данных — ничего страшного, операционная система переведет ожидающий поток в спящий режим и позволит процессору тем временем работать с другим потоком (обрабатывая другой запрос). Конечный результат довольно похож на то, что вы получаете с Node.
JavaScript, конечно, не делает потоки доступными для программиста. Но вместо этого у него есть концепция планирования запросов с помощью движка JavaScript и обеспечения обратного вызова, который будет вызван по завершении запроса. Вот как система в целом ведет себя аналогично традиционному языку многопоточного программирования: пользовательский код может сказать «сделайте это, затем запланируйте доступ к базе данных, и когда результат будет доступен, продолжайте с этим кодом [обратного вызова] здесь», и в ожидании запроса базы данных центральный процессор выполняет какой-то другой код. Чего вы хотите избежать, так это того, что центральный процессор будет сидеть сложа руки в ожидании, пока у центрального процессора найдется время для этого, и оба подхода (потоки Java и обратные вызовы JavaScript) выполняют это.
Наконец, async / await (так же, как и Promises) — это действительно просто синтаксический сахар, который упрощает написание кода на основе обратного вызова. Код, использующий async / await, ничуть не быстрее, чем код старого стиля, использующий прямые вызовы, просто красивее и менее подвержен ошибкам. Это также ничуть не быстрее, чем (хорошо написанный) сервер на базе Java.
Node.js популярен, потому что удобно использовать один и тот же язык для клиентской и серверной частей приложения. С точки зрения производительности, это не лучше традиционных альтернатив, просто также не хуже (или, по крайней мере, ненамного; на практике то, насколько эффективно вы разрабатываете свое приложение, имеет большее значение, чем то, реализуете ли вы его на Java или JavaScript). Не поддавайтесь на обман 🙂
Комментарии:
1. » использование async / await ничуть не быстрее, чем код старого стиля, использующий обратные вызовы » — это не то, что нам пытается сказать v8.dev /blog /fast-async 🙂 Но да, ни один из них изначально не быстрее другого.
Ответ №2:
Асинхронность (asyn / await) необходима для потенциально блокирующих действий, например, когда ваше приложение обращается к Интернету. Доступ к веб-ресурсу иногда происходит медленно или с задержкой. Если такая активность заблокирована в синхронном процессе, все приложение должно ждать.
В асинхронном процессе (потоке) приложение может продолжать выполнять другую работу, которая не зависит от веб-ресурса, пока не завершится потенциально блокирующая задача.
https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/hh191443(v=vs.110)?redirectedfrom=MSDN#threads Хотя вы должны понимать различия между потоками и программированием async / await.
Комментарии:
1. Я прочитал отправленную вами ссылку и понимаю, что async / await не создаст фоновый поток, но как так? Если вы делаете запрос к БД, у вас должен быть фоновый поток, который прослушивает ответ, нет? Тогда в чем преимущество async / wait перед потоками? (помимо более чистого синтаксиса)
2. Поток может делать гораздо больше полезных вещей. Await специально разработан для решения чего-то, требующего времени, чаще всего запроса ввода-вывода. Что традиционно выполнялось с обратным вызовом после завершения запроса ввода-вывода. Написать код, который полагается на эти обратные вызовы, довольно сложно, await значительно упрощает это.
Ответ №3:
Что касается асинхронного программирования, удобство использования является ключевым. Например, один запрос может быть разделен на более мелкие задачи, то есть получение внутренних результатов, чтение, запись, установление соединений и т.д. … Таким образом, половина времени тратится впустую на ожидание зависимых задач. Асинхронные модели используют это время для обработки других входящих запросов, сохраняя функцию обратного вызова, регистрируясь в очереди с сохранением состояния и становясь доступными для другого запроса. Таким образом, они могут обрабатывать больше запросов.
Узнайте больше об обработке запросов: https://www.youtube.com/watch?v=cCOL7MC4Pl0
Комментарии:
1. Хорошее объяснение.