преимущества node js перед php

UA Blog

Blog on instersting topics

Не смотря на то что PHP и Node.js могут справляться с приложениями любой сложности, они созданы на основе разных концепций и архитектур. Если вы владелец приложения выбирающий между двумя платформами, вы должны иметь в виду их основные преимущества и недостатки. Node.js и PHP одни из самых часто используемых средств для разработки веб-сайтов. PHP — скриптовый язык созданный Rasmus Lerdorf в 1994, являлся языком номер один ери Web 1.0. Показательное проявление успеха PHP являются системы управления контентом, такие как WordPress, Joomla и Drupal, с их помощью работают миллионы блогов и веб порталов. Node.js это представитель более новых технологий веб-разработки. В отличии от PHP, Node.js не является языком программирования, это среда выполнения которая использует JavaScript для написание приложений на стороне сервера. Представлен в 2009, Node.js продемонстрировал силу JavaScript при разработке событийно-ориентированных, data-driven приложений эпохи Web 2.0

Плюсы Node.js

1) Быстрое серверное решение

Node.js позволяет используя очередь событий JavaScript создавать приложения с неблокирующим вводом/выводом которые способны обрабатывать несколько запросов одновременно. Используя встроенною в JavaScript асинронность, можно создавать высокомасштабируемые серверные приложения, которые максимизируют использование одного CPU и памяти компьютера при одновременной обработке большего количества запросов, чем обычные многопоточные серверы. Такая функциональность делает Node.js прекрасным выбором для приложений реального времени и те которые требуют большого количества операций ввода/вывода

2) Один язык на фронт-енде и бекенде

Много популярных JS фреймворков таких как React или Vue написаны на JavaScript, который является основным языком всех современных браузеров. Используя Node.js на сервере вы получаете все преимущества скриптового языка на обеих платформах. Иметь один язык на фронт-енде и бекенде очень хорошо для обеспечения поддержки вашего приложения і координации меєду членами вашей команды.

Node.js не имеет строгих правил или жестких зависимостей, что оставляет простор для созидания и креативности при разработке приложений. Разработчики сами выбирают архитектуру, зависимости.

Недостатки Node.js

1) Малая эффективность в операциях интенсивно использующих CPU

Событийно-ориентированная архитектура Node.js имеет некоторые ограничения а именно низкую эффективность при большой нагрузки на CPU. Хотя и Node хорошо справляется конкурентной обработкой множества запросов, он все же плохо справляется с таким операциями как генеррование графики, обработка изображений. К счастью, существует обходной путь в котором можно выполнять такие операции по очереди или в отдельном процессе.

2) Незрелость платформы

Вместе с стабильными стандартными библиотеками такие как HTTP or Crypto, доступно множество библиотек от сторонних разработчиков. Эта екососитема еще не достаточно сфомировалась, и к сожаление приходится зависеть от не очень качесвенно протестированых модулейю

Плюсы PHP

1) Большая кодовая база

PHP огормною кодовою базу для всевозможных решений от систем управления контентом до мощных фреймворков таких как Laravel, Symfony. Например с помощью WordPress можно запустить свой блог за считанные минуты.

2) Переносимое решения

PHP достаточно независим от платформы, он может быть запущен почти на любом сервере и на любой платформе.

В тоже время, имеется широкий выбор хостингом которые с поддержкой PHP, и вам не нужно арендовать полноценный сервер с SSH доступом чтобы запустить ваш проект, в отличии от Node.js. Из этого следует что интеграция PHP проектов и их развертывание несколько проще для небольших компаний или для отдельных лиц который могут запускать и управляиь своими приложениями без знаний консольных команд, системы Linux

3) Спроектирована для WEB В отличии от Java или Python и других языков программирования общего назначения, PHP был разработан специально для Web. Именно поэтому он содержит всю необходимую функциональность для работы с HTML, серверами, базами данных. C всеобъемлющим языком PHP, в большинстве случаев можно обойтись минимальным количеством JS кода на фронт-енде.

Недостатки PHP

1) Плохое разделение ответственности (SoC)

PHP не очень хорош в реализации паттерна MVC, который является рекомендованным в веб-разработке. Очень часто можно можно встретить микс HTML и PHP, что выливается в не очень красивый и сложно поддерживаемый код, где бизнес логик смешана с представлением

2) Устаревшая клиент-серверная модель

Источник

php и nodejs, разница на пальцах

Являясь постоянным пользователем форума nodejs.ru, часто наблюдаю картину когда люди начиная изучать nodejs сравнивают ее с php, а иногда пытаются работать с ней так как с php. Я бы хотел объяснить “на пальцах” разницу между php и nodejs применительно к работе сайта. Статья предназначена для новичков. Я намеренно буду говорить очень упрощенно, не вдаваясь в глубокие подробности, что бы как можно проще показать различия в технологиях.

