Как стать автором
Обновить

Комментарии 160

Интересное сравнение… Правда мне кажется тут не совсем уместен Java
Вы не могли бы пояснить свою точку зрения, почему считаете что Java тут неуместна?
НЛО прилетело и опубликовало эту надпись здесь
Правда мне кажется тут не совсем уместен Java

Не знаю на повод java...

Зачем тогда вообще Java упоминаете? Если про нее ничего сказать не можете…
Поспешил с ответом. Не обратил внимание что ответ от другого человека.
Потому-что считаю что Java к вебу очень косвенно относится… Тут был-бы уместен Python
..Java к вебу очень косвенно относится

Тут вы ошибаетесь

Посмотрите хотя бы:
https://en.wikipedia.org/wiki/Programming_languages_used_in_most_popular_websites

Да разнообразие и популярность фрейморков для веба в Java говорит об обратном:
Spring, Dropwizard, Spark, Vert.x и т.д.

Вы на Java и не пишите похоже

Ну именно на Java я не пишу, я сейчас Kotlin штрудирую третий месяц

Загляните за обратную сторону Луны — там Web и Java почти синонимы. N-лет назад был популярен GWT, Джавнее уж некуда. Web-пауки пишут на Java в том числе.

Я почему-то всегда думал что Python популярнее Java в плане веба
НЛО прилетело и опубликовало эту надпись здесь
Действительно, есть cli, fpm
Принципиальной разницы не будет: все равно 1 процесс (пусть и реиспользуемый) на 1 запрос.
НЛО прилетело и опубликовало эту надпись здесь
что попробовать?
То, что фпм работает в целом быстре, чем пхп как модуль апача — это общеизвестный факт. Но на принцип работы (который автор указал в результирующей таблице) это никак не влияет.
Каждый запрос так или иначе будет выполняться в своем процессе. Неблокирующего i/o нет.

Я php ни в чем не обвиняю, если что. Просто применительно к этому тесту принципиальной разницы между fcgi vs mod_php не будет.
А как именно он быстрее модуля работает? Там какой-то принципиально другой более быстрый код?
Правильнее указать, что связка nginx + php-fpm работает быстрее (не намного и не всегда) и меньше памяти потребляет, но это не заслуга php-fpm, а nginx. Применительно к этому тесту грамотно настроенный nginx + php-fpm на третьем графике позволит получить лучший результат.

А вы знаете, что обозначает FPM? Помнится делал бенчмарки и apache+php-fpm показывал лучшие результаты чем apache+mod_php

Fastcgi process manager. Слово "Fast" здесь — часть названия протокола взаимодействия с веб-сервером, и оно само по себе не означает более быструю работу, если вы намекали на это.

Имеено, протокол взаимодействия. Нет, намекал я на то, что скорость работы php-fpm не зависит от того, apache или nginx перед ним.

Это менеджер процессов FastCGI, который в связке с апачем в принципе не может быть быстрее модуля. Если у вас есть результаты исследований, то прикладывайте пожалуйста ссылку на них.

В принципе как раз может: ОС не нужно форкать apache+mod_php, а только apache.


Результаты в другой стране и не актуальны — php5.2 емнип там был

А вы знаете что означает prefork? Тесты от боевого сайта могут очень сильно отличатся, в реальных условиях при верной настройке лишних форков не будет.

Знаю, но это уже про администрирование, а не про разработку.

Чукча не читатель?
в связке PHP + Apache при большом количестве подключений доминирующим фактором становятся удельные накладные расходы, связанные с созданием новых процессов и выделением им памяти, что негативно влияет на производительность PHP

Это серьёзное обвинение и, как говорится, needs to be backed with hard numbers.
А дефолтная конфигурация sudo apt-get install lamp-server^ никак не тянет на hard numbers…

UPD: А! Он ещё ПХП 5.4 использовал! 2017 год на дворе, блжад!

Наверно потому же, почему и Java тестировали на сервлетах, хотя есть Grizzly/Netty. Типа это более популярно. Хотя если кто-то только смотрит на финальные каритинки, не читая текст, в надежде выбрать более "крутую" технологию для нового проекта, то может сложиться немного неадекватное предстваление. Ведь и на PHP, и на Java можно сделать оптимальнее. Даже касательно Node.js, если задача напряжная для CPU (как здесь — подсчёт контрольных сумм), то можно запустить несколько процессов и баллансировать между ними nginx-ом/haproxy/etc. Это позволит загрузить все ядра процессора. Так сравнивать некорректно. Но Go всё же рулит.

Образец для тестов PHP был без использования reactphp, насколько я понял?

И без HHVM. ReactPHP под HHVM показывает совсем другие цифры:)

Ну HHVM это всё же допиленный PHP, а react — просто php-библиотека.

Между 7 и hhvm на базе 5.6 критической разницы не заметил, кстати.

НЛО прилетело и опубликовало эту надпись здесь

Я говорил о ReactPHP. После прогрева его JIT компилятор показывает очень интересные результаты, которых может не быть при использовании в более традиционном сценарии использования.

Какой ещё JIT-компилятор у reactphp, это просто набор PHP-классов?
hhvm с ядром 5.6 от php 7.0.x отличается на пару процентов даже с прогревом.

