Pull to refresh

Сравнение прозводительности D и Go для веб

Reading time 4 min
Views 18K
Доброго времени суток, хабр!

Так как мне скоро предстоит разрабатывать веб-приложение, а писать на интерпретирумых языках как-то нет желания, тем более, что есть такие ЯП как D и Go, возникло желание сравнить их производительность при работе с веб (в сети не нашёл тестов, которые были бы свежими). Для D это vibe.d, а для Go, как я понял, не используются фреймворки. Так как Go я знаю менее чем «никак» решил не выпендриваться: тестовые приложения просто отдают страничку с некоторым текстом (ни баз данных, ни сложного роутинга, ни изображений).

Нагрузка давалась с помощью Apache Benchmark.



Приложение на D это стандартное vibe приложение, нас будут интересовать только
source/app.d
import vibe.d;

shared static this()
{
    auto settings = new HTTPServerSettings;
    settings.options |= HTTPServerOption.distribute; // без этой настройки vibe однопоточен
    settings.port = 8101;
    settings.bindAddresses = ["::1", "127.0.0.1"];

    listenHTTP(settings, &index);
}

void index(HTTPServerRequest req, HTTPServerResponse res)
{
    auto var = "hello habr";
    res.render!("index.dt",var);
}
и
views/index.dt
html
  head
  body
    h1 Привет, Хабр!

    p D is a systems programming language with C-like syntax.

    = var
сборка: dub build --build=release

В Go приложении нас интересуют соответствующие файлы
site_test_go.go
package main

import (
    "html/template"
    "net/http"
)

type Page struct {
    Var string
}

func indexViewer(w http.ResponseWriter, r *http.Request) {
    p := Page{Var:"hello habr"}
    t, _ := template.ParseFiles("index.html")
    t.Execute(w, p)
}

func main() {
    http.HandleFunc("/", indexViewer);
    http.ListenAndServe(":8100", nil);
}

и
index.html
<h1>Привет, Хабр!</h1>

<p>Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.</p>

<div>
    {{.Var}}
</div>

сборка: go build site_test_go.go

Нагрузка: ab -c200 -n50000 http://localhost:8101/ (8100 для site_test_go)

Начнём

Apache Benchmark

Немного различный код index файлов был сделан для соответствия Document Length (видимо vibe передаёт что-то в заголовке ответа)
dlang golang
Server Software: vibe.d/0.7.28
Server Hostname: localhost
Server Port: 8101

Document Path: /
Document Length: 182 bytes

Concurrency Level: 200
Time taken for tests: 4.481 seconds
Complete requests: 50000
Failed requests: 0
Total transferred: 16450000 bytes
HTML transferred: 9100000 bytes
Requests per second: 11157.90 [#/sec] (mean)
Time per request: 17.925 [ms] (mean)
Time per request: 0.090 [ms] (mean, across all concurrent requests)
Transfer rate: 3584.91 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 8 33.2 7 1009
Processing: 2 10 3.7 9 207
Waiting: 1 8 3.5 7 205
Total: 3 18 33.4 17 1020

Percentage of the requests served within a certain time (ms)
50% 17
66% 18
75% 18
80% 18
90% 19
95% 23
98% 29
99% 30
100% 1020 (longest request)

Server Software:
Server Hostname: localhost
Server Port: 8100

Document Path: /
Document Length: 182 bytes

Concurrency Level: 200
Time taken for tests: 4.263 seconds
Complete requests: 50000
Failed requests: 0
Total transferred: 14950000 bytes
HTML transferred: 9100000 bytes
Requests per second: 11728.36 [#/sec] (mean)
Time per request: 17.053 [ms] (mean)
Time per request: 0.085 [ms] (mean, across all concurrent requests)
Transfer rate: 3424.59 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 8 14.9 7 1011
Processing: 2 9 2.3 9 211
Waiting: 1 7 2.4 7 210
Total: 10 17 15.1 16 1020

Percentage of the requests served within a certain time (ms)
50% 16
66% 17
75% 18
80% 18
90% 19
95% 20
98% 21
99% 22
100% 1020 (longest request)



Память

Замер производился с помощью gnome-system-monitor
dlang golang
до первого запроса memory: 680.0KiB
virtual: 907.5MiB
resident: 10.2MiB
writable: 343.3MiB
shared: 9.5MiB
memory: 888.0KiB
virtual: 110.8MiB
resident: 5.2MiB
writable: 35.7MiB
shared: 4.4MiB
после запуска ab memory: 19.2MiB
virtual: 9.5GiB
resident: 28.7MiB
writable: 9.0GiB
shared: 9.6MiB
memory: 6.5MiB
virtual: 1.3GiB
resident: 12.5MiB
writable: 1.0GiB
shared: 5.9MiB


Загрузка процессора

Замер производился с помощью gnome-system-monitor
dlang golang


Версии ПО

apr-util-1.5.4-1.fc22.x86_64

DMD64 D Compiler v2.071.0
DUB version 0.9.25, built on May 22 2016
vibe 0.7.28

go version go1.5.4 linux/amd64

Выводы

Производительность инструментов практически не различается (чему я удивлён, на самом деле).
Огорчило потребление памяти у D: практически в 3 раза больше чем у Go.
Исходя из графиков загруженности процессора, можно сделать вывод: планировщик заданий в Go устроен лучше — сразу распределяет нагрузку на ядра поровну, но в среднем загрузка ЦП у D ниже.
Стоит отметить, что приложение на D компилируется дольше (для веб разработки это может быть неприятным моментом).

PS: это мой первый эксперимент с производительностью веб (вообще пока не хорошо с веб знаком), так что буду очень рад, если вы укажите на ошибки в способе измерения и/или начальных условиях =)



UPD:
Вот тут я понял, наверное, самоую большую ошибку, во всей этой проверке. vibe-d использует libevent2 и в этом тесте упирается производительностью именно в него (судя по результатам valgrind/callgrind). А go, как я понял, имеет собственную реализацию event-loop'а, причём сторонние библиотеки даже лучше по производительности чем из коробки (не понял как скомпилировать go, чтобы символы были в исполняемом файле для valgrind, go build -ldflags "-w" -gcflags "-N -l" не помогло).

Но всё-равно, тест конфигураций «из коробки», лично для меня был интересен.
Tags:
Hubs:
+3
Comments 57
Comments Comments 57

Articles