Комментарии 57
ab -k -c 200 -n 50000…
Когда соединение остаётся открытым? Например если я установлю связь с сервером через websocket?
Прогнал такой тест:
ab -k -c500 -n100000 http://localhost:8100/
Concurrency Level: 500
Time taken for tests: 1.654 seconds
Complete requests: 100000
Failed requests: 0
Keep-Alive requests: 100000
Total transferred: 35300000 bytes
HTML transferred: 18200000 bytes
Requests per second: 60450.25 [#/sec] (mean)
Time per request: 8.271 [ms] (mean)
Time per request: 0.017 [ms] (mean, across all concurrent requests)
Transfer rate: 20838.81 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 2.1 0 50
Processing: 0 8 14.0 2 178
Waiting: 0 8 14.0 2 178
Total: 0 8 14.6 2 178
Percentage of the requests served within a certain time (ms)
50% 2
66% 8
75% 14
80% 15
90% 19
95% 22
98% 32
99% 92
100% 178 (longest request)
Concurrency Level: 500
Time taken for tests: 3.297 seconds
Complete requests: 100000
Failed requests: 0
Keep-Alive requests: 100000
Total transferred: 32300000 bytes
HTML transferred: 18200000 bytes
Requests per second: 30330.25 [#/sec] (mean)
Time per request: 16.485 [ms] (mean)
Time per request: 0.033 [ms] (mean, across all concurrent requests)
Transfer rate: 9567.06 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 2.0 0 45
Processing: 0 16 15.7 12 139
Waiting: 0 16 15.7 12 139
Total: 0 16 15.8 12 139
Percentage of the requests served within a certain time (ms)
50% 12
66% 18
75% 25
80% 28
90% 39
95% 48
98% 60
99% 68
100% 139 (longest request)
В этой ситуации D выигрывает в 2 раза.
Слева D, справа Go
Похоже, пора переходить на wrk и увеличивать количество запросов, ab все равно не выдаст больше ~120к рпс
Как вы видимо уже сами поняли, без keepalive это превращается в тест обработчиков соединений.
А вы думаете когда по рекламе залетает тонна посетителей они открывают 200 страниц подряд?
Кипалив это не правильно для тестирования динамики, перед беком стоит обычно какой-то сервер который статику отдает, он то и будет обратабывать все ваши «кипаливы».
Боюсь, здесь ситуация не про клиентов. Естественно, перед беком стоит балансировщик. Этот балансировщик лезет на сервер бека и мы имеем общение "балансер — бекенд". Здесь мы можем настроить все, как нам нужно.
И вот тут есть выбор "создавать новое соединение на каждый запрос" или "держать соединение и отправлять новые запросы в нем". В первом случае есть накладные расходы на установление соединения. Во втором случае — нет.
Когда у вас rps начинает исчисляться тысячами, это начинает чувствоваться. Ну и вылезают другие проблемы, например, на балансировщике могут кончиться порты для исходящих соединений. Поэтому желательно настраивать keepalive от балансировщика ко всем бекендам.
А вторую часть не до конца понял. Веб-сервера не встроены ни в D ни в Go — это библиотечные реализации. В целом я их хотел их сравнить: кто шустрее, меньше памяти ест, процессор грузит. Или вы имели ввиду что ещё можно что-то сравнивать в производительности веб приложений? Я только начинаю этим заниматься, поэтому не знаю, какие ещё могут быть критерии.
а еще самое главное — замеров надо делать несколько и брать среднее от них.
библиотечные реализации
Исправлюсь — сравнение производительности библиотечных реализаций. Не знаю, пользуются ли библиотечными реализации веб-серверов Go и D в продакшине
Извиняюсь, вы сравнивали скорость работы существенно разных шаблонизаторов или что-то ещё?
При таких "кажется" надо измерять. Ни там, ни там не используется кэширование шаблонов после парсинга, как оно рекомендуется ибо эта стадия обычно довольно дорогая, хотя в случае html/template
может быть относительно дешевой относительно шаблонизатора vibe.d, который более-менее сопоставим с jade/slim по функциональности.
В плане Go можно попробовать использовать: https://github.com/valyala/fasthttp, https://github.com/celrenheit/lion, https://github.com/labstack/echo
Потребление памяти и цпу в связке echo + fasthttp + quicktemplate должно быть ниже. Для REST-а можно заменить encoding/json на ffjson.
В Go 1.6 планировщик более оптимизирован. Если лень ставить руками, то можно использовать gvm (https://github.com/moovweb/gvm). Таким образом сравнить производительность в разных версиях языка.
Вы бы исходники выложили на гитхаб — я бы вам пулреквестов накидал :-)
vibe.d по умолчанию тянет с собой кучу мусора (всякие редисы, монги и прочий хлам), поэтому лучше явно указывать конкретные подмодули:
dependency "vibe-d:core" version="~>0.7.23"
dependency "vibe-d:diet" version="~>0.7.23"
import vibe.http.server;
import vibe.templ.diet;
Сравнение получается не совсем честным — реализация на го выдаёт чуть больше текста. Это не должно существенно сказываться на скорости, тем не менее нет смысла вносить лишнюю погрешность.
Кроме того diet шаблоны компилируются один раз при компиляции приложения. А го шаблоны судя по всему парсятся при каждом запросе — нужно кешировать результат парсинга.
Насчёт больше/меньше текста: значение Document Length одинаково, оба приложения отдают 182 байта.
А вот по поводу шаблонов в го ничего сказать не могу. Может быть вы подскажите как реализовать «честное» сравнение?
у D — «Total transferred: 16450000 bytes»
у Go — «Total transferred: 14950000 bytes»
может быть Go какие-либо заголовки не передаёт или vibe.d что-то большее передаёт (как я понимаю у него много функционала из коробки, может быть стоит что-то отключить, если есть возможность)
func main() {
t, _ := template.ParseFiles(«index.html»)
http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
p := Page{Var:«hello habr»}
t.Execute(w, p)
});
http.ListenAndServe(":8100", nil);
}
И всё-таки хочется конкретных опций компилятора (inline, O3, nobounds-check вкл или выкл).
P.S. минус не мой, не подумайте.
https://www.techempower.com/benchmarks/#section=data-r12&hw=peak&test=fortune&l=cnc
vibe 0.7.28 вышел 27 февраля (hot fix версия), а этот тест производился 25 февраля
возможно эти 2 бага сильно влияли на производительность
Собрать Ваш код на D не удалось. (та и время тратить не хотел)
Проведя тест(test1.go) на среднестатистическом сервере, у меня получилось ~16970.795 rps
Первое что бросается в глаза — отсутствие url роутера.
Без роутера(test2.go) получаем +~88.51 rps.
Во время сборки кода на D, заметил интересную строку: Compiling diet template 'index.dt'…
Будем считать, что D загружает шаблон в память.
Третей тест (test3.go) показывает ~55588.8625 rps, что дает ~+38618 rps
Исходя из Ваших тестов, возьмем среднепальцеве число производительности кода D в 17000 rps.
Если этот код на D загружает все в память, то этот тест показывает, на сколько в хлам GO разбивает производительность D. Это выглядит как 17000 vs 55000 rps
Сам код: github.com/vitalvas/go-benchmark
На Go запускал как и Ваш, так и свой. Результаты тестов в репозиторию
Хотя теоретически D — должен работать быстрее GO.
В go пожертвовали некоторою производительностью для простоты.
Хотя теоретически D — должен работать быстрее GO.
мне хотелось поднять вопрос не «кто быстрее в целом» (который я для других языков уже пытался поднять), а именно для веб… и тут, по всей видимости, компилятор и язык не будут играть большой роли, а будут играть: подход к сборке мусора, архитектура библиотеки (в vibe радуют compile-time шаблоны страниц), алгоритмы роутинга и тд
Хотелось проверить всё в целом, в сумме (кроме работы с базой данных). На самом деле я думал D проиграет в веб значительно, просто было интересно во сколько раз, но оказалось не всё так просто.
Для тех, кто всё же захочет собрать код на D, последовательность действий такова:
- Создаём проект на VibeD: dub init go-vs-d vibe.d
- Для студии можем сгенерить солюшен: dub generate visuald
- Исходники помещаем в source/app.d
- Шаблоны в views/
- Билдим и запускаем: dub --build=release
1. Начинаем сравнивать только когда выявлены реально важные критерии. Например, где-то важно потребление памяти, где-то — поддерживаемость или «интуитивная понятность» (напр. у VBScript). Критерии «от балды» — не интересны, особенно когда сравнивают МИКРОсекунды в вебе, где страницу можно ждать секундами! К чему там скорость??
2. До сих пор один из важных критериев языков — поддерживаемость, которая вытекает из простоты и выразительная мощность, которая должна соблюдать баланс с простотой. Писать на очень простом языке — нудно (спросите джабистов), на оч выразительном — мозг вывихнешь (любители Хаскеля не поняли вопроса :) ). Мне кажется, у D в этом плане хороший баланс — море простых конструкций, одновременно с мощной библиотекой.
Поэтому «для веба» я бы сразу взял Ди и критерием была бы быстрота написания и понятность кода. Веб — это не место для экономии микросекунд или, ещё смешнее, экономия килобайт в ГИГАБАЙТОВЫХ серверах. Есть нагрузка — почти всегда дешевле «оптимизировать вширь железом», чем насиловать программиста «ну ещё пару мегабайт!». Особенно зная, что есть не так много разных способов написания алгоритма или использования библиотеки (т.е. не всегда есть возможность что-то вообще выжать).
Веб — это не место для экономии микросекунд
Вы хоть одно нагруженное приложение в жизни писали?
Я не могу рассказывать о нагрузках типичного форума а-ля rsdn, потому что не имею отношения к разработке типичных форумов а-ля rdsn. Зато имею отношение к разработке нескольких продуктов с нагрузками в тысячи и десятки тысяч запросов в секунду. И не по наслышке знаю, как сэкономленные где-нибудь в дальнем углу кода 10-20 миллисекунд могут сэкономить десяток тысяч долларов в месяц на железе.
Поскольку мне было интересно, откуда взялось ваше утверждение, я задал простой вопрос — «Вы хоть одно нагруженное приложение в жизни писали?». Он короткий и не несёт в себе никаких эмоций.
Как я могу предположить теперь — нет, не писали. А если я прав (если я прав) — получается, в предмете вы ни черта не понимаете, о чём говорите — не знаете, но Веское Мнение имеете.
П — Профессионализм.
И должен вам сказать — это такая страшная редкость.
И если уж тестировать Go на возможность написания именно таких приложений, то тестировать грамотно — используя fasthttp.
Я иной раз думаю всякое. Вот как так получается, что Microsoft Word, который в 1999 году работал на 486м процессоре, влезая в 16 мегабайт памяти, сейчас отжирает половину ресурсов и еле ворочается на восьмиядерном ксеоне? Что за индус мог написать калькулятор для убунты, который для своей работы тянет сотню пакетов ради красивой отрисовки кнопочек? Какая такая волшебная сила превращает танчики, которые работали на денди, в многомегабайтного монстра, за полчаса высасывающего батарейку на топовом смартфоне? Что за мировой заговор новостных сайтов, которые состоят из текста и картинок и при этом отжирают по гигабайту в браузере?
И периодически убеждаюсь, что нет ни чудес, ни волшебства, ни индусов, ни масонского заговора. Есть лишь Правильные программисты, которые презирают всяких пижонов, заботящихся о производительности своих продуктов. Правильным программистам не нужны бенчмарки. Им не надо знать, что быстрее в конкретной задаче — D, Go, плюсы или вообще пхп. Это всё вторично.
Скорость работы везде и особенно в вебе — для пижонов. Ведь если вы пишете не один-на-миллион поисковик/соцсеть/биллинг, а сайт «Сады и парки Норильска», то можно это делать спустя рукава и как-нибудь. А когда всё начинает тупить — так это не кодер неподходящий инструмент выбрал, это хостер кривой. Голову включать не надо, надо масштабироваться железом.
Аминь.
Вы убедились, что частота процессора не менялась на протяжении всех тестов?
t, _ := template.ParseFiles("index.html")
пересоздается на каждый запрос. Разве вы так будете писать в реальном проекте? А если нет, то зачем такое мерять?https://dlang.org/spec/garbage.html
Это неверное утверждение. Вопрос раскидывания файберов по ядрам очень сложный и на сегодняшний день я скорее считаю, что правильнее, когда планировщик загружает ядра ближе к 85%, оставляя свободные ядра.
Это дает возможность линуксу запустить что-то ещё на сервере.
Сравнение прозводительности D и Go для веб