JIT компилятор в HHVM, он хорошо проявляет себя когда функции вызываются без перезапуска много раз, что и происходит при запуске HTTP сервера с ReactPHP поверх HHVM.


Не знаю о каком ядре 5.6 идет речь, HHVM поддерживает обе версии одновременно с некоторыми нюансами.

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


На момент теста поддержки 7 у hhvm ещё не было, 7 только релизнулась.

Сравнение производительности на Apache2? Почему не Nginx?

Для Nginx выпустили ngx_http_php_module? Можно ссылку? А то на официальном сайте никаких упоминаний…

А модуль-то вам зачем О_о? Есть же php-fpm.

Ну, вы же спросили про Nginx… Если бы вы спросили:
Сравнение производительности на Apache2? Почему не php-fpm?
, то и я, наверное, не полез бы со своим сарказмом…
php-fpm или apache — это выбор между тем, кто будет запускать php. А nginx может стоять перед любым из них.

Apache вполне поддерживает php-fpm.

Нас сейчас тут совсем заминусуют хранители святого грааля «nginx + php-fmt»…
Да, я тоже некорректно выразился — под «apache» я подразумевал «apache+php_module». И да, согласен, можно перед php-fpm поставить и apache (с fast_cgi модулем) вместо nginx, только лучше выбрать mpm event или worker. Правда, я большой разницы в производительности на своих неправильных тестах не увидел, единственное — apache больше оперативки съел.
… и Java есть реализации неблокирующих вводов/выводов, доступных для использования в веб-приложениях. Но они не так распространены, как вышеописанные подходы..

Это спорное утверждение. И, как мне кажется, если привести статистику с неблокирующими вызовами на Java то она будет уж точно не хуже Go (а может даже лучше).
Netty не чисто на Java написан, там и нативного кода хватает (насколько я знаю)
неправильно знаете =)

нативный код может быть в 2 случаях:
1) если вам не нравится стандартный java nio вы можете попросить epoll из линукса
2) если не устраивает скорость ssl в java и вы используете обертку поверх openssl

во всех остальных случаях чистая java которую хоть на android запускай.

в 99% использований нетти всегда укладываются в стандартную java.
Ну давайте сходим и посмотрим https://github.com/netty/netty
Давайте:
https://github.com/netty/netty/tree/4.1/transport-native-epoll
https://github.com/netty/netty/tree/4.1/transport-native-kqueue
https://github.com/netty/netty/tree/4.1/transport-native-unix-common
xhumanoid сверху уже ответил, что в проекте действительно по сути одна только Java. Но все же в репозитории полно нативного кода.
1% если точнее =) а то у людей может сложиться предвзятое отношение после слова «полно»
Все эти модули являются необязательными. netty вполне работает и без них.
А уж если использовать github.com/valyala/fasthttp, то вряд ли получится догнать го в любом бенчмарке :)
Где-нибудь уже сравнивалась производительность? Есть публичные бенчмарки? Вы сами сравнивали производительность с аналогичным решением на других языках?

Просто поражает, откуда такая пустословная уверенность в быстроте go…
Go шустрая, но отнюдь не панацея от всех бед. Java, c#, c++ и прочие тоже не пальцем деланные.
Если говорить именно о том, что с fasthttp будет сильно круче, то не уверен, несколько быстрее будет. Fasthttp выделяет намного меньше памяти и соответственно GC меньше съест. Правда код на нем, по личному опыту, трудно поддерживать: неинформативные ошибки, попытка почитать код приводит к чтению функций по 200-400 строк…
Бенчмарки можно посмотреть тут
Слишком устаревший, php7 нет, максимум php5.
эээ нет. попробуйте навести на строчку вроде php-raw: «PHP-raw [php-raw7] (None; nginx on Linux; MySQL on Linux; Raw database connectivity, Platform class; Realistic approach) [Test #475]»
Спасибо, теперь вижу. Искал по ctrl+F php7, поэтому не нашёл.
Странно, что оно там медленнее php5.
Просто поражает, откуда такая пустословная уверенность в быстроте go…

Скорее всего, потому что из коробки go и правда быстрее. Как минимум потому, что впитал новые идеи, в то время как старые языки базируются на старых. Просто проблема в том, что люди, которые работают с языком (например, Java) знают, что решения, которые из коробки предлагает Java в основном не используются, если вам нужна скорость, но зато используются во всех туториалах и там, где не особо важна скорость чтения (например, десктопное приложение).


А когда кто-то пилит такой бенчмарк, то ищет мануалы и находит решения из коробки.

Наличие новых идеи в языке совсем не значит, что runtime будет работать быстрее. И напомню, что самые производительные решения пишутся на дедушка (c,asm). К тому же с чего вы взяли, что Java не используется, если вам нужна скорость? Скорость чего? Старта? Отклика? Каков критерий то?
Я боюсь спрашивать у автора бенчмарка, а сколько у Java потоков работало? И почему не взяли netty, который является монстром по обработке, который написан на чистой java?

P.S.На мои взгляд сравнение совершенно некорректное.

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


А в случае с go, используется стандартный функционал go, который написан с учетом идей, которые использовали те же библиотеки на java, например.


Скажем, если сравнивать работу с потоками с Java c Go из коробки быстрее на Go, потому что на Java нет легких потоков. Я не прав?

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

Давайте будем объективными. Java thread мапится 1 к 1 на native thread. А что происходит под капотом go я не знаю, но думаю что все равно вся магия горутин посроена вокруг threads. В java вам тоже никто не мешает взять какой-нибудь ForkJoinPool и делать execute на какие-нибудь задачи, что по сути тож самое)

Или использовать netty/akka-http/undertow/mina или более высокоуровневый vert.x, например. И в процессе шедулить задачи как принято в конкретной библиотеки на FJP или обыкновенный ThreadPool.


У Go обычно фиксированное число потоков, так что если загрузить их достаточным количеством cpu-bounded работы он будет не сильно отличаться от nodejs или java в аналогичных условиях.

Ну, честно говоря, публичных бенчмарков у fasthttp хватает. Например вот:

https://github.com/valyala/fasthttp/tree/master/examples/fileserver

fasthttp, например, в полтора раза быстрее nginx при раздаче файлов :)
https://github.com/valyala/fasthttp/tree/master/examples/fileserver

Ну себя они в плохом свете точно выставлять не будут…

Я не против этого сервера, как и не против Go. Просто с трудом верится в такой разрыв, по сравнению с nginx, и других бенчмарков быстро не удалось найти…
Ну так вам же скинули огромный и очень экстенсивный бенчмарк: https://www.techempower.com/benchmarks/#section=data-r14&hw=ph

Там очень много разделов и частей, и во многих случаях fasthttp выигрывает, ну или по крайней мере занимает топовые места.
Ну, кстати, в этом бенчмарке light-java обходит во многих случаях fasthttp. Nginx, да, проигрывает.
Но все же хотелось бы видеть чистое сравнение на разных нагрузках, разных количествах одновременных подключений и т.д.

А каким образом NodeJS может быть быстрее Lua(JIT)? Или я чего-то не знаю?

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


NodeJS по умолчанию использует интерпретатор v8, который тоже относится к классу JIT

Я многого не понимаю в веб приложениях, но зачем нам там много операций чтения в них?

Смысл подобных статей непонятен, ежу понятно что GO будет быстрее, ведь он специально разработан для решения таких задач.
… ведь он специально разработан для решения таких задач

Не аргумент.

В этой статье весьма спорное решение использовалось для других языков, в частности для Java. Либо приведите конкретные пруфы, либо не бросайтесь словами.
на что нужны пруфы?
и где я бросаюсь словами?
ежу понятно что GO будет быстрее

Чем можете подтвердить это утверждение?
прочтите что я написал, максимум что можно требовать это пруф на «он специально разработан для решения таких задач», вот
https://golang.org/doc/faq#What_is_the_purpose_of_the_project
Go is fully garbage-collected and provides fundamental support for concurrent execution and communication.
By its design, Go proposes an approach for the construction of system software on multicore machines.


«ежу понятно что GO будет быстрее» следует из логики, инструмент заточенный под конкретные условия будет быстрее, банально потому что оверхеда меньше, то что другие инструменты создавались под другие условия общеизвестно, наследственность давлеет над ними несмотря на многолетнее развитие.
Пруфы на условия
PHP — https://en.wikipedia.org/wiki/PHP
Java — https://en.wikipedia.org/wiki/Java_(programming_language)
Node.js — https://en.wikipedia.org/wiki/Node.js

На всякий случай даю пруф на логику — https://en.wikipedia.org/wiki/Logic
инструмент заточенный под конкретные условия будет быстрее, банально потому что оверхеда меньше

Из того что инструмент заточен под конкретные условия еще ничего не следует. Это лишь говорит о том на что будут направлены усилия разработчиков, но никак не о том что получится в итоге.
наследственность давлеет над ними несмотря на многолетнее развитие

Она же еще и позволяет убрать кучу детских болячек и вылизать все технические решения

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


выражение — инструмент заточен — означает что он уже соответствует заданным условиям а не когдато будет.

наследственность давлеет над ними несмотря на многолетнее развитие

Она же еще и позволяет убрать кучу детских болячек и вылизать все технические решения


выражение — наследственность давлеет — означает что есть что-то с чем приходится мирится а не исправлять. исправление возможно если выкинуть существующее и написать заново но это уже не наследственность.

так что логику надо еще подкачать.

Почему для Node.js не был задействован модуль cluster? Это как бы изкоробочная функциональность.


Про ReactPHP уже говорили (кстати, без кластера он должен был показать во втором тесте столь же плохой результат что и нода).

ну да
кстати, не сказано, сколько ядер в машине тестовой
и было бы логично создать столько же форков на ноде и распределить нагрузку между ними, хотя я где-то и такой бенчмарк уже видел
НЛО прилетело и опубликовало эту надпись здесь
Наилучшая связка для классических задач Apache + Nginx одновременно.
НЛО прилетело и опубликовало эту надпись здесь
Интересно минусют ) Мы с админами проводити тесты настроек, nginx побеждал в отдаче статических файлов, а apache помогал выживать под сильной одновременной нагрузкой, когда nginx возращал ошибки.
node.js поумолчанию использует только один процессор.
Получается что графики иллюстрируют сравнение 1-го ядра для node.js против 4-х для всех остальных языков :(
(посмотрел исходники по ссылке из статьи )
GO тоже использует один логический процессор по умолчанию. В примерах кода этот параметр не изменялся. Так что он тоже работает на одном ядре). Дабы распараллелить выполнение задач требуется установка GOMAXPROCS.