Что то объяснять всегда лучше на наглядном примере с картинками. Поэтому придумаем небольшой “сферический сайт в вакууме” и примем некоторые условия.

Пусть у нас имеется некий сайт, который понимает всего два запроса:
Запрос А выполняется за 1 секунду, он не требует обращение к БД.
Запрос Б выполняется за 5 секунд, причем 4 из них, он тратит на ожидание ответа БД.
Так же условимся что время между запросами не менее 1 секунды.

Давайте рассмотрим как это работает на php.
В самой упрощенной форме архитектура сервера выглядит так:

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

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

При наличии всего одного php процесса, работа нашего сервера можно отобразить на такой схеме:

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

Из схемы видно, что пока к нам поступают только запросы А наш сервер бодро на них отвечает и в целом выполняет поставленным задачи, но как только к нам приходит запрос Б, сервер перестает отвечать на запросы, до момента пока не будет готов ответ на запрос Б. Так же на схеме видно что большую часть времени запроса Б “все” ждут результат работы базы данных.

Для решения этой проблемы приходиться увеличивать кол-во php процессов, давайте увеличим до 2х, в результате схема принимает такой вид:

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

Из этой схемы видно, что запрос Б “повисает” в обработке в первом php процессе, при этом сервер продолжает отвечать на остальные запросы. Все будет идти хорошо до момента, когда к нам не придут два запроса Б, тогда оба php процесса “повиснут” в ожидании ответа базы, и сервер в целом перестанет отвечать, до момента пока один из них не освободиться.

Ну мы то уже знаем что делать? Правильно, возьмем и увеличим кол-во php процессов, сразу до 20 или 30 и проблема вроде как ушла, хотя на самом деле проблема просто немного отдалилась и момент когда придет 30 запросов Б наступит. Вся беда в том что мы не можем создавать бесконечно много php процессов и путь наращивать их в запредельных количествах неверен.

Самое главное в что следует вынести из этих схем, это то, что операции работы с базой данных в php выполняются синхронно. В нашем случае процесс выполнивший запрос к базе неспособен обработать другие запросы и вынужден “висеть” (ничего не делая) ожидая ответ от базы данных.

nodejs

Что дает нам nodejs?
Сначала посмотрим как выглядит простой сервер:

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

Сразу бросается в глаза то, что сервер включает в себя обработчики непосредственно запросов А и Б, а так же сам Веб сервер. Всё это добро крутится в одном node процессе и постоянно висит в памяти.

Посмотрим на схему работы:

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

На схеме хорошо видно что запросы Б не приводят к “подвисанию” сервера в ожидании ответа базы. Сервер получив запрос Б, просто сформирует и отправит запрос в базу данных, и продолжит отвечать на остальные запросы, как только ответ от базы будет получен, сервер вернет результат клиенту. В случае nodejs неважно как и в каком количестве придут запросы Б, ни один из них не приведет к “подвисанию” в ожидании ответа базы.

Источник

PHP vs Node.js

Это перевод статьи Крэга Баклера (Craig Buckler) «SitePoint Smackdown: PHP vs Node.js» и судейских решений Бруно Шкворца и Джеймса Хиббарда (Bruno Škvorc, James Hibbard) статьи Крэга Баклера.

От переводчика

Существует много статей на эту тему, с качественными характеристическими анализами и прогнозами производительности. Однако, мне все же хотелось найти такую статью, где профессиональные программисты делятся своими мнениями и пытаются что-то подсказать, предостеречь новичка, который только изучает PHP или NodeJS (cерверный JavaScript). Многие не любят PHP и говорят, что PHP создан, чтобы умирать (да, там есть сборщик мусора, который убивает наши переменные после выполнения скрипта, а не потому что его забросил Расмус Лердорф), однако, что теперь не учить PHP совсем, в то время как на нем работает 80% сайтов в интернете. Поэтому, если мы хотим быть профессионалами и пытаться хоть как-то расширить свой кругозор, нам нужно четко разделять задачи PHP и задачи NodeJS, а не сливать все в кучу.

«10 раундов боксеров разных весовых категорий»

Введение

Web-программирование стремительно развивается, и перед back-end разработчиками встает вопрос выбора между устоявшимися тяжеловесами Java, C, Perl и современными веб-ориентированными языками, такими как, Ruby, Clojure, Go. Ваш выбор имеет огромное значение, накладывая свой отпечаток на работу приложения.

Но какой сделать выбор для веб-разработки?

Не хочеться затевать холивар, но все же мы будем сегодня говорить о PHP и NodeJS:

Почему не говорим о C#, Java, Ruby, Python, Perl, Erlang, C++, Go, Dart, Scala, Haskell, и других?

Стали бы вы читать статью обо всем и вся, вам нужна энциклопедия? Поэтому мы огранили и сужили круг до двух знаменитых потому, что:

