Pull to refresh
16
0

Пользователь

Send message
И конечно же в случае кластера вы не ставили nginx перед node…

Чтобы упростить задачу, у php-fpm снизьте до 1 server-start (и 0 чилдов), потому что у вас в 5 раз больше php обработчиков (которые работают как треды, а не как воркеры), а результат всего на 23% лучше, что говорит не в пользу php
Уже проверяла, разница минимальна, но в данном тесте это не играет роли, по причинам которые выше написала
Нет, промисы дешево стоят, не сильно дороже callback (особенно если использовать bluebird)

Вы закрыли соединение до того, как промисы успели обратиться к базе. Поэтому они выкидывают сообщения об ошибках, а не тестируют соединение. А вот выкидывать сообщения об ошибках уже более дорогая операция, чем соединение
У вас та же проблема что и у автора, вот тут правильное сравнение с теми же тестами, но уже не пользу php:
https://habrahabr.ru/post/320670/#comment_10039552

Тесты в цикле нельзя просто прогнать, нужно еще результат запомнить и прочитать его после цикла, иначе оптимизатор просто выкинет половину из цикла, или вовсе схлопнет цикл
Из статьи видим, что php это делает более агрессивно чем js, достаточно добавить немного «логики» в вычисления и php уже отстаёт
Хоть wrk, хоть ab (которые действительно надо запускать не на тестируемой машине, а на удаленной)
Автор всё равно сравнивает 5 тредов php-fpm против 1-го в ноде
Нужно либо ноду в кластере запускать, либо у php-fpm дефолтные настройки снизить

https://habrahabr.ru/post/320670/#comment_10039552
Автор сравнивает 5 тредов php-fpm против 1-го в ноде
Нужно либо ноду в кластере запускать, либо у php-fpm дефолтные настройки снизить

https://habrahabr.ru/post/320670/#comment_10039552
Если добавить немного «логики» в вычисления, и запоминать результат вычислений, то разница уже не в пользу php (кроме ассоциативного массива, с которым в js всегда было не очень хорошо, и на замену сейчас рекомендуется использовать Map там где критична скорость)

node 7.3.0
test1 (str): 67.853ms
str len: 1000000 sb

test2 (sum): 8.685ms
sum: 2500000

test3 (array): 53.455ms
array len: 1000000 z

test4 (obj): 1036.474ms
obj1: b
obj2: a

test Map: 575.344ms
obj1: b
obj2: a

php 7.1.1
test1 (str): 83.961ms
str len: 1000000 sb

test2 (sum): 69.857ms
sum: 2500000

test3 (array): 63.453ms
array len: 1000000 z

test4 (obj): 206.375ms
obj1: b
obj2: a


для js например
let intns = 1000000

console.log(`\n`)
console.time('test1');
var str = '';
for (var i = 0; i < intns; i++) {
	if (str.length % 2 === 0) {
		str += (i % 2 == 0) ? 's' : 'z';
	}
	else {
		str += (i % 2 == 0) ? 'a' : 'b';
	}
}
console.timeEnd('test1');
console.log('str len: ' + str.length + ' ' + str[0] + str[intns - 1])

console.log(`\n`)
console.time('test2');
var count = 0;
for (var i = 0; i < intns; i++) {
	if (count % 2 == 0) {
		count += (i % 2 == 0) ? 1 : 2;
	}
	else {
		count += (i % 2 == 0) ? 3 : 4;
	}
}
console.timeEnd('test2');
console.log(`sum: ${count}`)

console.log(`\n`)
console.time('test3');
var array = [];
for (var i = 0; i < intns; i++) {
	array.push((i % 2 == 0) ? 's' : 'z');
}
console.timeEnd('test3');
console.log(`array len: ${array.length} ${array[intns - 1]}`)

console.log(`\n`)
console.time('test4');
var obj = {};
for (var i = 0; i < intns; i++) {
	obj['s' + i] = (i % 2 == 0) ? 'a' : 'b';
}
console.timeEnd('test4');
console.log(`obj1: ${obj['s' + (intns - 1)]}`)
console.log(`obj2: ${obj['s' + 0]}`)