У вас какие то устаревшие сведенья, уже давно (вроде с 1.5) по умолчанию GOMAXPROCS равно кол-во CPUs.

Перепроверил, действительно сведения явно устаревшие, спасибо за информацию. Насколько я помню, дефолтное значение в 1 логический процессор использовалось в связи с тем, что при увеличении количества ядер увеличивались накладные расходы на общение и переключение контекстов. Эта проблема еще актуальна?
Немного не верное утверждение. Сейчас по дефолту GOMAXPROC=NUMCPU.
Я буду обновлять комментарии перед отправкой. Я буду обновлять комментарии перед отправкой. Я буду обновлять комментарии перед отправкой.

Это я пропустил, или автор в самом деле сравнивает перфоманс:


  • многопоточной непрогретой JVM, с JSP в Томкате
  • PHP, который сидит за непонятным дефолтным конфигом Apache (в целом тоже многопоточном)
  • и однопоточную node.js
это да.
мэил ру в этот раз село в лужу с переводом не очень качественной статьи.
Не увидел сразу, что это мэйлы. Да уж, как-то неловко за них даже.
НЛО прилетело и опубликовало эту надпись здесь
Конечное спорное сравнение, могу прокоментировать nodejs, отдача файла должна была быть потоком, а не чтение в буфер, а потом его преобразование в string и отдача по сети (тут оверхеад на лицо). А второе это циклы, они должны быть неблокирующие через функции/лямбды, будет падение производительности в этом случае, но блокировок не будет. Ну про встроенную возможность кластерности я молчу. Я не знаю какая была цель теста, можно представить что это было условие. Резюмируя: nodejs выжрет оч. много памяти, но произвоительность будет как у java (сейчас как раз оптимизирую высоконагруженный сервис, переписывая части на java).

Ничего из перечисленного вами (кроме кластера) не поможет в CPU-bound задаче (тест 2), скорее даже помешает.

Я ничего не писал про конкретные тексты, как вы заметили. Что из написаного мною не является истинной? Что странно приводить буфер к строке и отдавать его, а на яве открывать стрим? Или то что циклы for (> 1000 элементов) нельзя использовать в ноде?

Зато я писал про конкретный тест.


Сильнее всего нода просела именно во втором. И именно там ваши предложения лишь замедлят работу.

Мой коммент был не защита ноды. Ну мы же хотим правдивый тест? Разумеется перебор массива for-ом на одном ядре это для ноды плохо, а при миллионах элементов — еще и смерть, но что уж тут поделаешь. Мне кажется лучше сравнивать рабочие варианты.

Когда нас интересует лишь средняя производительность, а не время отклика, или же когда все задачи одинаковые — то как раз перебор массива for-ом оказывается наилучшим способом даже на одном потоке.

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

Да какая разница сколько подключений блокировано, если задача — cpu-bound? Ее физически невозможно выполнить быстрее чем она уже выполняется!

Да разница большая, имеем 1000 подключений одновременных, в случае с блокирующим for наш сервер отвечает одному или нескольким, остальные отваливаются по таймауту, в случае «неблокирующего for» мы отвечаем медленно, но всем.

Как можно отвечать "медленно, но всем", когда ответ — это 64 байта плюс заголовки?

А как мы ответим "медленно, но всем"? Допустим у нас такие условия: у нас есть 10 входящих реквестов, каждый реквест выполняет цикл длительностью 1 сек, таймаут на ответ = 9 сек. При таких условиях 1й клиент получит ответ через 1 сек, 2й — через 2 сек… 10й клиент получит таймаут. Если мы делаем одновременное выполнение всех запросов, то исполниться они должны примерно одновременно, т.е. все через 10 сек, т.е. все клиенты получат таймаут. Или разве не так?

freeart
оффтоп вопрос
Не доскажите как лучше поступить? Есть node сервер, при определеном запросе нужно запустить node функцию (к примеру) которая будет выполнять синхронные операции с файловой системой (из за того что это может подвесить основной сервер, нужно запустить это в отдельном процессе). Как это красивее сделать?
Сейчас это выглядит так:

//fnc.js
function fileSystemOperation() {
//...
}

const proc = cp.fork("./fnc.js", [args], {
       execArgv: []
});

и дальше через process.send комуникация. Не подскажите более просто решение?



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


А операции совсем дорогие, можно подумать про какую-нибудь очередь, живущую вообще отдельно от сервера.

Да, там не стандартные операции из fs которые можно использовать асинхронно.
Спасибо за ответ.
Существует ряд вариаций, но среднестатистический PHP-сервер выглядит так.
От пользовательского браузера поступает HTTP-запрос на ваш веб-сервер Apache.


Я знаю, что такой комментарий уже был выше. Но повторюсь: дальше нет смысла читать. Никакого. Автор весьма далек от современной разработки на PHP.