1. PHP и Node.js веб-ориентированны, у обоих открытый исходных код, они направлены, исключительно, на веб-разработку
2. PHP давний язык, однако, Node.js в нашем случае является выскочкой, который набирает обороты по популярности, поэтому php-разработчику стоит задаться вопросом. А стоит ли менять технологию?
3. Многие разработчики программируют с далеких 90х на PHP и JavaScript и переходить на другие языки программирования не все хотят, ибо не отдают им должное.

Правила

Боксер в правом углу — PHP, боксер в левом — Node.js. Абсолютным победителем будет та технология, которая победит по количеству раундов.

Первый раунд: быстрый старт

В этом раунде мы определяем, как быстро мы можем написать «Hello, world» страницу на том или ином языке программирования, в это время мы включаем время потраченное на настройку сервера.

1) Как быстро вы можете построить «Hello World» веб-страницу на PHP:

Этот код может быть написан где угодно, как правило, код пишут в файлах, оканчивающихся на расширение .php. Если вы написали этот код в файле index.php и запустили на локальном сервере через порт 8000 (на своем компьютере, а не на реальном хостинге), то его отображение будет доступно по адресу:

.
Однако, используя готовый интерпретатор PHP со встроенным сервером довольно ненадежное занятие. Лучше использовать готовые решения, сборки Apache — XAMPP или виртуальные OS (Vagrant). Кстати, свой файл вы сможете загрузить на любой хостинг интернета.

2) Установить платформу Node.js проще простого, если вы работаете на unix-подобных системах, вы сможете это сделать и при помощи менеджеров пакетов. Давайте создадим страницу index.js:

Мы повторили аналогичные действия, код на JavaScript, как правило, пишут в файлах, оканчивающихся на расширение .js. Если вы написали этот код в файле index.js и запустили на локальном сервере через порт 8000 (на своем компьютере, а не на реальном хостинге), то его отображение также будет доступно по адресу (при условии, что php теперь работает на другом порту):

Теперь давайте оценим код, даже если вы хорошо знаете клиентский JavaScript, вам придется думать и разбираться с тем, что же здесь написано. Вы должны понимать замыкания и callback-функции, промисы, программирование на стороне Node.js требует некоторой сноровки.

PHP концептуально проще и выигрывает этот раунд. Хотя PHP имеет несколько программных зависимостей, однако PHP менее сложный для изучения.

Оценка судей — PHP 1:0 Node.js

Второй раунд: помощь и поддержка

На самом деле вы никуда не уедете на своих знаниях без изучения каких-либо курсов, современных практик, чтобы развиваться, вам нужно задавать вопросы на форумах, таких как — StackOverflow. PHP выигрывает этот раунд легко, он имеет большое руководство на сайте php.net и двадцать лет частовстречаемых вопросов. Что бы вы ни делали, кто-то сталкивался с этой проблемой и пытался ее решить за вас.

У Node.js есть хорошая документация, но технология довольно молода, поэтому и ответов на форумах, будет значительно меньше.

Оценка судей — PHP 2:0 Node.js

Третий раунд: синтаксис языка

В отличие от некоторых языков и фреймворков, PHP не заставит вас работать определенным образом, и растет вместе с вами. Вы можете писать свои маленькие программы на простых функциях PHP4, и они будут отличаться своей красотой от MVC PHP 5+. Однако в таком случае, ваш код может быть хаотичным, вы начнете писать лучший код только с пониманием некоторых вещей.

Синтаксис PHP изменялся с выходом новых версий, из-за чего была проведена работа по обратной совместимости. Вы можете легко перенести код с PHP4 на PHP5. Однако, в следствии такого подхода, в PHP образовался беспорядок (каша).

Например, как вы подсчитать количество символов в строке?

— count()? str_len()? strlen()? mb_strlen()?

Вы найдете в документации для этого несколько функции, но на самом деле, все просто. Вообще, в PHP много функций, которые работают одинаково, попробуйте написать несколько строк кода, не посоветовавшись с наставником.

C JavaScript все иначе:

PHP имеет множество преимуществ, однако Node.js выигрывает по некоторым причинам:

1. JavaScript кажется самым непонятным языком в мире, но как только вы улавливаете его концепцию, остальные языки становятся громоздкими по сравнению с ним.
2. JavaScript выглядит минимальнее, чем PHP, вам не нужно бороться с тем же UTF-8.
3. Full-stack разработчики могут писать код на JavaScript как на стороне клиента, так и на стороне сервера. Вам больше не нужно переключаться между технологиями.
4. Изучая JavaScript, вам хочется больше и чаще писать на этом языке, про PHP такого нельзя сказать.

Оценка судей — PHP 2:1 Node.js

Четвертый раунд: инструменты разработчика

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