console.log(`\n`)
console.time('test Map');
var objMap = new Map();
for (var i = 0; i < intns; i++) {
	objMap.set('s' + i, (i % 2 == 0) ? 'a' : 'b');
}
console.timeEnd('test Map');
console.log(`obj1: ${objMap.get('s' + (intns - 1))}`)
console.log(`obj2: ${objMap.get('s' + 0)}`)


аналогично для php
<?php
$phpVersion = "v" . explode('-', PHP_VERSION)[0];
$intns = 1000000;

$start = microtime(1);
$str = '';
for ($i = 0; $i < $intns; $i++) {
	if(strlen($str) % 2 == 0) {
		$str .= ($i % 2 == 0)  ? 's' : 'z';
	}
	else {
		$str .= ($i % 2 == 0)  ? 'a' : 'b';
	}
}
echo "test1: " . round((microtime(1) - $start) * 1000, 3) . "ms \n";
echo "str len: " . strlen($str) . ' ' . $str[0] . $str[$intns - 1] . "\n";
echo "\n";

$start = microtime(1);
$count = 0;
for ($i = 0; $i < $intns; $i++) {
	if($count % 2 == 0) {
		$count += ($i % 2 == 0)  ? 1 : 2;
	}
	else {
		$count += ($i % 2 == 0)  ? 3 : 4;
	}	
}
echo "test2: " . round((microtime(1) - $start) * 1000, 3) . "ms \n";
echo "sum: " . $count . "\n";
echo "\n";

$start = microtime(1);
$array = array();
for ($i = 0; $i < $intns; $i++) {
	$array[] = ($i % 2 == 0)  ? 's' : 'z';
}
echo "test3: " . round((microtime(1) - $start) * 1000, 3) . "ms \n";
echo "array len: " . count($array) . ' ' . $array[$intns - 1] . "\n";
echo "\n";

$start = microtime(1);
$obj = array();
for ($i = 0; $i < $intns; $i++) {
	$obj["s" . $i] = ($i % 2 == 0)  ? 'a' : 'b';
}
echo "test4: " . round((microtime(1) - $start) * 1000, 3) . "ms \n";
echo "obj1: " . $obj["s" . ($intns-1)] . "\n";
echo "obj2: " . $obj["s" . 0] . "\n";
echo "\n";



На счет веб-сервера. У php-fpm не указаны настройки пула, по умолчанию у него 5 тредов
У ноды естественно 1

Либо у php надо понизить до 1, либо ноду как кластер запускать:
чуть больше строчек требуется
var cluster = require('cluster');
var http = require('http');
var numThreads = 5;

if (cluster.isMaster) {
    for (var i = 0; i < numThreads; i++) {
        cluster.fork();
    }
} else {
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end('process ' + process.pid + ' says hello!');
    }).listen(8000);
}



Но всё равно учитывая как взялись за php7, рано или поздно это может случиться
Просто v8 сильно оптимизирует работу с обычными, не ассоциативными, массивами
В статье совсем правильная вводная. Это не совсем новый язык, никто не будет писать на wasm
wasm это в первую очередь бинарный формат который должен заменить asm.js, с нормальной работой с памятью и т.д. Вы пишите код на любой языке который поддерживает LLVM, компилируете код в wasm и получившийся модуль подключаете как любой другой скрипт

По этому примеры не несут никакого особого смысла, всё что работало для asm.js, будет работать и для wasm
У wasm есть человеко читаемое представление, но и там смотреть особо не на что:

image

Всё так и есть, не поспорить
Но async-await всё равно удобные. Удачно удалось сократить один модуль на промисах, переписав его на async-await, на 40%, и добавлять в него новый функционал стало проще и приятнее ^__^
Их не надо заворачивать в try-catch, потому что верхний try-catch поймает все исключения ниже
В примере с new Array(10000) смысл ускорения не в том, что аллокаций нет, а в том, что массив заполнен и в цикле на 100000 итераций данные берутся уже готовые без вычислений

Я, для чистоты эксперимента, привела пример кода когда этот «недостаток» исключен, чтобы показать, что динамическое добавление в объект снижает производительность, но совершенно не критично, чтобы помнить об этом

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

Поэтому прощу прощения, я бы с удовольствием обсудила реальные проблемы деоптимизаций, а не проблемы с недостатком мастерства или проблемы алгоритмов

Когда рассуждения на таком уровне идут, мне всегда вспоминается история как компания вложила много денег и времени чтобы ускорить код на golang v1.4, ничего путного не получилось, а потом вышел golang 1.5 и всё ускорилось само собой в 28 раз
Но JavaScript не Haskel. Вот простейший пример. Разница в производительности в 2600 раз.
И это в 2600 раз ускорение внесло лишь 1% к общему ускорению

Полагаю, что в обоих случаях вы увидите в своих тестах заветное «optimized»
Если бы функция была deopt, то даже дикие ухищрения с алгоритмом вам не помогли бы ее разогнать, только хаки для браузера

Ещё как относится
Можно сортировку делать пузырьком и приговаривать «Ах этот v8, не разогнал мой код»

Прощу прощения, не могу больше поддержать разговор на эту тему
если у вас серьёзные требования к производительности, то с объектами в JavaScript нужно работать с умом

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

Те или иные оптимизации не означает написать for(var i = 0, l = arr.length; i < l; i++) {...}, это означат уменьшить выделение памяти, оптимизировать работу путем линейного выделения памяти, уменьшить количество вызовов и т.д.
И снова вы про плохие алгоритмы, а не про «убийц оптимизаций» в рамках статьи

покажите код, давать результаты тестирования в абсолютных значениях и без кода нет смысла. динамически менять свойства объекта это моветон, а не удобство, программист ожидает одну форму объекта, а у вас приходит другая так как вы где-то динамически что-то поменяли.
Вот код из соседней темы про wasm:
https://habrahabr.ru/company/ruvds/blog/319834/#comment_10020032

Усложним немного код оригинала, чтобы было еще очевиднее факт динамического добавления в объект:
const fiboJsMemo = (num, memo) => {
  memo = memo || function(){return 'hello'}

  if (memo[num]) return memo[num]
  if (num <= 1) return 1

  return memo[num] = fiboJsMemo(num - 1, memo) + fiboJsMemo(num - 2, memo)
}


Проверим на 100000 итераций, попутно с вариантами для Map и Set:
time for fiboJsMemoDynamicObj: 160.85888671875ms
time for fiboJsMemoArray: 112.782958984375ms
time for fiboJsMemoMap: 470.0009765625ms
time for fiboJsMemoSet: 175.534912109375ms
fiboJsMemoResult: 1100000
fiboJsMemoArrayResult: 1100000
fiboJsMemoMapResult: 1100000
fiboJsMemoSetResult: 1100000

Код целиком: http://codepen.io/anon/pen/vgZoWe

Разница между динамическим добавлением свойств и отсутствием всего 48-100мс

То о чем вы говорите, это снова про плохие алгоритмы и плохо продуманную архитектуру приложения. Это можно отнести к совершенно любому языку, даже с типизацией и отличным компилятором

А вся статья (эта и оригинальная) совершенно не про плохие алгоритмы
И таким программистам просто необходимо заморачиваться на даже 10% прирост производительности
Точно необходимо? Создатели AAA игр с вами не согласны, создатели http://slither.io/ с вами не согласны и т. д.

Вот вы потратили 90% времени разрабатывания вашей игры выискивая оптимизации для специфичной логике работы браузера, чтобы выжать fps на 10% больше, через неделю выходит оптимизатор который изменил логику работы и вектора больше не являются проблемой и ускорились на 30%, в обоих случаях это внесло 3.5% к результирующей производительности. А потом выясняется, что другие браузеры и вовсе по другому ведут себя с этой логикой.
И в итоге игра не готова, и ваши оптимизационные хаки оказались не так хороши

Вы ведь наверняка поняли о чем статья. Браузерные хаки ускоряющие не нужны, которые приводили к деоптимизации, а не то, что теперь можно плохие алгоритмы использовать, а v8 за вас все разгонит
С вашим нет я не соглашусь. Для UI нет, для игр и вычислений — да. Каждому свое.

То, что вы пишете на нем сложным путем, не делает его сложным и медленным для нормального использования (и игры и вычисления сюда входят)

в любом случае это уже свыше 20% запустите это в цикле и будет вам счастье

Это и было в цикле на 1000000 итераций. Выигрыш в 40мс на 1кк итераций — это не та «награда», которая компенсирует неудобство при написании js кода

Вы так и не поняли про что статья, то что вчера было медленным, завтра будет в 50 раз быстрее без вашего вмешательства. И не факт, что вы закончите проект раньше, чем выйдут новые оптимизации
По сути я ответил чуть выше
Именно это я и назвала «Вы теряете суть и уходите в крайности»

В вопросах производительности js очень сложный язык
Нет

Я вам как раз и говорю, что изучать оптимизации не нужно, эвристики для vm меняются часто, но вот принципы работы остаются на долго
Вы не это говорите, перечитайте ваши комментарии
Вот так как раз делать нельзя так как создаются новые скрытые классы для этих объектов и потери производительности значительны.

Именно так, и я проверила как это влияет на производительность, вместо 140мс, код выполнился за 180мс, добавляла 20 свойств динамически

Вы теряете суть и уходите в крайности. Вспоминать что у const и let были проблемы в рамках этой статьи странно. Генераторы тоже оптимизируются, как и async-await
function* exampleFunction() {
  yield 1;
  yield 2;
  return 3;
}

Function is optimized by TurboFan: exampleFunction


Может получится так, что пока вы скрупулезно разбираетесь с тем какой тут нужен хак для ускорения, оптимизатор обгонит вас, а вы останетесь с ворохом знаний которые уже не актуальные и не будут актуальны

Куда важнее понимать принципы программирования в целом, чем изучать устаревшие оптимизации
Я понимаю вашу позицию, но не могу с ней согласиться

Код может оптимизироваться и так и эдак но работать совершенно с разной скоростью
Даже на самом быстром в мире языке можно написать код, который будет тормозить, и найдется тот, кто напишет его еще более медленным способом

Есть всего 3-5 простых некритичных правила, чтобы js-код не страдал потерей производительности:
1. Не переназначать переменные другим типом
2. Мегаморфизм функций
3. Не добавлять динамически свойства в объект
4. for быстрее forEach
5. Большое количество конкатенаций мелких строк (например, посимвольно) ведет к перерасходу памяти

Решение:
1. использовать const
2. редкое явление
3. потери производительности незначительны
4. использовать for..of
5. использовать arr.push вместо +=

Нужно понимать, как работает vm
Не нужно, vm это черный ящик, сегодня он так работает, завтра по другому

чтоб его ускорить приходится расписывать его некрасиво и дублировать конструкции
Раньше делали inline asm вставки в С код, сейчас чтобы сделать inline вставку, которая будет быстрее, чем clang заоптимизирует, настолько сложно, что этим мало кто занимается

Вы предлагаете заниматься тем же для js, ускорять то, что не внесет даже 0.1% в итоговую производительность, а может даже замедлит
Это всё интересно (знать про внутреннее устройство, про оптимизации, про ускоряющие хаки), но нужен взгляд и с другой стороны

Сейчас парадокс языка в том, что красивый код обычно означает медленный код
Наоборот, именно сейчас можно писать компактный, красивый, с async-await код, который будет быстрым, который удобно писать и понимать

Information

Rating
Does not participate
Location
Дания
Registered
Activity