Плюс еще автор умудрился взять самую, пожалуй, старую доступную ему конфигурацию тестового стенда: «PHP v5.4.16; Apache v2.4.6» А что не PHP 4 сразу?

Берем Форд модель Т и Volvo XC90. Устраиваем гонки. Вольво выигрывает. Форд — дрянь? ))
Поддержу. Такое ощущение, что человек, либо абсолютно далек от php, либо специально подогнал окружение под желаемые результаты.
хотябы php7.x + php-fpm + nginx.
не говоря уже про react/php-pm/swoole
Думаю, что это специально сделано. Слишком велик был соблазн включить время, затраченное на дорогущий форк процесса Апача в общее время тестов и показать, насколько плох PHP.
Уверен, что там еще и префорк на нуле специально был, иначе сложно объяснить смысл последнего графика.
НЛО прилетело и опубликовало эту надпись здесь
Надо. Например, уже есть бенчмарк reactPHP vs node: https://gist.github.com/nkt/e49289321c744155484c. ReactPHP проигрывает раз в пять (а не в два раза, как в посте).
Если верить другому бенчмарку (http://marcjschmidt.de/images/reactphp-benchmark-requests.png), то react может работать наравне обычного hhvm или phpfpm+nginx.
Если верить третьему бенчмарку (http://hostingadvice.digitalbrandsinc.netdna-cdn.com/wp-content/uploads/2015/03/nodejs-vs-php-performance-requests-per-second.png), то php 5.5 + opcache сильно медленнее ноды, а hhvm — наравне.

По большому счёту, быстрый гуглинг говорит о том, что кардинально картина не меняется от манипуляций с reactphp, поднимая результаты максимум в два раза (неважно, используется react, hhvm или php7+opcache+php-fpm).

Но тогда и для Golang вместо net/http делать fasthttp (что на порядок быстрее может быть, чем обычный net/http).

НЛО прилетело и опубликовало эту надпись здесь
раз на то пошло, давайте addon-ы на Си писать для ноды)
кстати, я как раз редко встречаю такую практику, даже в яндексе на ноде пишут простенькие http-рендеры, тяжелые операции выполняются на java
Навреное потому, что обычно на ноде пишут сервисы, суть в которых минимальная обработка данных(циклами, хэши считать), и по максимуму работа с I/O.
но в некоторых npm библиотеках встречал node-gyp зависимости, и однажды проект не установился, когда gcc был версии меньше 4.4, требовал 4.8. Видимо, в узких местах пишут на Си.
НЛО прилетело и опубликовало эту надпись здесь
Swoole — сишный сервер для пхп? Тогда пхп становится просто языком сценариев для этого сервера в асинхронной среде.
С таким же успехом к ноде можно прикрутить серверную часть от nginx(это будет просто — у обоих асинхронщина в крови, оба на этом взлетели), ой, тогда получится lua script для nginx). Но и этим никто не заморачивается в ноде, она и так прекрасна — сетевой стек весь на js, полный контроль над соединением начиная с tcp.

Ой. Что я вижу. И эти люди мне рассказывали про каллбэк-хэлл:) Ну и эвент-дравен во всей красе. Только в ноде это родное все, а в пхп — попытка прикрутить асинхронщину.

$client = new swoole_redis;
$client->connect('127.0.0.1', 6379, function (swoole_redis $client, $result) {
    echo "connect\n";
    var_dump($result);
    $client->set('key', 'swoole', function (swoole_redis $client, $result) {
        var_dump($result);
        $client->get('key', function (swoole_redis $client, $result) {
            var_dump($result);
            $client->close();
        });
    });
});



НЛО прилетело и опубликовало эту надпись здесь
Не первая и не последняя попытка прикрутить асинхронщину туда, где ее не было. Что-то не припомню годных примеров из продакшена.

НЛО прилетело и опубликовало эту надпись здесь
Осталось прикрутить программистам асинхронщину и параллельное программирование в голову. Вот с этим возникают проблемы, то что есть либы под любой язык и любой подход — не новость.
swoole — это примерно то же самое что старый добрый phpDaemon, призванный отойти от концепции always die?
Ну и ReactPHP. Было бы интересно прочитать про сравнение их всех между собой.

Ну раз php-pm приводится в качестве примера, тогда уж и appserver можно за компанию.

судя по тому что 90% PHP сидят на версии 5, все они далеки от php

Хотя бы apache+php-fpm, поскольку остальные тоже работают из-под апача.

"Остальные" — это кто?

В этой статье мы сравним Node, Java, Go и PHP из-под Apache

Разве это не означает, что Apache стоит перед всеми?

Правильно читать вот так:


В этой статье мы сравним (Node), (Java), (Go) и (PHP из-под Apache)

Как минимум нода в отдельном веб-сервере точно никогда не нуждалась. Для Java существует AJP, но это дополнительная возможность, а не основная. Про Go не скажу.

Как мне казалось, мало того выпускает наружу голые (Node), (Java), (Go) и (PHP), ставят перед ними Apache, nginx, lighthttpd и, даже, прости господи, IIS, чаще всего еще и статику ими раздавая, оставляя на апп-сервер только динамику.

