@fattan
программист

Как объективно протестировать производительность node.js и PHP в запросах к mysql БД?

Скрипт на node, чтобы подсчитать время выполнения от 1-го до последнего асинхронного подключения к БД:
// начало выполнения скрипта
var start = new Date();
// счетчик обращений к БД
var ConnCountGlobal = 0;
// Число обращений к БД
var iLength         = 100;

var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : '', 
  database : 'epr'
});

for (var i = 0; i < iLength; i++) {
  connection.query(
    'SELECT * FROM dreg_document', 
    function(error, result, fields){
      
      // для последнего запроса вычисляем таймер
      if (ConnCountGlobal == iLength-1){
      
        var dateObj   = new Date();
        var currTime  = dateObj.getTime();
      
        console.log(' node.js - %d мс', (currTime-start.getTime()) / 1000);
      }

      ConnCountGlobal++;
    }
  );
}
connection.end();


Скрипт на PHP

$mtime = microtime();        //Считываем текущее время
$mtime = explode(" ", $mtime);    //Разделяем секунды и миллисекунды

// Составляем одно число из секунд и миллисекунд
// и записываем стартовое время в переменную
$tstart = $mtime[1] + $mtime[0];

define('DB_NAME', 'epr'); 
define('DB_USER', 'root'); 
define('DB_HOST', 'localhost'); 
define('DB_PASSWORD', '');

$link = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD) or die ("Could not connect to MySQL");

$charset = 'utf8';
$connection_method = 'SET CHARACTER SET';

@mysql_query("{$connection_method} {$charset}", $link);

mysql_select_db (DB_NAME) or die ("Could not select database!");

  for ($i = 0; $i < 1000; $i++) {
    $result = mysql_query('SELECT * FROM dreg_document');
  }

// Делаем все то же самое, чтобы получить текущее время
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = $mtime[1] + $mtime[0];
$totaltime = ($mtime - $tstart); //Вычисляем разницу	
  
  print 'php - ' . $totaltime ;
  • Вопрос задан
  • 28716 просмотров
Решения вопроса 2
Как у нас на пхп. Пишешь строчки, выполняет по порядку. Сделал до конца одно, дальше. Как у нас с нодежс. Пишешь строчки и тоже по порядку, но не по такому порядку, как в php. К примеру у нас 2 обращения к базе. Они тоже будут идти по порядку, но почти одновременно, так как сразу после первого обращения к базе он не дожидаясь ответа обратится второй раз. Дожидаться ответа он уже будет в callback функции к обращению.

PHP - спокойный тип, который спокойно выполняет задачи и не запутывается. Nodejs - карьерист амфетаминщик, который в любое свободное время (к примеру, пока ждет ответа от той же базы) будет выполнять другие свои обязанности.
Ответ написан
Комментировать
@fattan Автор вопроса
программист
Итак. Спасибо за ответы. Я понял в чем дело. Т.к. программирую на node.js аж целых 2 недели, я неверно трактовал результаты. Изменил тест, и вышло вот что:

var start = new Date();

var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : '', 
  database : 'epr'
});


for (var i = 0; i < 1000; i++) {
	connection.query(
		'SELECT * FROM dreg_document', 
		function(error, result, fields){
			
			var str = '';
			
			result.forEach(function(row){

				str += ' ' + row.id + ' ';

			});
			console.log(str);
		}
	);
}

connection.end();

var end = new Date();
console.log('node.js %d мс', (end.getTime()-start.getTime()) / 1000);
	
client.send('qwerty');


Если думать по php-шному, после отработки всех запросов, отправляется сообщение клиенту -
client.send('qwerty');

Но на деле, сообщение отправляется тогда когда node-server отправит к БД ВСЕ запросы. Затем (! не дожидаясь ответа от БД) сервак отправляет клиенту сообщение. Клиент (браузер) подсчитывает время (вышло, к примеру 2 секунды для 100 000 итераций). А в это время в ноду продолжают поступать ответы от БД. Эти ответы мы видим с помощью
console.log(str);
И тут уже получаются совсем другие результаты....

Далее, изменяем скрипт следующим образом, чтобы подсчитать время выполнения от 1го до последнего асинхронного подключения к БД:
// начало выполнения скрипта
var start = new Date();
// счетчик обращений к БД
var ConnCountGlobal = 0;
// Число обращений к БД
var iLength         = 100;

var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : '', 
  database : 'epr'
});

for (var i = 0; i < iLength; i++) {
	connection.query(
		'SELECT * FROM dreg_document', 
		function(error, result, fields){
			
			// для последнего запроса вычисляем таймер
			if (ConnCountGlobal == iLength-1){
			
				var dateObj   = new Date();
				var currTime  = dateObj.getTime();
			
				console.log(' node.js - %d мс', (currTime-start.getTime()) / 1000);
			}

			ConnCountGlobal++;
		}
	);
}

connection.end();


Результат
Для 100 итераций 2.5 сек (что в 15 раз медленнее чем на PHP)

Промежуточный ответ на топик:
Node.js не быстрее PHP в 150 раз в вопросе доступа к БД.
Напротив, Node.js в этом плане в 15 раз медленнее чем PHP.
(это если брать оба сервера "из коробки", без улучшательств и настроек)

Новый вопрос:
Верен ли мой последний тест? Или я в нём тоже что-то не так сделал?
Ответ написан
Пригласить эксперта
Ответы на вопрос 8
Staltec
@Staltec
Node.js разработчик
Node-код в примере некорректен по отношению к поставленной задаче:
for (var i = 0; i < 100000; i++) {
  connection.query(
    'SELECT * FROM dreg_document', 
    function(error, result, fields){}
  );
}

Тут просто в синхронном цикле вызывается 100000 асинхронных запросов БЕЗ ожидания их завершения. Просто 100000 раз кинули запрос и закончили работу программы подсчитав время. Автор вопроса не понимает как работает node.js и в связи с этим неверно трактует полученный результат. Если ожидать каждого ответа на запрос к SQL-серверу, то результат будет совсем другим.
Ответ написан
nazarpc
@nazarpc
Open Source enthusiast
for ($i = 0; $i < 1000; $i++) {
    $result = mysql_query('SELECT * FROM dreg_document');
  }

Бессмысленно, и беспощадно. Вы слышали про кэширование запросов? Так вот только оно здесь и будет работать)

И ещё, вы об асинхронности слышали? Так вот, NodeJS асинхронный, в том числе с запросами к БД.
Ответ написан
@ollisso
мысли вслух:

PHP: mysql_query делает запрос и буфферизирует результат. в памяти.
Если делать это 1000 раз, то каждый раз сохраняется буффер. Можно надеяться что он опустошается после каждой строки, но это не 100%.

NodeJS: возможно это не делает, стоит добавить чтение этих строк в переменную.
Ответ написан
Melkij
@Melkij
PostgreSQL DBA
и который постоянно обновляется

Ха-ха. mysql_* фактически не поддерживается уже больше 10 лет с выхода PHP5.0.0 и появления mysqli.
Сравните с mysqli, тогда уже можно что-то думать.
Ответ написан
65536
@65536
$mtime = microtime();        //Считываем текущее время
$mtime = explode(" ", $mtime);    //Разделяем секунды и миллисекунды

// Составляем одно число из секунд и миллисекунд
// и записываем стартовое время в переменную
$tstart = $mtime[1] + $mtime[0];

=
$tstart = microtime(true);
Ответ написан
Комментировать
@kazmiruk
Как уже писали выше нода асинхронна, поэтому получилось и быстрее. Но это не значит, что она быстрее. Просто Вы не учли эту особенность при написании теста. Как работает тест в php:
цикл - (отправить запрос - подождать результат) - вывести время работы; как работает Ваш тест на ноде - цикл - (отправить запрос) - вывести время отправки всех запросов - начать получать результаты. Т. е. function(error, result, fields){} не попадает в замер.
Ответ написан
zoonman
@zoonman
⋆⋆⋆⋆⋆
PHP выполняет код синхронно, т.е. один запрос за другим.
Node.JS выпоняет запрос асинхронно, в данном примере параллельно.

for (var i = 0; i < 100000; i++) {
  connection.query(
    'SELECT * FROM dreg_document', 
    function(error, result, fields){}
  );
}

Я не рекомендую вам использовать выборки без ограничения.
Ответ написан
SWEBB
@SWEBB
Software Developer
Насчет PHP... Немного не честный тест ... Вы проверяли выполнение запроса на на платформе V8 ... Сервер как я понял на ноде вам был не к месту.. Поэтому логично было бы сравнить выборку из пхп через интерпретатор в консоли а не через браузер и HTTP сервер Апач, Нджинкс..
Как писали выше - обе технологии совершенно разные (асинхронные и синхронные) .. Но если хотите сравнить реально, то отключите кэши и все возможные надстройки, Апач и нджинкс никак не относиться к PHP...
К PHP вы добавили довольно солидный оверхед
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы