Comments 98
Mail.ru как бы намекает, что скоро начнет хантить Go разрабов =)
+10
Хороший обзор, спасибо.
К слову, regexp библиотека в Go считается медленной, хотя там использован алгоритм, несколько отличный от C-шного, который гарантирует линейную зависимость времени от размера входных данных.
Для этого случая можно попробовать PCRE (хотя, он оказался медленнее), или наивный split строки:
Результат примерно такой выходит:
К слову, regexp библиотека в Go считается медленной, хотя там использован алгоритм, несколько отличный от C-шного, который гарантирует линейную зависимость времени от размера входных данных.
Для этого случая можно попробовать PCRE (хотя, он оказался медленнее), или наивный split строки:
Код вариантов
package regex
import (
«github.com/glenn-brown/golang-pkg-pcre/src/pkg/pcre»
«regexp»
«strings»
)
var (
reg = regexp.MustCompile("^/greeting/([a-z]+)$")
pcreReg = pcre.MustCompile("^/greeting/([a-z]+)$", 0)
)
func RegexOrig(str string) string {
return reg.FindStringSubmatch(str)[1]
}
func RegexPCRE(str string) string {
return pcreReg.MatcherString(str, 0).GroupString(1)
}
func RegexStrings(str string) string {
return strings.Split(str, "/")[2]
}
func RegexNaive(str string) string {
if strings.HasPrefix(str, "/greeting/") {
return str[len("/greeting/"):]
}
return ""
}
import (
«github.com/glenn-brown/golang-pkg-pcre/src/pkg/pcre»
«regexp»
«strings»
)
var (
reg = regexp.MustCompile("^/greeting/([a-z]+)$")
pcreReg = pcre.MustCompile("^/greeting/([a-z]+)$", 0)
)
func RegexOrig(str string) string {
return reg.FindStringSubmatch(str)[1]
}
func RegexPCRE(str string) string {
return pcreReg.MatcherString(str, 0).GroupString(1)
}
func RegexStrings(str string) string {
return strings.Split(str, "/")[2]
}
func RegexNaive(str string) string {
if strings.HasPrefix(str, "/greeting/") {
return str[len("/greeting/"):]
}
return ""
}
Код бенчмарка
package regex
import «testing»
var str = "/greeting/user"
func TestRegexps(t *testing.T) {
if RegexOrig(str) != «user» {
t.Fatal(«RegexpOrig failed on», str, ":", RegexOrig(str))
}
if RegexPCRE(str) != «user» {
t.Fatal(«RegexpPCRE failed on», str, ":", RegexPCRE(str))
}
if RegexStrings(str) != «user» {
t.Fatal(«RegexpStrings failed on», str, ":", RegexStrings(str))
}
if RegexNaive(str) != «user» {
t.Fatal(«RegexpNaive failed on», str, ":", RegexNaive(str))
}
}
func BenchmarkOrig(b *testing.B) {
for i := 0; i < b.N; i++ {
RegexOrig(str)
}
}
func BenchmarkPCRE(b *testing.B) {
for i := 0; i < b.N; i++ {
RegexPCRE(str)
}
}
func BenchmarkStrings(b *testing.B) {
for i := 0; i < b.N; i++ {
RegexStrings(str)
}
}
func BenchmarkNaive(b *testing.B) {
for i := 0; i < b.N; i++ {
RegexNaive(str)
}
}
import «testing»
var str = "/greeting/user"
func TestRegexps(t *testing.T) {
if RegexOrig(str) != «user» {
t.Fatal(«RegexpOrig failed on», str, ":", RegexOrig(str))
}
if RegexPCRE(str) != «user» {
t.Fatal(«RegexpPCRE failed on», str, ":", RegexPCRE(str))
}
if RegexStrings(str) != «user» {
t.Fatal(«RegexpStrings failed on», str, ":", RegexStrings(str))
}
if RegexNaive(str) != «user» {
t.Fatal(«RegexpNaive failed on», str, ":", RegexNaive(str))
}
}
func BenchmarkOrig(b *testing.B) {
for i := 0; i < b.N; i++ {
RegexOrig(str)
}
}
func BenchmarkPCRE(b *testing.B) {
for i := 0; i < b.N; i++ {
RegexPCRE(str)
}
}
func BenchmarkStrings(b *testing.B) {
for i := 0; i < b.N; i++ {
RegexStrings(str)
}
}
func BenchmarkNaive(b *testing.B) {
for i := 0; i < b.N; i++ {
RegexNaive(str)
}
}
Результат примерно такой выходит:
$ go test -v -bench . -benchmem .
=== RUN TestRegexps
--- PASS: TestRegexps (0.00s)
PASS
BenchmarkOrig-4 2000000 845 ns/op 64 B/op 2 allocs/op
BenchmarkPCRE-4 1000000 1481 ns/op 160 B/op 3 allocs/op
BenchmarkStrings-4 5000000 284 ns/op 48 B/op 1 allocs/op
BenchmarkNaive-4 100000000 11.4 ns/op 0 B/op 0 allocs/op
ok test/regex 6.879s
+1
И на чем бы им свой очередной вирус написать? Кто бы написал сервис по вычищению ихних сервисов с компа.
-7
Интересно, что бы показал finagle от твиттера. Всё же там минимум абстракций над netty
+4
Если есть желание – можете напилить проектик на github, мы его соберем и прогоним на той же машине. Ну или можете сами собрать наши сервисы и прогнать их на своей =)
+3
Вот такой код:
Дал такие результаты:
Для сравнения:
Но если брать несколько прогонов то там результаты и Go и Finch примерно одинаковы ~6ms.
val endpoints: Endpoint[String :+: String :+: CNil] =
get(/) {Ok("Hello, World!")} :+: get("greeting" / string) { name: String => Ok("Hello, " + name + "!") }
Await.ready(Http.serve(":8080", endpoints.toService))
Дал такие результаты:
Finch
Server Software:
Server Hostname: localhost
Server Port: 8080
Document Path: /
Document Length: 13 bytes
Concurrency Level: 256
Time taken for tests: 1.154 seconds
Complete requests: 50000
Failed requests: 0
Total transferred: 5800000 bytes
HTML transferred: 650000 bytes
Requests per second: 43328.87 [#/sec] (mean)
Time per request: 5.908 [ms] (mean)
Time per request: 0.023 [ms] (mean, across all concurrent requests)
Transfer rate: 4908.35 [Kbytes/sec] received
Connection Times (ms)
min mean[±sd] median max
Connect: 0 2 1.1 1 8
Processing: 0 2 1.6 2 15
Waiting: 0 2 1.4 1 15
Total: 0 4 2.6 3 17
Percentage of the requests served within a certain time (ms)
50% 3
66% 5
75% 6
80% 6
90% 8
95% 9
98% 10
99% 11
100% 17 (longest request)
Server Hostname: localhost
Server Port: 8080
Document Path: /
Document Length: 13 bytes
Concurrency Level: 256
Time taken for tests: 1.154 seconds
Complete requests: 50000
Failed requests: 0
Total transferred: 5800000 bytes
HTML transferred: 650000 bytes
Requests per second: 43328.87 [#/sec] (mean)
Time per request: 5.908 [ms] (mean)
Time per request: 0.023 [ms] (mean, across all concurrent requests)
Transfer rate: 4908.35 [Kbytes/sec] received
Connection Times (ms)
min mean[±sd] median max
Connect: 0 2 1.1 1 8
Processing: 0 2 1.6 2 15
Waiting: 0 2 1.4 1 15
Total: 0 4 2.6 3 17
Percentage of the requests served within a certain time (ms)
50% 3
66% 5
75% 6
80% 6
90% 8
95% 9
98% 10
99% 11
100% 17 (longest request)
Для сравнения:
Go
Server Software:
Server Hostname: localhost
Server Port: 8080
Document Path: /
Document Length: 12 bytes
Concurrency Level: 256
Time taken for tests: 1.241 seconds
Complete requests: 50000
Failed requests: 0
Total transferred: 6450000 bytes
HTML transferred: 600000 bytes
Requests per second: 40297.59 [#/sec] (mean)
Time per request: 6.353 [ms] (mean)
Time per request: 0.025 [ms] (mean, across all concurrent requests)
Transfer rate: 5076.55 [Kbytes/sec] received
Connection Times (ms)
min mean[±sd] median max
Connect: 0 3 49.5 0 1000
Processing: 1 3 4.5 3 204
Waiting: 0 3 4.5 3 203
Total: 1 6 51.2 3 1199
Percentage of the requests served within a certain time (ms)
50% 3
66% 3
75% 3
80% 3
90% 4
95% 6
98% 8
99% 15
100% 1199 (longest request)
Server Hostname: localhost
Server Port: 8080
Document Path: /
Document Length: 12 bytes
Concurrency Level: 256
Time taken for tests: 1.241 seconds
Complete requests: 50000
Failed requests: 0
Total transferred: 6450000 bytes
HTML transferred: 600000 bytes
Requests per second: 40297.59 [#/sec] (mean)
Time per request: 6.353 [ms] (mean)
Time per request: 0.025 [ms] (mean, across all concurrent requests)
Transfer rate: 5076.55 [Kbytes/sec] received
Connection Times (ms)
min mean[±sd] median max
Connect: 0 3 49.5 0 1000
Processing: 1 3 4.5 3 204
Waiting: 0 3 4.5 3 203
Total: 1 6 51.2 3 1199
Percentage of the requests served within a certain time (ms)
50% 3
66% 3
75% 3
80% 3
90% 4
95% 6
98% 8
99% 15
100% 1199 (longest request)
Но если брать несколько прогонов то там результаты и Go и Finch примерно одинаковы ~6ms.
+3
Круто ) Спасибо!
0
Найс. Если мне не изменяет память, то Финч где-то на 5-15% добавляет оверхеда, то на то и выходит
0
Я бы сказал 5-7% по последним данным:
— Очень много опитизаций было сделано Тревисом в Circe
— В Finch как минимум две вещи помогли сократить разрыв: TooFastString и быстрые ридеры
Но, на удивление, этот тест не использует ни того ни другого. В любом случае оч крутой результат!
— Очень много опитизаций было сделано Тревисом в Circe
— В Finch как минимум две вещи помогли сократить разрыв: TooFastString и быстрые ридеры
Но, на удивление, этот тест не использует ни того ни другого. В любом случае оч крутой результат!
0
Accepted.
+1
Кстати, она теперь поддерживает keep-alive в HTTP 1.0, так что можно тестировать и с ab -k.
+2
А если сделать замеры, экззотики для и фана ради, на связке Nginx+LUA?
Еще есть вот такая экзотика: H2O+MRuby (неделю назад наткнулся вот на эту статью 25,000+ Req/s for Rack JSON API with MRuby
PS еще конечно не пятница, но вдруг :)
Еще есть вот такая экзотика: H2O+MRuby (неделю назад наткнулся вот на эту статью 25,000+ Req/s for Rack JSON API with MRuby
PS еще конечно не пятница, но вдруг :)
+1
> и, так или иначе, субъективных взглядов мы выбрали Go
Вы ведь его выбрали еще до тестов, к чему тогда был этот карнавал?
Вы ведь его выбрали еще до тестов, к чему тогда был этот карнавал?
+5
Вы на localhost тестировали? Почему такая высокая задержка? Или это VirtualBox тормозит?
0
Я имею ввиду Time per request в ab. У меня на локальных тестах с вашим кодом выдает цифры в районе ~10ms.
0
На локальных тестах – где у кого ~10ms? ) Тесты и серверы запускались на одной виртуалке, да. Естественно, по очереди. Да, может, лучше было бы запустить где-то в облаке, но в среднем, результаты из прогона в прогон – сохраняются. Тем более, что нам важнее было определить не производительность в общем, а производительность относительную.
0
Вы выбирали основной язык для mail.ru или для одного определенного сервиса?
+1
Утилита от Apache ab использует HTTP 1.0 и может передавать заголовок «Connection: Keep-Alive». Если сервер достаточно вменяемый, то он, увидев этот заголовок, будет держать keep-alive соединение. Делается это с помощью флага -k, например:
ab -k -n50000 -c256 -t10 http://service.host/
ab -k -n50000 -c256 -t10 http://service.host/greeting/hello
+1
Ребят, вот честно, ну что вы в самом деле, вот берёте плюшевый плюсовый http-сервер из примеров буста: www.boost.org/doc/libs/1_59_0/doc/html/boost_asio/examples/cpp11_examples.html
Меняете там request_handler.cpp под задачу из поста (которая гораздо проще, чем в примере).
И тестируете. Ну рвёт ведь всех просто как тузик грелку.
Вынесу из-под спойлера:
wrk, 1-й тест:
Average Latency, ms: 38.56
Requests/sec: 9874.16
(лень заморачиваться с nginx, результат понятен).
ab, 1-й тест:
Completed requests: 50000
Time per request, ms: 14.923
Request, #/sec: 17155.15
ab, 2-й тест:
Completed requests: 50000
Time per request, ms: 14.562
Request, #/sec: 17580.17
Причём не просто успевает 50000 запросов за 10 секунд, а даже укладывается менее чем в 3 секунды.
О чём это говорит? Надо выбирать C++ (C++14).
И это ещё я не говорю об использовании памяти и процессора (т.е., в конечном счёте, электроэнергии). Ведь мы хотим не только быстро обслуживать клиентов, но ещё и делать это дешевле на долгом промежутке времени.
Причём даже тут есть куда пооптимизировать.
Меняете там request_handler.cpp под задачу из поста (которая гораздо проще, чем в примере).
Код метода
void request_handler::handle_request(const request& req, reply& rep)
{
using namespace std::literals::string_literals;
static std::regex greeting_regex("^/greeting/([a-z]+)$");
std::string request_path;
if (!url_decode(req.uri, request_path))
{
rep = reply::stock_reply(reply::bad_request);
return;
}
std::smatch greeting_match;
if (request_path == "/")
{
rep.status = reply::ok;
rep.content = "Hello, World!";
}
else if (std::regex_match(request_path, greeting_match, greeting_regex))
{
if (greeting_match.size() == 2)
{
rep.content = "Hello, "s + greeting_match[1].str() + "\r\n"s;
}
else
{
rep = reply::stock_reply(reply::not_found);
return;
}
}
else {
rep = reply::stock_reply(reply::not_found);
return;
}
rep.status = reply::ok;
rep.headers.resize(1);
rep.headers[0].name = "Content-Length";
rep.headers[0].value = std::to_string(rep.content.size());
}
И тестируете. Ну рвёт ведь всех просто как тузик грелку.
Спойлер с измерениями
комп
(192.168.1.16 — моя виртуалка)
wrk:
ab:
(192.168.1.16 — моя виртуалка)
wrk:
$ wrk -d300s -c1000 -t50 --timeout 2s http://192.168.1.16/
Running 5m test @ http://192.168.1.16/
50 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 38.56ms 139.88ms 2.00s 95.47%
Req/Sec 210.75 156.88 4.49k 67.59%
2963235 requests in 5.00m, 146.95MB read
Socket errors: connect 0, read 1108, write 31, timeout 3153
Requests/sec: 9874.16
Transfer/sec: 501.42KB
ab:
$ ab -n50000 -c256 -t10 http://192.168.1.16/
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.16 (be patient)
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
Completed 25000 requests
Completed 30000 requests
Completed 35000 requests
Completed 40000 requests
Completed 45000 requests
Completed 50000 requests
Finished 50000 requests
Server Software:
Server Hostname: 192.168.1.16
Server Port: 80
Document Path: /
Document Length: 13 bytes
Concurrency Level: 256
Time taken for tests: 2.915 seconds
Complete requests: 50000
Failed requests: 0
Total transferred: 1600000 bytes
HTML transferred: 650000 bytes
Requests per second: 17155.15 [#/sec] (mean)
Time per request: 14.923 [ms] (mean)
Time per request: 0.058 [ms] (mean, across all concurrent requests)
Transfer rate: 536.10 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 2 7 30.9 6 1005
Processing: 2 8 2.0 7 25
Waiting: 1 6 1.9 5 17
Total: 9 15 31.0 14 1011
Percentage of the requests served within a certain time (ms)
50% 14
66% 15
75% 15
80% 15
90% 17
95% 20
98% 22
99% 24
100% 1011 (longest request)
$ ab -n50000 -c256 -t10 http://192.168.1.16/greeting/hello
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.16 (be patient)
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
Completed 25000 requests
Completed 30000 requests
Completed 35000 requests
Completed 40000 requests
Completed 45000 requests
Completed 50000 requests
Finished 50000 requests
Server Software:
Server Hostname: 192.168.1.16
Server Port: 80
Document Path: /greeting/hello
Document Length: 12 bytes
Concurrency Level: 256
Time taken for tests: 2.844 seconds
Complete requests: 50000
Failed requests: 0
Total transferred: 1550000 bytes
HTML transferred: 600000 bytes
Requests per second: 17580.17 [#/sec] (mean)
Time per request: 14.562 [ms] (mean)
Time per request: 0.057 [ms] (mean, across all concurrent requests)
Transfer rate: 532.21 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 3 6 1.4 6 15
Processing: 2 8 1.8 8 20
Waiting: 1 6 1.9 6 15
Total: 8 15 1.9 14 28
Percentage of the requests served within a certain time (ms)
50% 14
66% 15
75% 15
80% 15
90% 17
95% 19
98% 20
99% 22
100% 28 (longest request)
Вынесу из-под спойлера:
wrk, 1-й тест:
Average Latency, ms: 38.56
Requests/sec: 9874.16
(лень заморачиваться с nginx, результат понятен).
ab, 1-й тест:
Completed requests: 50000
Time per request, ms: 14.923
Request, #/sec: 17155.15
ab, 2-й тест:
Completed requests: 50000
Time per request, ms: 14.562
Request, #/sec: 17580.17
Причём не просто успевает 50000 запросов за 10 секунд, а даже укладывается менее чем в 3 секунды.
О чём это говорит? Надо выбирать C++ (C++14).
И это ещё я не говорю об использовании памяти и процессора (т.е., в конечном счёте, электроэнергии). Ведь мы хотим не только быстро обслуживать клиентов, но ещё и делать это дешевле на долгом промежутке времени.
Причём даже тут есть куда пооптимизировать.
+5
C++ надо еще выучить.
И желательно не медленнее, чем за 21 день :)
+8
wrk, 1-й тест:
Average Latency, ms: 38.56
Requests/sec: 9874.16
Если сравнивать наши реализации серверов на go и c++, то у нас они следующие (c++ не представлен в статье):
Go:
Average Latency, ms: 104,83
Requests/sec: 36191.37
C++
Average Latency, ms: 57.88
Requests/sec: 16792.48
Скорость ответа не всегда равно высокая производительность.
Никто не спорит, что C++ может быстрее. Erlang, например, тоже может очень быстро.
И данный обзор никак не пытается определить лучший в мире язык программирования. =)
+1
А покажите код C++ и результаты ab для req/sec.
wrk больше для измерения latency подходит.
wrk больше для измерения latency подходит.
0
В ab его не тестировали. Код показать, к сожалению, нельзя.
Почему wrk подходит больше для latency?
Почему wrk подходит больше для latency?
0
Особенности реализации (предназначен для тестирования nginx).
Например, скорость работы wrk зависит от ресурсов системы (не сервера, а откуда запускаете).
Если, например, запускать подряд, то он может даже выдать `Socket errors: connect: 1000` или что-то типа: `Socket errors: connect 0, read 1490, write 159932, timeout 0`, полная ерунда, т.е. все коннекты свалились в ошибку, хотя при этом на сервер даже не было соединений (я проверял по tcpdump). Соответственно, все такие «несостоявшиеся» соединения уменьшат значение «Requests/sec». А вот latency рассчитывается только по удачным соединениям.
При этом прямо во время этих ошибок коннекта можно проверять банально браузером — всё будет работать.
Вот здесь ещё много «грязных» подробностей: gwan.com/en_apachebench_httperf.html
Например, скорость работы wrk зависит от ресурсов системы (не сервера, а откуда запускаете).
Если, например, запускать подряд, то он может даже выдать `Socket errors: connect: 1000` или что-то типа: `Socket errors: connect 0, read 1490, write 159932, timeout 0`, полная ерунда, т.е. все коннекты свалились в ошибку, хотя при этом на сервер даже не было соединений (я проверял по tcpdump). Соответственно, все такие «несостоявшиеся» соединения уменьшат значение «Requests/sec». А вот latency рассчитывается только по удачным соединениям.
При этом прямо во время этих ошибок коннекта можно проверять банально браузером — всё будет работать.
Вот здесь ещё много «грязных» подробностей: gwan.com/en_apachebench_httperf.html
+3
Понял, большое спасибо!
+1
Или вот прямо сейчас пытаюсь разобраться:
в одном окне терминала запустил сервер, во втором (на той же машине чтобы уж точно не повлияло ничего):
в третьем:
т.е. сервер слушает, всё ок, но соединений нет
как результат:
Вот что он делал? Я не знаю. И никаких подробностей.
Вывод: wrk — довольно странный инструмент. Или я совсем ничего не понимаю и пора уже переквалифицироваться в дворники. Кто понимает — помогите понять, плз.
в одном окне терминала запустил сервер, во втором (на той же машине чтобы уж точно не повлияло ничего):
$ ./wrk -d300s -c1000 -t50 --timeout 2m http://localhost/greeting/hello
в третьем:
$ netstat -an | grep tcp
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:6942 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:63342 0.0.0.0:* LISTEN
т.е. сервер слушает, всё ок, но соединений нет
как результат:
Running 5m test @ http://localhost/greeting/hello
50 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 81.71ms 174.10ms 1.75s 90.76%
Req/Sec 62.24 136.83 1.74k 94.96%
7328 requests in 5.00m, 379.28KB read
Socket errors: connect 1000, read 0, write 0, timeout 0
Requests/sec: 24.42
Transfer/sec: 1.26KB
Вот что он делал? Я не знаю. И никаких подробностей.
Вывод: wrk — довольно странный инструмент. Или я совсем ничего не понимаю и пора уже переквалифицироваться в дворники. Кто понимает — помогите понять, плз.
0
А со второй попытки – работает? )
0
Не знаю, со второй или нет, но сейчас запустил — работает.
Всё слишком странно.
Почему ab работает, а wrk нет?
Всё слишком странно.
Почему ab работает, а wrk нет?
0
Ещё попутно вот что нашёл: github.com/giltene/wrk2
Автор утверждает, что wrk считает latency неправильно.
Автор утверждает, что wrk считает latency неправильно.
0
> Код показать, к сожалению, нельзя.
Странно, код на других языках показали, а этот нельзя :-)
Странно, код на других языках показали, а этот нельзя :-)
+2
Причем еще бустовая реализация — самая медленная из всех C\CPP.
+1
а какая быстрее?
0
Когда-то давно — нативный модуль к nginx всех уделывал, надо бы перетестить.
Всетроенный libevent-овский и mongoose были не плохи.
Всетроенный libevent-овский и mongoose были не плохи.
0
Однопоточные библиотеки (libevent/mongoose) в принципе не могут «уделать» Boost.Asio (многопоточность, под линухом использует epoll, под bsd — kqueue, под виндой — iocp).
cpp-netlib не в счёт, это очень плохая реализация и не зря заброшена на текущий момент.
cpp-netlib не в счёт, это очень плохая реализация и не зря заброшена на текущий момент.
0
go: 92838.98 rps
java: 200127.00 rps
java: 200127.00 rps
./wrk -c 512 -t 2 -d 60 http://localhost:8080/
Running 1m test @ http://localhost:8080/
2 threads and 512 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.22ms 3.58ms 77.45ms 77.41%
Req/Sec 46.68k 5.97k 73.15k 69.77%
5577230 requests in 1.00m, 686.13MB read
Requests/sec: 92838.98
Transfer/sec: 11.42MB
./wrk -c 512 -t 2 -d 60 http://localhost:8084/
Running 1m test @ http://localhost:8084/
2 threads and 512 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.56ms 2.73ms 49.36ms 87.17%
Req/Sec 100.61k 11.36k 130.28k 74.87%
12009644 requests in 1.00m, 1.29GB read
Requests/sec: 200127.00
Transfer/sec: 21.95MB
0
А можно на `htop` посмотреть во время теста явы? :-)
0
только завтра, код на рабочем ноутбуке… не знаю, правда на что смотреть, все четыре ядра заняты на 100%
0
ой-ой, тогда можно не показывать htop :-)
вот тот код на с++ использует 1% cpu
вообще, я, конечно, хотел спросить про потребление памяти, но теперь уже не имеет смысла
вот тот код на с++ использует 1% cpu
вообще, я, конечно, хотел спросить про потребление памяти, но теперь уже не имеет смысла
0
Такие бенчмарки — полная туфта.
Делать их весело, но как себя поведет приложение, когда в него добавится логика, когда начнется сборка мусора, проявятся прочие нюансы — эти тесты не показывают.
Делать их весело, но как себя поведет приложение, когда в него добавится логика, когда начнется сборка мусора, проявятся прочие нюансы — эти тесты не показывают.
+9
Зато эти тесты показывают, как ведут себя голые серверы, без «прочих нюансов» которые зависят от рук программистов. И оверхед каждого из претендентов никуда не денется, если «в него добавится логика и начнется сборка мусора».
0
Странно, что вы не добавили maintainability в список показателей.
0
Написать сервер с «hello world» и тестировать производительность языка? Окай…
Могу сказать про Rust, его производительность ± такая же, что и C++. Писал небольшой сервис для неточного сравнения текстов и сравнивал производительность.
Очевидно, что Rust будет быстрее работать Go, поскольку в Rust нет сборщика мусора.
Могу сказать про Rust, его производительность ± такая же, что и C++. Писал небольшой сервис для неточного сравнения текстов и сравнивал производительность.
Очевидно, что Rust будет быстрее работать Go, поскольку в Rust нет сборщика мусора.
+6
Тоже целиком за Раст, единственный минус его — то, что сегодня написанная программа через 2 недели может устареть: «Too old compiler version» :-)
0
Вроде как это выражение уже не особо актуально.
Еще смущает выбор hyper для теста.
Еще смущает выбор hyper для теста.
0
Так пишите не на nightly, а на stable — до выхода 2.х никаких проблем.
0
ну а минусовать зачем?
только недавно осенью был 1.3, теперь уже 1.5
а вообще у раста есть проблема, похожая на проблему рельсов: сегодня такой-то гем популярен, а завтра буквально он может выйти из моды
только недавно осенью был 1.3, теперь уже 1.5
а вообще у раста есть проблема, похожая на проблему рельсов: сегодня такой-то гем популярен, а завтра буквально он может выйти из моды
0
Это просто выражение согласия/несогласия, не относитесь к этому серьёзно.
Они каждые 6 недель будут выпускать новую версию.
При этом гарантируют, что в пределах мажорной версии (1.хх) обратная совместимость не сломается.
Они каждые 6 недель будут выпускать новую версию.
При этом гарантируют, что в пределах мажорной версии (1.хх) обратная совместимость не сломается.
0
А какой смысле стрелять по серверу с того же хоста, более того в виртуалке. Сама программа бенчмарка будет неслабо афектить http-сервер. Да и куча всего остального может афектить процесс виртуалки на макбуке. Мне кажется лучше исключать внешние факторы по максимуму.
hyper на сколько я смотрел в его код некоторое время назад, выглядел довольно тормозной либой. Выглядело тогда, что он использует штатный TcpStream с блокирующими сокетами. Тут скорее измерение скорости тормозной либы, а не языка. Но в го, же да есть горутины, которые по логике сильно лучше должны быть, чем треды с синхронными read/write.
Вроде MIO должно быть лучше, но там нет http.
+ я совсем не знаю про дебагеры для го и раста. Как то пункт про дебаг у вас мимо.
hyper на сколько я смотрел в его код некоторое время назад, выглядел довольно тормозной либой. Выглядело тогда, что он использует штатный TcpStream с блокирующими сокетами. Тут скорее измерение скорости тормозной либы, а не языка. Но в го, же да есть горутины, которые по логике сильно лучше должны быть, чем треды с синхронными read/write.
Вроде MIO должно быть лучше, но там нет http.
+ я совсем не знаю про дебагеры для го и раста. Как то пункт про дебаг у вас мимо.
0
И go и rust можно дебажить с gdb. По поводу mio – да, его и пытаются прикрутить создатели hyper (есть ссылка на issue в статье). Меня еще расстраивает тот факт, что в Rust выпилили аналогичные «горутины» или «green threads» после, вроде 0.9 версии со смыслом, типа, если вам нужно – сами напилите планировщик для этих дел.
Про тесты с локального хоста – где-то выше я уже говорил, что расклады от прогона к прогону остаются прежними, соответственно, все в равных условиях.
Про «измерение скорости тормозный либы» – какую не тормозную http либу для Rust знаете вы? Или вы предлагает писать для такого бенчмарка свой http сервер? )
Про тесты с локального хоста – где-то выше я уже говорил, что расклады от прогона к прогону остаются прежними, соответственно, все в равных условиях.
Про «измерение скорости тормозный либы» – какую не тормозную http либу для Rust знаете вы? Или вы предлагает писать для такого бенчмарка свой http сервер? )
0
Я не искал быстрого http-сервера на rust. Возможно его вообще нет. Из-за молодости и не очень большой популярности языка.
Про выпиливание корутит из раста я тоже был не рад. Он стал более общим языком, но из-за этого проиграл в легкости написания высокопроизводительных многопоточных приложений.
Ну http сервер на либе с корутинами на расте я думаю по силам написал в mail.ru ) Tarantool, например, сильно более сложный проект.
Собственно, все что нужно это откопать зарытую либу корутин из версии 0.9, взять MIO, либу парсинга http протокола и слепить все вместе с хорошим API!
Про выпиливание корутит из раста я тоже был не рад. Он стал более общим языком, но из-за этого проиграл в легкости написания высокопроизводительных многопоточных приложений.
Ну http сервер на либе с корутинами на расте я думаю по силам написал в mail.ru ) Tarantool, например, сильно более сложный проект.
Собственно, все что нужно это откопать зарытую либу корутин из версии 0.9, взять MIO, либу парсинга http протокола и слепить все вместе с хорошим API!
0
Лучше бы Swift и D сравнили. Куда более простые языки, чем предложенная выборка.
-2
Community size по предложенной в статье методике у D будет 1 887. На hh разработчиков — 1.
Судя по githut.info и stackoverflow, D уже менее популярен, чем Rust, а значит пакетов у него скорее всего меньше. И что-то мне подсказывает, что разрыв будет все больше. С производительностью там тоже не все однозначно.
Swift только-только вышел в opensource.
Зачем сравнивать заведомо проигрышные варианты? Особенно если есть уже положительный опыт с другими.
Судя по githut.info и stackoverflow, D уже менее популярен, чем Rust, а значит пакетов у него скорее всего меньше. И что-то мне подсказывает, что разрыв будет все больше. С производительностью там тоже не все однозначно.
Swift только-только вышел в opensource.
Зачем сравнивать заведомо проигрышные варианты? Особенно если есть уже положительный опыт с другими.
+1
>, то первый претендент — это, конечно, Node.js
Лол, месяц сравнения nodejs со всем подряд.
Ладно я понимаю еще с PHP тут пытались сравнить, но cо Scala…
Лол, месяц сравнения nodejs со всем подряд.
Ладно я понимаю еще с PHP тут пытались сравнить, но cо Scala…
0
Кто бы вот объяснил — какой скрытый смысл в КДПВ?
0
Мы буквально на днях проводили похожие тесты для поиска основы для наших веб серверов. Только мы стреляли яндекс танком с одной машины в другую. Ну и среди участников также были haskell и clojure.
Вот результаты по Responses Per Second
source Yandex.Tank response per second(ubuntu vm 8 cores)
target ubuntu vm 8 cores
golang fast http 30k+
nginx 20k
golang http 20k-
haskell wai warp 15k+
clojure http-kit 15k-
node.js 7k
rust hyper 10k+
rust iron 10k-
fsharp suave.io 4k+ (best result ever for .net web servers)
asp.net 5 kestrel coreclr/mono ??? 400-
В чистом итоге видно что golang fast http абсолютный лидер. Хотя изначально мы возлагали большие надежды на nginx с lua(openresty). Забавно что мы также уперлись в регексп в голанг и решили его просто через слайс по FindIndex.
Вот результаты по Responses Per Second
source Yandex.Tank response per second(ubuntu vm 8 cores)
target ubuntu vm 8 cores
golang fast http 30k+
nginx 20k
golang http 20k-
haskell wai warp 15k+
clojure http-kit 15k-
node.js 7k
rust hyper 10k+
rust iron 10k-
fsharp suave.io 4k+ (best result ever for .net web servers)
asp.net 5 kestrel coreclr/mono ??? 400-
В чистом итоге видно что golang fast http абсолютный лидер. Хотя изначально мы возлагали большие надежды на nginx с lua(openresty). Забавно что мы также уперлись в регексп в голанг и решили его просто через слайс по FindIndex.
+4
Также интересно что я так и не решил проблему с fsharp там можно было поднять скорость через libuv. Но видать баг в suave и скорость упала. Кестрел еще сыроват но ребята вроде его уже почти допилили по скорости до нетти. бенчмарк.
По компиляции я не заметил разницы для голанг флагов go build -ldflags "-s -w". gccgo так и не удалось проверить.
Rust версия была скомпилирована не как релиз версия.
Haskell был скомпилирован с тредами и запущен +RTS -A4M -N8 -qg0 -qb -g1
HttpKit был запущен как java -server -Xms3072m -Xmx3072m -cp `lein classpath` clojure.main -m main
По компиляции я не заметил разницы для голанг флагов go build -ldflags "-s -w". gccgo так и не удалось проверить.
Rust версия была скомпилирована не как релиз версия.
Haskell был скомпилирован с тредами и запущен +RTS -A4M -N8 -qg0 -qb -g1
HttpKit был запущен как java -server -Xms3072m -Xmx3072m -cp `lein classpath` clojure.main -m main
0
Я пробовал gccgo, у меня он с флагом fast оказался медленнее (на той же виртуалке, что и тесты) ~ на 20-25% =(
0
Rust версия была скомпилирована не как релиз версия
А какой смысл мерить код без оптимизаций?
+1
Чтобы nginx не так сильно затормаживал обработку запросов его надо правильно настроить: gist.github.com/hgfischer/7965620
Сам недавно сталкивался с вопросом оптимизации nginx перед сервисом на Go. Без оптимизации Go напрямую показывал 39k rps, через nginx пролазило только 13k rps. После настройки как в статье по ссылке — nginx увеличил скорость до 32k rps.
Сам недавно сталкивался с вопросом оптимизации nginx перед сервисом на Go. Без оптимизации Go напрямую показывал 39k rps, через nginx пролазило только 13k rps. После настройки как в статье по ссылке — nginx увеличил скорость до 32k rps.
+1
мы используем практически идентичные настройки и нет нгинкс у нас медленней чем го фаст хттп а когда возишся с модулями тот там дело вообще не очень становится.
0
Спасибо! Натыкался на этот бенчмарк во время наших тестов. Безусловно, можно ускорить nginx, но в контексте статьи производительность nginx не столь критична, так как все серверы находились в равных условиях.
0
Встречная статья Rust vs Go
+4
Sign up to leave a comment.
Как выбрать язык программирования?