У PHP есть свой менеджер пакетов, разработанный под влиянием npm — Composer. Однако, ежели npm встроен по умолчанию, тот composer придется встраивать самостоятельно. Благодяря npm широкое распространение получили Gulp, Grunt — системы сборки front-end проектов.

Оценка судей — PHP 2:2 Node.js

Пятый раунд: среда

Где могут быть использованы эти технологии. Как их развернуть? Какими платформами поддерживаются? Веб-разработчикам часто нужно создавать приложения, которые только относятся к web, например, разработка онлайн-сервиса, сценарии преобразования данных и т.д.

На PHP вы можете разрабывать десктопные приложения или консольные утилиты, но в основном PHP нужен на стороне сервера и редко выходит за пределы этой границы.

Несколько лет назад, JavaScript использовался исключительно для браузера. С приходом Node.js вы можете писать десктопные и мобильные приложения, а также можно программировать и микроконтроллеры. Node.js расширил границы JavaScript.

Оценка судей — PHP 2:3 Node.js

Шестой раунд: интеграция

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

Node.js догоняет быстро, но вы можете изрядно попотеть, чтобы найти современные компоненты интеграции для старых вещей.

Оценка судей — PHP 3:4 Node.js

Седьмой раунд: хостинг и развертывание

Как легко разворачиваются новенький приложения на настоящем веб-сервере? Тут еще одна чистая победа PHP. Любой хостинг интернета поддерживает PHP. Вы можете получить MySQL базу данных по выгодной цене. Тут PHP значительно проще песочницы (локального сервера) и вы будете точно уведомлены, какие PHP расширения отключены, а какие нет.

Node.js совсем другой зверь, и он может работать на стороне сервера постоянно, без разрыва связи. Для этого, вам придется искать специализированные хостинги. Вам потребуется виртуальное облако (VDS/VPS, серверная среда, с полным доступом). К сожалению, такое могут себе позволить не все хостеры, поэтому и цены будут соответствующие.

Оценка судей — PHP 4:4 Node.js

Восьмой раунд: производительность

PHP не сутулиться и есть реальные проекты, и варианты, которые позволяют PHP работать быстрее. Даже самый требовательный разработчик PHP редко беспокоится о скорости, но производительность Node.js, как правило, лучше. Конечно, производительность в значительной степени является следствием опыта и командной разработки, однако, Node.js имеет несколько преимуществ:

1. Меньше зависимостей
Все запросы к приложению PHP должны быть направлены на веб-сервер, который запускает интерпретатор PHP, который обрабатывает код и отдает его. Node.js не нужно так много зависимостей, и, хотя вы почти наверняка используете фреймворк на сервере, такой как express, он совсем легкий и управляет частью вашего приложения.

2. Быстрый интерпретатор
Node.js меньше и проворнее, чем РНР. Это связано с наследием Google, который сделал огромный вклад в производительность JavaScript движка — V8.

3. Приложения работают постоянно
РНР выполняет обычную клиент-серверную модель. Каждый запрос страницы инициирует приложение, загрузка параметров подключения к базе данных, извлечение информации и отображения HTML-кода. В Node.js приложение постоянно работает и его нужно инициализировать только один раз. Например, можно создать один объект подключения к базе данных, которая используется повторно при новом запросе. Правда, есть способы, реализации такого поведения и на PHP с использованием специальных систем, таких как memcached, но это не стандартная функция языка.

4. Событийный, неблокирующий поток ввода/вывода
PHP и большинство других серверных языков используют очевидную модель блокировки. Когда вы делаете запрос на извлечение информации из базы данных, запрос выполнит и завершит процесс, прежде чем перейдет к следующему оператору. В Node.js все иначе. В Node.js не нужно ждать. Вместо этого можно создать функцию обратного вызова, которая, прослушивая процесс, выполняется после того, как действие завершится.

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

Node.js / JavaScript работает в одном потоке, а большинство веб-серверов многопоточные и обрабатывают запросы параллельно. Написание асинхронного кода является сложным и несет свои собственные проблемы.

Оценка судей — PHP 4:5 Node.js

Девятый раунд: страсть программирования

Это немного сложно сравнивать, но относительно немногие разработчики PHP увлечены самим языком. Когда в последний раз вы читали статью по PHP или смотрели презентацию, которая пленила публику? Возможно, все, что было сказано? Может быть, есть менее увлекательным? Может быть, вы не смотрите в нужных местах? Есть некоторые интересные особенности, которые появились совсем недавно, например, появление — PHP7, но все же эта технология топталась в течение нескольких лет. Это сказалось на самом языке, многие разработчики стали ругать PHP.

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

Оценка судей — PHP 4:6 Node.js

Деcятый раунд: будущее

Это не особо важно, какой язык вы используете на стороне сервера, он все равно будет продолжать работать, даже если проект заброшен. Многие продолжают использовать PHP. Это безопасная ставка и ее поддержка выглядит уверенной еще двадцать лет.
При этом мы знаем, что восхождение Node.js было быстрым. Современный подход к развитию очевиден тем, что использует тот же синтаксис, что и на клиентской стороне. JavaScript поддерживает HTML5, веб-сокеты. Node.js неизбежно отнимает долю на рынке, но PHP, я сомневаюсь, что будет обгонять. Обе технологии имеют большое будущее. Я заявляю, этот раунд заканчивается ничьей.

Оценка судей — PHP 5:7 Node.js

Абсолютный победитель

Окончательный счет 5:7 в пользу Node.js. Node.js имеет крутую кривую обучения и не является идеальным для начинающих разработчиков, но он все же выигрывает. Просто. Если вы грамотный JavaScript-программист, который любит свой язык, Node.js не разочарует вас. Вы почувствуете себя свежее и получите освободительный опыт веб-разработки. Но не стоит сбрасывать PHP со счетов. PHP жив, и есть мало оснований ставить подножку PHP, из-за того, что это выглядит модным. PHP проще изучить, вы сможете овладеть профессиональными приемы программирования, главное практика. PHP очень легко развернуть на сервере. Даже упертые Node.js-разработчики должны использовать PHP для простых сайтов и приложений.

Мой совет: оценить варианты и выбрать язык, основанный на ваших требованиях. Это гораздо более практично, чем полагаться на «за и против»!

Источник

Производительность I/O бэкэнда: Node vs. PHP vs. Java vs. Go

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

Понимание модели ввода/вывода вашего приложения может привести и к пониманию различий между приложением, работающим с нагрузкой, под которой оно создавалось, и тем, которое лицом к лицу столкнулось с реальным способом своего применения. Возможно, если ваше приложение невелико и не создаёт большой нагрузки, то для него это не так важно. Но по мере роста трафика использование ошибочной модели ввода/вывода может погрузить вас в мир боли.

Как и в большинстве других ситуаций с несколькими возможными решениями, дело не в том, какой из вариантов лучше, дело в понимании компромиссов. В этой статье мы сравним Node, Java, Go и PHP из-под Apache, обсудим модели ввода/вывода в разных языках, рассмотрим достоинства и недостатки каждой модели и прогоним простенькие бенчмарки. Если вас волнует производительность ввода/вывода вашего следующего веб-приложения, то эта статья для вас.

Основы ввода/вывода: освежим знания

Для понимания факторов, относящихся к вводу/выводу, сначала нужно вспомнить некоторые концепции, используемые на уровне ОС. Маловероятно, что со многими из них вам придётся иметь дело напрямую, скорее всего, вы будете работать с ними опосредованно, через runtime-окружение приложения. И подробности играют важную роль.

Системные вызовы

Возьмём сначала системные вызовы, которые можно описать так:

Ваша программа (в так называемом пользовательском пространстве) должна просить ядро операционной системы выполнить операцию ввода/вывода от имени вашей программы.

Системные вызовы — это способ, с помощью которого программа просит ядро что-то сделать. Специфика их реализаций зависит от ОС, но базовый принцип везде один и тот же. Должна быть какая-то конкретная инструкция для передачи управления из вашей программы через ядро (как вызов функции, только со специальной «добавкой» для работы в такой ситуации). В целом системные вызовы блокирующие, т. е. программа ждёт, пока ядро не вернётся к вашему коду.

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

Блокирующие и неблокирующие вызовы

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

Чтобы было понятнее, вот некоторые примеры (системных вызовов Linux):

Важно понимать различия в тайминге. Если ядро процессора работает на частоте 3 ГГц, без каких-либо оптимизаций, то оно выполняет 3 миллиарда тактов в секунду (3 такта в наносекунду). Для неблокирующего системного вызова могут потребоваться десятки тактов, то есть несколько наносекунд. Вызов, блокирующий получение информации по сети, может выполняться гораздо дольше: например, 200 миллисекунд (1/5 секунды). То есть если неблокирующий вызов длится 20 наносекунд, то блокирующий — 200 миллионов наносекунд. Процесс ждёт выполнения блокирующего вызова в 10 миллионов раз дольше.

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

Ядро предоставляет средства для выполнения как блокирующих («считай данные из сетевого подключения и дай их мне»), так и неблокирующих («скажи мне, когда в этих сетевых подключениях появятся новые данные») вводов/выводов. И в зависимости от выбранного механизма длительность блокировки вызывающего процесса будет разительно отличаться.

Диспетчеризация (Scheduling)

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

Для нашей задачи разница между процессом и потоком выполнения невелика. В реальной жизни самое главное отличие между ними с точки зрения производительности заключается в том, что поток выполнения использует одну и ту же область памяти, а процессы получают собственные области. Поэтому отдельные процессы требуют гораздо больше памяти. Но если мы говорим о диспетчеризации, то всё сводится к тому, сколько потокам и процессам нужно времени выполнения на доступных ядрах процессора. Если у вас есть 300 потоков и восемь ядер, то придётся поделить время так, чтобы каждый поток получил свою долю: каждое ядро недолго выполняет один поток, а затем переходит к следующему. Это делается с помощью переключения контекста, когда процессор переключается с одного выполняемого потока/процесса на другой.

Но с этими переключениями контекста связаны определённые затраты — они занимают какое-то время. Иногда это может происходить меньше, чем за 100 наносекунд, но нередко переключение занимает 1000 наносекунд и больше, в зависимости от особенностей реализации, скорости/архитектуры процессора, его кеша и т. д.

И чем больше потоков выполнения (или процессов), тем больше переключений контекста. Если речь идёт о тысячах потоков, когда на переключения с каждого из них уходят сотни наносекунд, то всё выполняется очень неторопливо.

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

Ещё не потеряли нить рассуждения? Сейчас начинается самое интересное: мы рассмотрим, что некоторые популярные языки могут делать с вышеописанными инструментами, и сформулируем выводы о компромиссах между простотой использования и производительностью… и другими интересными пикантностями.

В качестве примечания: в статье приведены тривиальные примеры (в некоторых случаях неполные, когда будут показаны только релевантные биты). Обращения к базе данных, внешние системы кеширования (Memcache и т. д.) и многие другие вещи в результате будут выполняться под капотом, но, по сути, это те же вызовы операций ввода/вывода, который окажут то же влияние, что и приведённые в статье простенькие примеры. В сценариях, в которых ввод/вывод описан как блокирующий (PHP, Java), HTTP-запросы и операции чтения и записи сами по себе являются блокирующими вызовами: в системе скрыто немало операций ввода/вывода, что приводит к проблемам с производительностью, которые надо учитывать.

На выбор языка программирования для проекта влияет много факторов. Также немало факторов влияет на производительность. Но если вас беспокоит, что ваша программа в основном упрётся во ввод/вывод, если производительность ввода/вывода жизненно важна для проекта, то вам нужно знать обо всех этих факторах.

В 1990-х многие носили обувь Converse и писали CGI-скрипты на Perl. Затем появился PHP, и хотя его любят критиковать, но этот язык сильно облегчил создание динамических веб-страниц.

PHP использует очень простую модель. Существует ряд вариаций, но среднестатистический PHP-сервер выглядит так.

Конечно, реальный код просто встроен прямо в вашу страницу, а операции являются блокирующими:

Вот как это выглядит с точки зрения интеграции в систему:

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

Всё просто: один процесс на запрос. Вызовы ввода/вывода просто блокируют. Достоинства? Схема простая, и она работает. Недостатки? После 20 тысяч параллельных клиентских обращений сервер просто расплавится. Этот подход плохо масштабируем, потому что не используются предоставляемые ядром ОС инструменты для работы с большим объёмом ввода/вывода (epoll и пр.). Ситуацию усугубляет то, что выполнение отдельного процесса на каждый запрос приводит к потреблению большого объёма системных ресурсов, особенно памяти, которая зачастую заканчивается в первую очередь.

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

Многопоточный подход: Java

Java пришёл в те времена, когда вы как раз купили своё первое доменное имя, и было так круто везде в разговоре вставлять словечки «точка ком». В Java встроена многопоточность (multithreading) — отличная функция (особенно на момент своего создания).

Большинство Java веб-серверов создают новый поток выполнения для каждого поступающего запроса, и уже в этом потоке в конце концов вызывают функцию, которую написали вы, разработчик приложения.

Выполнение ввода/вывода в Java Servlet выглядит так:

Поскольку наш метод doGet соответствует одному запросу и выполняется в собственном потоке, то вместо отдельного процесса для каждого запроса, требующего отдельной памяти, мы получаем отдельный поток выполнения. Это даёт приятные возможности, например можно поделиться состоянием или закешировать данные между потоками, потому что они способны обращаться к памяти друг друга. Но оказываемое при этом влияние на взаимодействие с диспетчером почти аналогично тому, что и в примере с PHP. Каждый запрос получает новый поток, и различные операции ввода/вывода блокируют внутри потока до тех пор, пока запрос не будет полностью выполнен. Потоки объединяются (pooled), чтобы минимизировать стоимость их создания и уничтожения, но в любом случае если у нас тысячи подключений, то создаются тысячи потоков, что плохо сказывается на работе диспетчера.

Важным поворотным моментом в Java 1.4 (и значительным апгрейдом в 1.7) стала возможность выполнения неблокирующих вызовов ввода/вывода. Большинство приложений, веб- и прочих, их не используют, но они хотя бы есть. Некоторые Java веб-серверы пытаются как-то применять преимущества неблокирующих вызовов, однако подавляющее большинство развёрнутых Java-приложений всё ещё работает так, как описано выше.

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

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

Неблокирующий ввод/вывод: Node

Node.js снискал себе популярность с точки зрения хорошей производительности ввода/вывода. Любой, кто хотя бы вскользь познакомился с Node, говорит, что он неблокирующий, что он эффективно обрабатывает операции ввода/вывода. И в целом это так. Но дьявол в деталях, точнее в колдовстве, с помощью которого достигается хорошая производительность.

Суть сдвига парадигмы, реализуемого Node, такова: вместо того чтобы сказать: «Напиши здесь свой код для обработки запроса», он говорит: «Напиши здесь свой код для начала обработки запроса». Каждый раз, когда вам нужно использовать ввод/вывод, вы делаете запрос и отдаёте callback-функцию, который Node вызовет по окончании работы.

Типичный код Node для выполнения операции ввода/вывода по запросу выглядит так:

Здесь есть две callback-функции. Первая вызывается, когда стартует запрос. Вторая — когда становятся доступными данные файла.

По сути, это позволяет Node эффективно обрабатывать ввод/вывод между двумя callback-функциями. Более подходящий сценарий: вызов базы данных из Node. Но я не буду приводить конкретный пример, потому что там используется тот же принцип: вы инициируете вызов базы данных и даёте Node callback-функцию; он с помощью неблокирующих вызовов отдельно выполняет операции ввода/вывода, а когда запрошенные вами данные становятся доступны, вызывает callback-функцию. Этот механизм постановки в очередь вызовов ввода/вывода с последующим вызовом callback-функции называется циклом событий (event loop). И он хорошо работает.

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

Но под капотом модели есть уловка. По большей части она связана с реализацией JS-движка V8 (JS-движок Chrome, используемый Node). Весь JS-код, который вы пишете, выполняется в одном потоке. Задумайтесь над этим. Это означает, что в то время как ввод/вывод происходит с помощью эффективных неблокирующих методик, ваш JS выполняет все связанные с процессором операции в одном потоке, когда один кусок кода блокирует следующий. Характерный пример того, к чему это способно привести: циклический проход по записям базы данных, чтобы неким образом обработать их, прежде чем отдавать клиенту. Вот как это может работать:

Вся эта концепция основана на предпосылке, что операции ввода/вывода — самая медленная часть, а значит, важнее всего обрабатывать их как можно эффективнее, даже за счёт последовательной обработки всех остальных операций. В каких-то случаях это справедливо, но не во всех.

Другое дело — это лишь мнение, — что может быть весьма утомительным писать кучу вложенных колбэков, и кто-то считает, что это сильно ухудшает читабельность кода. Нередко в Node-коде можно встретить четыре, пять и даже больше уровней вложенности.

И мы снова вернулись к компромиссам. Модель Node хорошо работает в том случае, если основная причина плохой производительности связана с вводом/выводом. Но её ахиллесова пята в том, что вы можете использовать функцию, которая обрабатывает HTTP-запрос, вставить код, зависящий от процессора, и это приведёт к тормозам во всех сетевых подключениях.

Естественное неблокирование: Go

Прежде чем перейти к обсуждению Go, должен сообщить, что я его поклонник. Я использовал этот язык во многих проектах, открыто пропагандирую предоставляемые им выигрыши в производительности, причём отмечаю их роль в своей работе.

И всё-таки давайте посмотрим, как Go работает с операциями ввода/вывода. Одна из ключевых особенностей языка — в нём есть собственный диспетчер. Вместо привязки каждого потока выполнения к одному потоку на уровне ОС Go использует концепцию горутин. В зависимости от задачи, выполняемой горутиной, среда выполнения языка может приписывать горутину к потоку ОС и заставлять исполнять её — или переводить её в режим ожидания и не ассоциировать с потоком ОС. Каждый запрос, поступающий от HTTP-сервера Go, обрабатывается в отдельной горутине.

Схема работы диспетчера:

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php

Под капотом это реализовано с помощью разных ухищрений в runtime-среде Go, которая реализует вызовы ввода/вывода, делая запросы на запись/чтение/подключение и т. д., затем переводя текущую горутину в спящий режим с информацией, позволяющей снова активировать горутину, когда можно будет предпринять следующее действие.

Фактически runtime-среда Go делает нечто, не слишком отличающееся от того, что делает Node. За исключением того, что механизм колбэков встроен в реализацию вызовов ввода/вывода и автоматически взаимодействует с диспетчером. Также Go не страдает от проблем, возникающих из-за того, что вам приходится помещать весь обрабатывающий код в один поток выполнения: Go автоматически распределяет горутины по такому количеству потоков ОС, какое он считает подходящим в соответствии с логикой диспетчера. Код выглядит так:

Как видите, базовая структура кода того, что мы делаем, напоминает структуру более простых подходов, но под капотом использует неблокирующий ввод/вывод.

В большинстве случаев нам удаётся «взять лучшее от двух миров». Для всех важных вещей используется неблокирующий ввод/вывод; при этом код выглядит как блокирующий, но всё же получается более лёгким в понимании и сопровождении. Остальное решается при взаимодействии между диспетчерами Go и ОС. Это неполное описание магии, и если вы создаёте большую систему, то рекомендуется уделить время более глубокому изучению работы с вводом/выводом. В то же время окружение, полученное вами из коробки, хорошо работает и масштабируется.

У Go есть свои недостатки, но в целом они не относятся к работе с вводом/выводом.

Ложь, наглая ложь и бенчмарки

Трудно привести конкретные тайминги переключения контекста при использовании вышеописанных моделей. К тому же эта информация вряд ли была бы вам полезна. Вместо этого предлагаю прогнать простенькие бенчмарки и сравнить общую производительность HTTP-сервера в разных серверных окружениях. Но имейте в виду, что на результирующую производительность «HTTP-запрос/ответ» влияет много факторов, и приведённые здесь данные позволят получить лишь общее представление.

Более подробную информацию о тестируемых средах можно почитать здесь.

Сначала рассмотрим примеры с небольшим распараллеливанием (low concurrency). Прогоним 2000 итераций с 300 одновременными запросами и применением только одного хеширования к каждому запросу (N = 1):

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php
Сколько миллисекунд потребовалось на выполнение всех одновременных запросов. Чем меньше, тем лучше

На основании одного графика трудно делать какие-то выводы. Но создаётся впечатление, что при таком объёме подключений и вычислений мы видим результаты, которые больше похожи на общую продолжительность выполнения самих языков, а не длительность обработки операций ввода/вывода. Обратите внимание, что медленнее всего работают так называемые скриптовые языки (слабая типизация, динамическая интерпретация).

Увеличим N до 1000, оставив 300 одновременных запросов — нагрузка та же, но нужно выполнить в сто раз больше операций хеширования (значительно повышается нагрузка на процессор):

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php
Сколько миллисекунд потребовалось на выполнение всех одновременных запросов. Чем меньше, тем лучше

Неожиданно значительно упала производительность Node, потому что операции, активно использующие процессор в каждом запросе, блокируют друг друга. Любопытно, что PHP стал гораздо лучше по производительности (по сравнению с другими) и обогнал Java. Нужно отметить, что реализация SHA-256 в PHP написана на Си, и в этом цикле путь выполнения (execution path) занимает гораздо больше времени, потому что теперь нам нужны 1000 итераций хеширования.

Теперь сделаем 5000 одновременных запросов (N = 1) или как можно ближе к этому количеству. К сожалению, в большинстве сред частота отказов была значительной. На графике отражено общее количество запросов в секунду.

преимущества node js перед php. Смотреть фото преимущества node js перед php. Смотреть картинку преимущества node js перед php. Картинка про преимущества node js перед php. Фото преимущества node js перед php
Общее количество запросов в секунду. Чем выше, тем лучше

Картина совсем другая. Это предположение, но похоже на то, что в связке PHP + Apache при большом количестве подключений доминирующим фактором становятся удельные накладные расходы, связанные с созданием новых процессов и выделением им памяти, что негативно влияет на производительность PHP. Go стал победителем, за ним идут Java, потом Node, и последний — PHP.

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

В итоге

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

Честно говоря, несмотря на данные в этой статье описания, в PHP и Java есть реализации неблокирующих вводов/выводов, доступных для использования в веб-приложениях. Но они не так распространены, как вышеописанные подходы, и потому нужно принимать в расчёт сопутствующие этим подходам накладные операционные расходы. Не говоря уже о том, что ваш код должен быть структурирован так, чтобы работать в подобных средах. Ваше «нормальное» PHP или Java веб-приложение без серьёзных модификаций вряд ли будет работать в такой среде.

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

ЯзыкПотоки vs. процессыНеблокирующие I/OПростота использования
PHPПроцессыНет
JavaПотокиДоступноНужны колбэки
Node.jsПотокиДаНужны колбэки
GoПотоки (горутины)ДаКолбэки не нужны

С точки зрения потребления памяти потоки выполнения должны быть гораздо эффективнее процессов. Если также учесть факторы, относящиеся к неблокирующим операциям ввода/вывода, то по мере движения вниз по таблице общая ситуация с вводом/выводом улучшается. Так что если бы я выбирал победителя, то предпочёл бы Go.

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

Надеюсь, всё вышесказанное поможет вам лучше понять, что происходит под капотом нескольких языков и сред, и подскажет, как лучше решать проблемы масштабирования ваших приложений. Удачного ввода и вывода!

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *