Comments 92
function mysqlQuery(query, cb) {
connection.query(query, function (err, results, fields) {
cb({err, results, fields});
});
}
function generatePage(res) {
const time = process.hrtime();
mysqlQuery("SELECT * FROM `users`", ({err, results, fields}) => {
let response = JSON.stringify(results);
const diff = process.hrtime(time);
const generationTime = diff[1] / 1000000;
response += `<div><b>Страница сгенерирована за: ${generationTime}ms</b></div>`;
res.end(response);
});
}
а зачем вы столь извращенно завернули обращение к базе в «свой апи»?
вы же этим кодом вставляет палки в колеса JIT'у.
почему нельзя было сделать так?:
function generatePage(res) {
const time = process.hrtime();
connection.query("SELECT * FROM `users`", function (err, results, fields) {
let response = JSON.stringify(results);
const diff = process.hrtime(time);
const generationTime = diff[1] / 1000000;
response += `<div><b>Страница сгенерирована за: ${generationTime}ms</b></div>`;
res.end(response);
});
}
const Promise = require('bluebird')
const mysql = require('mysql')
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'pwd',
database: 'test',
connectionLimit: 100
})
pool.query = Promise.promisify(pool.query)
function generatePage(res) {
const time = process.hrtime()
pool.query(`SELECT * FROM 'users'`)
.then(results => {
let response = JSON.stringify(results)
const diff = process.hrtime(time);
const generationTime = diff[1] / 1000000;
response += `<div><b>Страница сгенерирована за: ${generationTime}ms</b></div>`
res.end(response)
})
.catch(err => console.log(err))
}
Я не node.js дев, потому лишь указал на явный косяк в коде.
1. если не преследуется цель написать DAL, чтобы потом можно было менять имплементацию коннектора, то смысла в этом нету.
2. в версии ПХП этого теста, даже функций нету — сплошное полотно.
Если была цель сделать как в реальной системе — были бы модули, подключался хотя бы PDO, а не функция mysqli, которая еще с php4 тянется в коре.
А так, это похоже на попытку написать код так, чтобы он просто работал хуже.
В реальных проектах на php уже давно не пишут простыню кода. И уж тем более не делают смесь html + php + sql, как это будет у вас при вашем текущем подходе.
Измерять скорость работы в попугаях в двух задачах, которые даже близко не лежали с реальными — зачем? Ради холивара? — ок, вам это получилось. Ради правды? — так вы не узнаете ничего.
И снова таки: если вам нужна производительность системы — возьмите платформу, которая даст производительность из коробки — компилируемые языки такие как C#, Java, Scala, Go.
ps: а задачи php и node.js в целом не схожи между собою: php нацелен на CPU-bound обработку, node.js — на IO-bound. В нормальной системе было бы хорошо даже совмещать их, нежели пихать невпихуемую логику в конкретную из платформ.
Кусок кода
const mysql = require('mysql2');
const Promise = require('bluebird');
const http = require('http');
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'pwd',
database: 'test',
connectionLimit: 100
});
pool.query = Promise.promisify(pool.query);
function generatePage(res) {
const time = process.hrtime();
pool.query('SELECT * FROM `users`')
.then(results => {
let response = JSON.stringify(results);
const diff = process.hrtime(time);
const generationTime = diff[1] / 1000000;
response += `<div><b>Страница сгенерирована за: ${generationTime}ms</b></div>`;
res.end(response)
})
.catch(err => console.log(err))
}
connectionLimit пробовал ставить разный и 10 и 50 и 100 и 1000. Лучший результат — 380 запросов в секунду…
node 7.3.0
test3 (array): 53.455ms
php 7.1.1
test3 (array): 63.453ms
То есть php не «в разы быстрее», а медленнее
С этим «тестом» та же история, только новичков пугать, не зря минусуют. Или кто-то верит, что существуют приложения без пост обработки данных после получения их с базы данных? Добавить немного логики в вычисления, и красивые цифры в пользу php разрушаться
С простой логикой, вроде подсчёта возрастов, или подсчёта людей по полам
Тогда исключим влияние сторонних библиотек
for (let i = 0; i < results.length; i++) {
response += `<span>Hello <i>${results[i].login}!</i> </span>`;
}
это не то же самое, что просто выплёвывание строки через echo в случае с PHP
while ($row = $res->fetch_assoc()) {
echo "<span>Hello <i>{$row['login']}!</i> </span>";
}
Склеивание строк — не самая дешёвая операция. А скорость работы через echo в свою очередь зависит от буферизации ответа.
1. Прикрутите в PHP переменную и склеивайте в неё ответ как в случае с Node.js
2. А зачем вам вообще Nginx? Запустите в консоли два скрипта и измеряйте их скорость.
2. Зачем убирать nginx? Лучше же когда конфиг максимально близок к работающему в боевом режиме.
2. Боевые конфиги тоже бывают разными. Тут просто надо определиться, что тестируем. Если сферическое приложение, то лучше бы добавить хотя бы шаблонизаторы. Если скорость взаимодействия с nginx (что довольно бредово, но тестировать можно всё что угодно), то надо выкидывать базу данных. Если скорость отрисовки строк, вынутых из mysql, то nginx не нужен.
Похоже вы не поняли смысл теста и что именно тестируется, прочитайте текст внимательнее. Сравнение 2х примеров реального приложения. Какой язык заставит пользователя меньше ждать результата от сервера.
И медленный ответ сервера может значить в равной степени и его кривую настройку. Почему я вам выше и предлагал пустить два чистых скрипта без nginx и сравнить результаты. Ну или добавьте на гитхаб конфиги nginx'а хотя бы.
И, честно говоря, судя по вашим комментариям, у вас нет цели разобраться в том, почему так происходит. За что вас, собственно, и поливают грязью. Одно дело сделать исследование вида «чёрный ящик А работает быстрее чем чёрный ящик Б в сферической задаче Х» и совсем другое разобраться, почему так происходит. Если бы вы провели глубокое исследование по любому участку, начиная со склеивания строк и заканчивая коммуникацией с базой, сравнили бы работу через unix-сокеты с проксированием запроса nginx'ом на другой порт и прочее и прочее, то эффект был бы другим. Пока вы просто плюнули в Node.js с применением странной задачи. Как думаете, убедили ли вы кого-нибудь в своей правоте? Извлёк ли кто-то пользу из вашей стати? Вы сами для себя в чём-то стали лучше разбираться? Пока кажется, что вы просто хотите похоливарить. Как развлечение это годиться, но пользы от этого никому нет. Топик утонет в сотнях таких же непонятных тестов, которые поверхностно показывают что на взятой с потолка задаче побеждает любимый язык автора.
Какой язык заставит пользователя меньше ждать результата от сервера.
Уж если на то пошло, то не язык, а платформа. Язык никого ждать не заставляет.
#ab -n 3000 -c 1000…
Никогда не понимал, зачем такакя конкурентность большая в тестах. :)
Разве столько клиентов придет одновременно?
Ну а по теме:
Используем PHP 7.0, преимуществ в 7.1 не вижу. Хз, есть ли для него тот же memcached.
Но PHP используется, потому что так исторически сложилось.
Ну и код просто на нем пишется.
А NodeJS — это чуток другой подход, вся эта асинхронность, чтобы не наделать случайно синхронности.
Да, оно красиво, может и быстрее работает, но лень разбираться. :)
На мой взгляд вы сравнили скорость работы драйверов MySQL для nodejs и php7, а не сам бэкенд.
https://habrahabr.ru/post/323208/#comment_10101554
кто-то верит, что существуют приложения без пост обработки данных после получения их с базы данных? Добавить немного логики в вычисления, и красивые цифры в пользу php разрушаться
Поэтому ваш код брать даже смысла нет, потому что он ничего не делает
Но если вы настаиваете, что такие бывают, то всё еще проще, для таких приложений уровня как вы тестируете совершенно не важно что брать, потому что там не будет больше 2х человек в месяц
test1_node (str): 67.853ms
test1_php (str): 83.961ms
test2_node (sum): 8.685ms
test2_php (sum): 69.857ms
test3_node (array): 53.455ms
test3_php (array): 63.453ms
«обогнал» так обогнал, только пятки видны.
При этом чем больше логики (то есть чем приложение больше приближено к реальному), тем слабее позиции php. Но можно и дальше закрывать на это глаза и прогонять «пустые» тесты без логики
Если добавить к тестам логики, то php отстанет еще сильнее
Php Был первым, и простым.
Но если, не завезут Jit, много-поточность, асинхронность, connection pool, технология постепенно вымрет.
Я сам только писал на php, с nodejs,python,C# только баловался.
Вопрос сколько php будет вымирать ))
Жаль конечно что существуют еще люди которые верят что php Rules!
Php архитекторам надо надо Libuv внедрять!
Так как новый net core так и сделал !
Тесть вас не волнует скорость работы приложения? Главное чтобы язык был модный и новый?
Не холивара ради, но сколько лет я слышу уже что пхп вот-вот вымрет… а он таки живее всех живых, а вымирают лишь модные(появился захайпился и сгорел аки мотылек через условные(!) пару лет) фреймворки\языки, причем пачками :)
толстый тролль
Мне пых не нравится по определению.
Поэтому я промолчу про кривые тесты в сферическом вакууме.
Ответ: На одно ядреном процессоре будет медленнее. (Проверено неоднократно)
Вначале вы говорите:
Сегодня у нас будет более честное сравнение, которое отображает большинство реальных задач.
Но разве делать сервис, с серьёзными требованиями к производительности, на таком железе «отображает большинство реальных задач»?
а для числодробилок лучше что-нибудь другое использовать
по самим тестам необходимо указывать конфигурации. например, включен ли opcache
Напиши как угодно и с любыми хаками, если это поможет обогнать другой язык, то это просто супер.
Во вторых, я решил сравнить именно эти 2 очень популярных языка и не вижу в этом ничего плохого.
В третьих, если мне нужна реальная скорость, я напишу это на СИ) Ибо, зачем прибегать к полумерам в виде C#, Java, Scala, Go и т.п. в таком случае)
А мне производительность не настолько важна, чтобы поддерживать логику рендеринга на двух языках (клиентский рендеринг React точно в проекте будет) или писать бизнес-логику на JS. От этих двух языков я беру, прежде всего, лучшую скорость разработки в соответствующих задачах.
Долго пытался понять, зачем в коде запроса к BD используется деструктуризация аргументов (причем в обе стороны), но так и не смог. Видимо, чтобы сделать код специально медленнее. И тем более в тесте на скорость странно видеть let а не var. Это тесты из серии — когда очень хочется, чтобы любимый язык победил?
А ещё, если я все запросы в БД замeню на
SELECT `id` FROM `users` WHERE `id` = 1
и тогда нода будет будет работать с базой в 15 раз быстрее, чем пхп!!!А я то думаю, как же так, почему такая значительная разница в скорости…
- let до сих пор не оптимизирован в циклах, потому обычно его там не используют.
- Так что там с деструктуризацей, зачем аргументы загонять в объект и потом обратно разворачивать этот объект? Какой сакральный смысл то?
Как только в приложении появляется бизнес логика (привет коллбэкам), как только с данными нужно проводить операции которые занимают процессорное время (привет однопоточности) а не только асинхронный io, начинаются пляски с промисами, асинк и т.д. (асинк эвэйт из той же серии) и разработка превращается в ад и Израиль.
Не ведитесь на цифры, они далеко не фактор. Я уже не говорю о нормальных разработчиках которые реально понимают разницу между Parallel vs Concurrent.
Я все еще пишу на ноде, но очень маленькие прототипы с минимум логики, микросервисы можно сказать. Когда нужно писать что нибудь серьезное, понимаешь что тебе не хватает управления твоей же программой. Хочется самому решать в каком потоке и что запускать, синхронизировать, и т.д. Хочется писать нормальный синхронный код и не тратить время на понимание каши которую сам же и написал 5 минут назад, и строить в голове граф из колббэков, прромисов и т.д.
В тоже время PHP я вообще не использую для написания миркосервисов (ну не его это ниша). Если программеры нормальные, PHP это отличное решение для быстрой веб-разработки, особенно для стартапов. Масштабируется PHP тоже очень хороше. А то что работает медленно, можно вынести в микросервис.
И вот тут у меня большие надежды на GO. Писать микросервисы одно удовольствие. GO дает достаточно высокоуровневого API, и в тоже время. у программиста есть возможность использовать низкоуровневые плюшки (мьютексы и т.д.).
P. S.
На неделе исправил баг в системе, когда CRM умирал (LAMP стэк). После рисерча, нашелся код, от одного разраба который работал в компании в 2015 году. Там было (это я еще почистил от мусора):
//Задача — найти все депозиты конкретного клиента
function findUserDeposits($user_id)
{
$deposits = $this->getAllDepositsFromDatabase(); // SELECT * FROM transactions
$transactions = $this->deepCopy($deposits); // deep copy of $deposits array data to new array with array key as row id from database
$results = [];
foreach ($transactions as $transaction) {
if (('' . ($transaction['user_id'])) !== ('' . $user_id)) {
continue;
}
$id = $transaction['id'];
$result[$id] = $transaction;
}
return $results;
}
Не трудно догадаться почему все умерло… Когда я это увидел у меня скатилась слеза…
Что-то мне подсказывает, дай этому разрабу вместо php, какой-нибудь С или JAVA, ничего бы не изменилось. А вой дай ему NODEJS с коллбэками, то я даже представить не могу что бы он там наколбасил. А вы тут микросекунды считаете. Я сам как инженер люблю цифры, но вот пришел к понимаю того, что это далеко не главное, во всяком случае не там где эти цифры нам показывают в тестах.
Вот померять скорость обработки изображения например — тут реально есть что мерять и сравнить разные тулзы и языки. А взять с базы, выплюнуть JSON или html страничку, и замерять это — вот уже действительно трата времени.
Ну вот, теперь осталось Вам понять, как ускорить php))
На самом деле, чтобы статья стала чуть более «уважаемым», надо добавить результаты профилировщика
Понять, где эти узкие места
И сказать, допустим, «вот из-за этой стандартной операции 1+1 php быстрее node»
или «из-за своей асихнронной модели нода оказалась чуть круче чем php в таких-то и таких-то задачах»
Это и послужит выводом, потому что сейчас его нет.
А завтра вы узнаете что в PHP есть Постоянные соединения. И он догонит, а потом я вам дам, свой форк mariasql и nodejs будет снова в лидерах.
А итог такой, ваш тест, тестирует только ваши знания и ничего больше.
По поводу конфигов системы, пхп, Mysql
У меня настроено так, чтобы работало максимально быстро.
Если вы не знаете как должна быть настроена операционная система, php, nginx и mysql. Это не моя проблема.
Несерьезный какой-то подход. А если у вас там запросы кэшируются или еще что? Может вы просто node vs nginx протестировали.
Залейте конфиг nginx в репозиторий хотя-бы.
Nginx + PHP 7.1.1 FPM vs Node.js 7.7.1 в качестве бэкенда ч.2