У Go не требует веб сервера
НЛО прилетело и опубликовало эту надпись здесь
$file_data = file_get_contents(‘/path/to/file.dat’);

    InputStream fileIs = new FileInputStream("/path/to/file");

я даже заглянул в код. Думаю очевидно что чтение файла и открытие дескриптора на него — это две совершенно разные вещи.
AloneCoder зачем вы это вообще переводили?
Да, разные, но вы плохо заглядывали в код бенчмарков, и там и там файл полностью считывается с диска, ссылка на листинги есть в статье, продублирую ее и здесь
А переводил затем, что любая статья про бенчмарки всегда неоднозначна и порождает дискуссию, обмен мнениями и реальным опытом, что прекрасно и ценно
Вредная статья, нарочно (или по незнанию) вводящая в заблуждение. Зачем сравнивать производительность node на задачах блокирующих event loop? Причём автор сам же написал в начале что это слабая сторона ноды. Она же просто не для этого.

Тесты в итоге выгдядят так: берём собаку, медведя, слона и кита. Смотрите — кит передвигается хуже всех. Еле по земле ползает.

И вредность данной статьи в том, что потом ходят толпами люди глубоко не разбирающиеся в условиях применения особенностей языков и тычут пальчиком вот в такие «статьи» — node дескать отстой. Mail.ru на Хабре доказало!
Спасибо мил человек, что дошел до вашего комента, и он тут был! Налайканый… а то бы поверил на слово статье

Добавлю к некорректному сравнению php и node.js ещё то, что в ноде никто уже несколько лет не пишет на коллбэках. Ну и отдельное удивление вызывает, что в статье не указаны версии движков. Как бы php5 очень сильно отличается по скорости от php7, то же самое с нодой.


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

Что касается PHP:
1) php nts (fpm) — работает в многопроцессовом режиме, php ts (mod apache) работает в многопоточном режиме, так что нельзя утверждать, что пых клонит процессы. Т.к. использовался апач — скорее всего использовался, mod + ts, т.е. многопоточный режим.
2) В пыхе есть неболкирующее I/O, в том числе и встроено в сам язык, к пример асинхронные запросы к mysqli, про react + event loop на основе какого-нибудь ev я уже не говорю, т.к. выборка будет не репрезентативна, т.е. это библиотеки, а не stdlib.
3) Не показаны версия и настройки опкеша. По-умолчанию конфиг содержит отключённый опкеш, но стоит его включить и отключить ревалидацию (т.е. избавиться от лишних запросов на жёсткий диск) — можно крайне сильно удивиться (я уж не говорю про jit-сборки, т.к. опять же, выборка не репрезнативна будет).

О чем вы говорите, если на тестовом стенде использовался Apache и PHP 5.4? Какой тут ZTS? Автор теста и слов-то таких не знает…

Хоть убейте — не нашёл ни строчки в статье о версии пыха =\

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

Потоки объединяются (pooled), чтобы минимизировать стоимость их создания и уничтожения, но в любом случае если у нас тысячи подключений, то создаются тысячи потоков, что плохо сказывается на работе диспетчера.

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

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

Не знаю ни одного современного веб-сервера на джаве, который бы не использовал неблокирующее io и ивент-луп так или иначе. И да, как описано выше соответственно сейчас никто не работает, кроме может быть каких-то самопальных поделок сделанных людьми, которые прочли статьи вроде этой.

Прежде чем перейти к обсуждению Go, должен сообщить, что я его поклонник.

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

Нужны колбэки

Нет, у джавы для неблокирющего io есть каналы из nio, которые прекрасно работают без колбэков и позволяют эффективно реализовать ивентлуп.

Бенчмарки вообще уморили: какие-то дефолтные конфиги и jsp для обработки запроса. Выбраны почему-то именно сервлеты, запускаются «бэнчмарки» без прогрева; когда один раз запускалось, томкат за указанное время еще и жсп поди успел скомпилировать. От реализации рассчета хеша вообще слезы на глаза наворачиваются. Не буду ничего говорить про другие языки, уверен, что там так же ляп на ляпе. А ведь кто-то возможно посмотрит и сделает какой-то вывод далекий от реальности.
НЛО прилетело и опубликовало эту надпись здесь
В PHP7 появились же thread

В смысле?

Два слова в «защиту» Node.js vs Go:
1) Начиная с версии 1.5 GOMAXPROCS = количество CPU, по-моему равные условия можно создать если в тестовом приложении Node.js использовать cluster https://nodejs.org/api/cluster.html
2) В Node.js как fs так и crypto (в частности crypto.randomBytes и crypto.pbkdf2) выходят в libuv thread pool http://docs.libuv.org/en/v1.x/threadpool.html, на мой взгляд результат мог бы быть иным если установить UV_THREADPOOL_SIZE=128 (максимум)
Спасибо за статью, комментарии честно признаюсь, не прочитал, может быть, кто-то что-то подобное уже высказал, поэтому выскажу субъективное пожелание.
Хотел бы увидеть более полную версию статьи, основанную на дополнительных данных, ввиде:
1. Дополнить данные схемы языками Ruby и Python, хотя бы потому-то что они тоже довольно популярны в виде бэкенда
2. И добавить еще одну ветку сравнений, в виде использования фреймворков. Т.е. как бы было на нативе и на ФВ. Не знаю как вы, но я ооочень редко встречал поддерживаемые велосипедные проекты)) Обычно(самые распрастранненые варианты)
when(lang) {
  Java -> Spring
  PHP -> Laravel
  Python -> Django
  Ruby -> Ruby on Rails
  NodeJs -> Express.js
}


Было бы любопытно посмотреть на цифры и объективное исследование)

Прочитайте лучше комментарии, от них пользы гораздо больше, чем от самой "статьи".

Ради интереса сделал тесты:
go 1.8.3 на виртуальном стенде в 4 ядра и 1 ГБ памяти лучший результат:


ab -n 10000 -c 5000 'http://127.0.0.1:4000/test?n=1'

Server Software:
Server Hostname: 127.0.0.1
Server Port: 4000


Document Path: /test?n=1
Document Length: 64 bytes


Concurrency Level: 5000
Time taken for tests: 2.776 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 1810000 bytes
HTML transferred: 640000 bytes
Requests per second: 3602.04 [#/sec] (mean)
Time per request: 1388.102 [ms] (mean)
Time per request: 0.278 [ms] (mean, across all concurrent requests)
Transfer rate: 636.69 [Kbytes/sec] received


Connection Times (ms)
min mean[±sd] median max
Connect: 0 300 390.9 132 1012
Processing: 1 365 352.5 195 1623
Waiting: 1 360 347.8 192 1622
Total: 1 664 436.5 700 1927


Percentage of the requests served within a certain time (ms)
50% 700
66% 1024
75% 1074
80% 1095
90% 1192
95% 1273
98% 1354
99% 1437
100% 1927 (longest request)


php 7.1.5 nginx + php-fpm (pm.max_children = 200, opcache.enable=1) лучший результат:


ab -n 10000 -c 5000 'http://127.0.0.1/test.php?n=1'

Server Software: nginx/1.13.0
Server Hostname: 127.0.0.1
Server Port: 80


Document Path: /test.php?n=1
Document Length: 64 bytes


Concurrency Level: 5000
Time taken for tests: 4.448 seconds
Complete requests: 10000
Failed requests: 1893
(Connect: 0, Receive: 0, Length: 1893, Exceptions: 0)
Write errors: 0
Non-2xx responses: 1893
Total transferred: 2504197 bytes
HTML transferred: 884197 bytes
Requests per second: 2248.37 [#/sec] (mean)
Time per request: 2223.832 [ms] (mean)
Time per request: 0.445 [ms] (mean, across all concurrent requests)
Transfer rate: 549.84 [Kbytes/sec] received


Connection Times (ms)
min mean[±sd] median max
Connect: 0 199 309.1 137 1069
Processing: 4 459 667.1 122 3127
Waiting: 1 447 669.9 103 3125
Total: 5 658 767.5 327 4093


Percentage of the requests served within a certain time (ms)
50% 327
66% 1024
75% 1138
80% 1313
90% 1527
95% 2125
98% 3236
99% 3251
100% 4093 (longest request)


Итог 3602.04 #/sec (go) против 2248.37 #/sec (php). Да, php проигрывает, но не так тотально как описывает автор.


Были ошибки запросов:


nginx/error.log

2017/05/28 23:42:10 [alert] 24969#24969: *758703 socket() failed (24: Too many open files) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET /test.php?n=1 HTTP/1.0", upstream: "fastcgi://127.0.0.1:9000", host: "127.0.0.1"
2017/05/28 23:42:10 [crit] 24968#24968: accept4() failed (24: Too many open files)


Ставил ulimt -n 200000, в конфиге php-fpm rlimit_files = 65535, в nginx.conf worker_connections 10000 и worker_rlimit_nofile 200000 — не помогло

НЛО прилетело и опубликовало эту надпись здесь

С сокетами получилось больше, но и ошибок больше:


4046.81 #/sec но и ошибок 2797 из 10000

Server Software: nginx/1.13.0
Server Hostname: 127.0.0.1
Server Port: 80


Document Path: /test.php?n=1
Document Length: 64 bytes


Concurrency Level: 5000
Time taken for tests: 2.471 seconds
Complete requests: 10000
Failed requests: 2797
(Connect: 0, Receive: 0, Length: 2797, Exceptions: 0)
Write errors: 0
Non-2xx responses: 2797
Total transferred: 2620813 bytes
HTML transferred: 1000813 bytes
Requests per second: 4046.81 [#/sec] (mean)
Time per request: 1235.542 [ms] (mean)
Time per request: 0.247 [ms] (mean, across all concurrent requests)
Transfer rate: 1035.73 [Kbytes/sec] received


Connection Times (ms)
min mean[±sd] median max
Connect: 0 439 445.8 226 1306
Processing: 81 394 212.7 389 990
Waiting: 1 349 202.5 365 969
Total: 110 833 491.5 626 1975


Percentage of the requests served within a certain time (ms)
50% 626
66% 865
75% 1323
80% 1356
90% 1759
95% 1862
98% 1872
99% 1875
100% 1975 (longest request)


nginx/error.log

2017/05/29 08:53:25 [alert] 10283#10283: *107893 socket() failed (24: Too many open files) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET /test.php?n=1 HTTP/1.0", upstream: "fastcgi://unix:/var/run/php-fcgi.sock:", host: "127.0.0.1"


В php-fpm выставил listen.backlog = 10000

НЛО прилетело и опубликовало эту надпись здесь

Это из-за ошибок. Когда происходит ошибка, то выдаётся всё очень быстро и тоже идёт в зачёт. Вообще ab не самая классная тулза. Вечером попробую siege'ом.

Самый адекватный без ошибок получилось с конкурентностью 1000:


Go 3786.41 [#/sec]

Server Software:
Server Hostname: 127.0.0.1
Server Port: 4000


Document Path: /test?n=1
Document Length: 64 bytes


Concurrency Level: 1000
Time taken for tests: 2.641 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 1810000 bytes
HTML transferred: 640000 bytes
Requests per second: 3786.41 [#/sec] (mean)
Time per request: 264.102 [ms] (mean)
Time per request: 0.264 [ms] (mean, across all concurrent requests)
Transfer rate: 669.28 [Kbytes/sec] received


Connection Times (ms)
min mean[±sd] median max
Connect: 0 5 10.7 1 53
Processing: 1 247 133.2 230 868
Waiting: 1 243 132.0 226 856
Total: 1 252 131.5 233 869


Percentage of the requests served within a certain time (ms)
50% 233
66% 289
75% 328
80% 353
90% 422
95% 504
98% 590
99% 644
100% 869 (longest request)


php 3418.30 [#/sec]

Server Software: nginx/1.13.0
Server Hostname: 127.0.0.1
Server Port: 80


Document Path: /test.php?n=1
Document Length: 64 bytes


Concurrency Level: 1000
Time taken for tests: 2.925 seconds
Complete requests: 10000
Failed requests: 14
(Connect: 0, Receive: 0, Length: 14, Exceptions: 0)
Write errors: 0
Non-2xx responses: 14
Total transferred: 2261806 bytes
HTML transferred: 641806 bytes
Requests per second: 3418.30 [#/sec] (mean)
Time per request: 292.543 [ms] (mean)
Time per request: 0.293 [ms] (mean, across all concurrent requests)
Transfer rate: 755.03 [Kbytes/sec] received


Connection Times (ms)
min mean[±sd] median max
Connect: 0 44 35.5 36 147
Processing: 38 238 89.1 236 577
Waiting: 1 210 84.6 207 526
Total: 43 282 84.4 276 583


Percentage of the requests served within a certain time (ms)
50% 276
66% 315
75% 336
80% 347
90% 380
95% 420
98% 456
99% 574
100% 583 (longest request)


После 1000 у php начинаются проблемы с потерей.

А если через wrk?

Что такое wrk?

Ничего особо не изменилось


php 4140.13 r/sec

Running 30s test @ http://127.0.0.1/test.php?n=1
12 threads and 400 connections
Thread Stats Avg Stdev Max ± Stdev
Latency 100.20ms 63.06ms 542.07ms 76.27%
Req/Sec 348.20 110.88 0.85k 72.45%
124513 requests in 30.07s, 32.06MB read
Requests/sec: 4140.13
Transfer/sec: 1.07MB


go 4765.73 r/sec

Running 30s test @ http://127.0.0.1:4000/test?n=1
12 threads and 400 connections
Thread Stats Avg Stdev Max ± Stdev
Latency 89.85ms 65.55ms 669.74ms 77.39%
Req/Sec 399.38 81.51 800.00 69.61%
143512 requests in 30.11s, 24.77MB read
Requests/sec: 4765.73
Transfer/sec: 842.38KB


С 4000 коннектов ошибки у php


php 4274.27 r/sec 4.5% ошибок

Running 30s test @ http://127.0.0.1/test.php?n=1
12 threads and 4000 connections
Thread Stats Avg Stdev Max ± Stdev
Latency 489.23ms 137.15ms 2.00s 94.40%
Req/Sec 362.90 249.27 3.52k 69.79%
128605 requests in 30.09s, 33.59MB read
Socket errors: connect 0, read 404, write 0, timeout 4065
Non-2xx or 3xx responses: 5850
Requests/sec: 4274.27
Transfer/sec: 1.12MB


go 4850.27 r/sec

Running 30s test @ http://127.0.0.1:4000/test?n=1
12 threads and 4000 connections
Thread Stats Avg Stdev Max ± Stdev
Latency 677.23ms 567.81ms 2.00s 60.05%
Req/Sec 418.88 183.85 2.30k 75.17%
146148 requests in 30.13s, 25.23MB read
Socket errors: connect 0, read 0, write 0, timeout 11398
Requests/sec: 4850.27
Transfer/sec: 857.32KB

Может нужно перезагрузить систему? :)

Невероятно непрофессиональный подход и просто типичнейший фанбой-булшит. Ничего толком о тестовой конфигурации, ни о железе, ни о софте, ни о версиях. Прогретая джава, не прогретая? Абстрактный аппач с пхп — как минимум странно. Тестирование на разном железе с разным объемом оперативки и количеством ядер? Где?


Мейлру студенческие работы стало переводить?

Обожаю комментарии в на хабре. Кладезь знаний.
(Без иронии.)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий