Нашёл один момент vibe 0.7.28 вышел 27 февраля (hot fix версия), а этот тест производился 25 февраля
возможно эти 2 бага сильно влияли на производительность
я не против минусов, только когда я понимаю за что
по сути вы правы, надо было приводить все параметры
все 3 варианта собирались с помощью dub --build=release
ps: а насчёт libevent я добавил в текст статьи ещё когда проверял сборки с ldc и gdc
Прошу заметить, что я не пытался сделать максимально производительный или правильный код, а пытался сделать эквивалентный (в силу своих познаний) код на двух разных языках.
Хотя теоретически D — должен работать быстрее GO.
мне хотелось поднять вопрос не «кто быстрее в целом» (который я для других языков уже пытался поднять), а именно для веб… и тут, по всей видимости, компилятор и язык не будут играть большой роли, а будут играть: подход к сборке мусора, архитектура библиотеки (в vibe радуют compile-time шаблоны страниц), алгоритмы роутинга и тд
Хотелось проверить всё в целом, в сумме (кроме работы с базой данных). На самом деле я думал D проиграет в веб значительно, просто было интересно во сколько раз, но оказалось не всё так просто.
Правильно ли я понял, что Вы сейчас прооперировали среднепальцевыми значениями, даже не запустив код (ни мой, ни тот, корректный, который Вы написали)?
Мне кажется шаблонизатор тут малую роль играет, там очень мало кода (подставляется лишь 1 переменная в коротком шаблоне). Я всё-таки пытался сравнить именно работу остальной части приложений.
Не думаю, что убрав так называемый «мусор» можно добиться хоть какого-нибудь прироста производительности, так как это влияет только на время компиляции, а не на работу приложения. Но на всякий случай измерил и ощутимой разницы не обнаружил (разница в пределах 5%, от запуска к запуску).
Насчёт больше/меньше текста: значение Document Length одинаково, оба приложения отдают 182 байта.
А вот по поводу шаблонов в го ничего сказать не могу. Может быть вы подскажите как реализовать «честное» сравнение?
4 секунды мало, потому что сборщик мусора не успевает включиться в бой?
А вторую часть не до конца понял. Веб-сервера не встроены ни в D ни в Go — это библиотечные реализации. В целом я их хотел их сравнить: кто шустрее, меньше памяти ест, процессор грузит. Или вы имели ввиду что ещё можно что-то сравнивать в производительности веб приложений? Я только начинаю этим заниматься, поэтому не знаю, какие ещё могут быть критерии.
Не совсем понимаю значение, этого флага: если соединение остаётся поднятым сервер должен меньше работы выполнять?
Когда соединение остаётся открытым? Например если я установлю связь с сервером через websocket?
Прогнал такой тест: ab -k -c500 -n100000 http://localhost:8100/
dlang
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)
golang
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)
Думаю можно обойтись только делегатами и вынести в отдельную функцию создание класса.
Правка
import std.stdio;
import std.traits;
auto f(string s) {
return s.length;
}
auto g(string s) {
return 2*s.length;
}
struct S {
auto getClosure() {
return (string s) { return 3*s.length; };
}
}
class X(R, A...) { // три точки значат, что можно это не один тип может быть, а кортеж типов
R delegate(A) g;
A a;
this(R delegate(A) g, A a) {
this.g = g;
this.a = a;
}
R run() { return g(a); }
}
auto newX(F,Args...)( F fnc, Args args )
if( isCallable!F && __traits(compiles, { fnc(args); }) )
// F может быть даже объектом с методом opCall
// с помощью __traits мы проверяем можем ли вызывать эту fnc с такими аргументами
{
return new X!( ReturnType!F, ParameterTypeTuple!F ) // тип объекта всё равно нужно задавать
( (Args a){ return fnc(a); }, args );
// в любом случае создаём делегат
}
void main() {
auto x = newX(&f, "a");
auto y = newX(&g, "ab");
auto s = S();
auto d = s.getClosure();
auto z = newX(d, "abc");
auto Z = [x,y,z];
foreach(t; Z) {
writeln(t.run());
}
}
Вариант функций создания
Вместо одной универсальной можно написать 2 специальные
auto newX(R,Args...)( R delegate(Args) fnc, Args args )
{ return new X!(R,Args)( fnc, args ); }
auto newX(R,Args...)( R function(Args) fnc, Args args )
{ return new X!(R,Args)( (Args a){ return fnc(a); }, args ); }
Можно озвучить более полную задачу? А то есть маленькое чувство, что Вы стреляете из пушки по воробьям.
Другой подход
import std.stdio;
import std.traits;
auto f(string s) {
return s.length;
}
auto g(string s) {
return 2*s.length;
}
struct S {
auto getClosure() {
return (string s) { return 3*s.length; };
}
}
auto apply(F,Args...)( F fnc, Args args )
if( isCallable!F && __traits(compiles,fnc(args)) )
{ return { return fnc(args); }; }
void main() {
auto x = apply(&f, "a");
auto y = apply(&g, "ab");
auto s = S();
auto d = s.getClosure();
auto z = apply(d, "abc");
auto Z = [x,y,z];
foreach(t; Z) {
writeln(t());
}
}
Не совсем понял аргумент. Если мы говорим про многопоточное программирование с блокировками в общем, то оно само по себе не является простым занятием. Передача сообщений это лишь способ снижения сложности, а конкретней, способ уйти от таких взаимоблокирующих вызовов. Многопоточное программирование без блокировок ещё более сложная задача, что подтверждает Ваш пример (кстати, весьма познавательный). Да и нет у него особой специфики в D. Та же самая функция cas и все те же проблемы, что и, например, в С++. А от велосипедов уйти никогда не удасться на 100%, так как std.concurrency не может покрыть все задачи, а реализовывать непокрытые как-то нужно. Поход, описанный мной, показывает только особенности способа создания очереди сообщений именно в D. Я не говорил, что надо делать всегда именно так. Выбор всегда остаётся за програмистом.
vibe 0.7.28 вышел 27 февраля (hot fix версия), а этот тест производился 25 февраля
возможно эти 2 бага сильно влияли на производительность
по сути вы правы, надо было приводить все параметры
все 3 варианта собирались с помощью
dub --build=release
ps: а насчёт libevent я добавил в текст статьи ещё когда проверял сборки с ldc и gdc
dlang
dconf
мне хотелось поднять вопрос не «кто быстрее в целом» (который я для других языков уже пытался поднять), а именно для веб… и тут, по всей видимости, компилятор и язык не будут играть большой роли, а будут играть: подход к сборке мусора, архитектура библиотеки (в vibe радуют compile-time шаблоны страниц), алгоритмы роутинга и тд
Хотелось проверить всё в целом, в сумме (кроме работы с базой данных). На самом деле я думал D проиграет в веб значительно, просто было интересно во сколько раз, но оказалось не всё так просто.
Насчёт больше/меньше текста: значение Document Length одинаково, оба приложения отдают 182 байта.
А вот по поводу шаблонов в го ничего сказать не могу. Может быть вы подскажите как реализовать «честное» сравнение?
А вторую часть не до конца понял. Веб-сервера не встроены ни в D ни в Go — это библиотечные реализации. В целом я их хотел их сравнить: кто шустрее, меньше памяти ест, процессор грузит. Или вы имели ввиду что ещё можно что-то сравнивать в производительности веб приложений? Я только начинаю этим заниматься, поэтому не знаю, какие ещё могут быть критерии.
Слева D, справа Go
Когда соединение остаётся открытым? Например если я установлю связь с сервером через 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 раза.
но я добавил это в desmath
Можно озвучить более полную задачу? А то есть маленькое чувство, что Вы стреляете из пушки по воробьям.