Browse Source

Revert 4635 and fix dlang vibed tests (#4640)

* Revert "Remove D/vibed (#4635)"

This reverts commit 956d1ef22ce2eb70aae93f2ecf16ba6ca34e2f9b.

* upgrade to latest version of compiler and packages

* Use fixed version of d compilers

* replace delete with destroy
Daniel Kozak 6 years ago
parent
commit
ef7d6e08cd

+ 34 - 0
frameworks/D/vibed/README.md

@@ -0,0 +1,34 @@
+# Vibe.D Benchmarking Test
+
+This is the Vibe.D portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test controller/view](source/app.d)
+
+### Data-Store/Database Mapping Test
+
+* [DB test controller/model](source/app.d)
+
+## Infrastructure Software Versions
+The tests were run with:
+* [Vibe.D v0.8.0-beta.5](http://vibed.org/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost:8080/json
+
+### Plaintext Test
+
+http://localhost:8080/plaintext
+
+### Data-Store/Database Mapping Test
+
+MongoRaw:
+http://localhost:8080/db
+
+### Variable Query Test
+
+MongoDB Raw:
+http://localhost:8080/queries?queries=5

+ 97 - 0
frameworks/D/vibed/benchmark_config.json

@@ -0,0 +1,97 @@
+{
+  "framework": "vibed",
+  "tests": [{
+    "default": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "plaintext_url": "/plaintext",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MongoDB",
+      "framework": "vibe.d",
+      "language": "D",
+      "flavor": "DLang2",
+      "orm": "Micro",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "vibe.d",
+      "notes": "",
+      "versus": "vibed"
+    },
+    "dmd-pgsql": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "plaintext_url": "/plaintext",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "Postgres",
+      "framework": "vibed",
+      "language": "D",
+      "flavor": "DLang2",
+      "orm": "Raw",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "vibe.d-pgsql",
+      "notes": "",
+      "versus": "vibed"
+    },
+    "ldc": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "plaintext_url": "/plaintext",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MongoDB",
+      "framework": "vibed",
+      "language": "D",
+      "flavor": "DLang2",
+      "orm": "Micro",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "vibe.d-ldc",
+      "notes": "",
+      "versus": "vibed"
+    },
+    "ldc-pgsql": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "plaintext_url": "/plaintext",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "Postgres",
+      "framework": "vibed",
+      "language": "D",
+      "flavor": "DLang2",
+      "orm": "Raw",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "vibe.d-ldc-pgsql",
+      "notes": "",
+      "versus": "vibed"
+    }
+  }]
+}

+ 36 - 0
frameworks/D/vibed/dub.json

@@ -0,0 +1,36 @@
+{
+  "name": "fwb",
+  "description": "A simple vibe.d server application.",
+  "copyright": "Copyright © 2015, jin",
+  "authors": [
+    "jin",
+    "Sönke Ludwig"
+  ],
+  "dependencies": {
+    "vibe-d": "0.8.5",
+    "mir-random": "2.2.3",
+    "vibe-d:tls": "0.8.5"
+  },
+  "targetType": "executable",
+  "sourcePaths": [],
+  "subConfigurations": {
+    "vibe-d": "vibe-core",
+    "vibe-d:tls": "notls"
+  },
+  "versions": [
+    "VibeManualMemoryManagement"
+  ],
+  "configurations": [
+    {
+      "name": "mongodb",
+      "mainSourceFile": "source/mongodb.d"
+    },
+    {
+      "name": "postgresql",
+      "mainSourceFile": "source/postgresql.d",
+      "dependencies": {
+        "vibe-d-postgresql": "2.0.2"
+      }
+    }
+  ]
+}

+ 26 - 0
frameworks/D/vibed/dub.selections.json

@@ -0,0 +1,26 @@
+{
+	"fileVersion": 1,
+	"versions": {
+		"botan": "1.12.10",
+		"botan-math": "1.0.3",
+		"derelict-pq": "4.0.0-alpha.2",
+		"derelict-util": "3.0.0-beta.2",
+		"diet-ng": "1.5.0",
+		"dpq2": "1.0.10",
+		"eventcore": "0.8.42",
+		"libasync": "0.8.4",
+		"libevent": "2.0.2+2.0.16",
+		"memutils": "0.4.13",
+		"mir-algorithm": "3.3.11",
+		"mir-core": "0.2.2",
+		"mir-linux-kernel": "1.0.1",
+		"mir-random": "2.2.3",
+		"money": "2.3.0",
+		"openssl": "1.1.6+1.0.1g",
+		"stdx-allocator": "2.77.5",
+		"taggedalgebraic": "0.11.3",
+		"vibe-core": "1.6.2",
+		"vibe-d": "0.8.5",
+		"vibe-d-postgresql": "2.0.2"
+	}
+}

+ 176 - 0
frameworks/D/vibed/source/mongodb.d

@@ -0,0 +1,176 @@
+import vibe.core.core;
+import vibe.db.mongo.mongo;
+import vibe.http.router;
+import vibe.http.server;
+import vibe.web.web;
+
+import mir.random : unpredictableSeedOf;
+import mir.random.variable : UniformVariable;
+import mir.random.engine.xorshift : Xorshift;
+
+import std.conv : ConvException, to;
+import std.array;
+
+enum worldSize = 10000;
+
+
+void main()
+{
+	runWorkerTaskDist(&runServer);
+	runApplication();
+}
+
+void runServer()
+{
+	auto router = new URLRouter;
+	router.registerWebInterface(new WebInterface);
+	router.rebuild();
+
+	auto settings = new HTTPServerSettings;
+	settings.options |= HTTPServerOption.reusePort;
+	settings.port = 8080;
+	listenHTTP(settings, router);
+}
+
+class WebInterface {
+	private {
+		MongoCollection _worldCollection;
+		MongoCollection _fortuneCollection;
+		UniformVariable!uint _uniformVariable;
+		Xorshift _gen;
+	}
+
+	this()
+	{
+		import std.process : environment;
+		auto db = connectMongoDB("tfb-database");
+		_worldCollection = db.getCollection("hello_world.world");
+		_fortuneCollection = db.getCollection("hello_world.fortune");
+
+		_gen = Xorshift(unpredictableSeedOf!uint);
+		_uniformVariable = UniformVariable!uint(1, worldSize);
+	}
+
+	// GET /
+	void get()
+	{
+		render!"index.dt";
+	}
+
+	// GET /json
+	void getJson(HTTPServerResponse res)
+	{
+		// NOTE: the status and content type parameters are optional, but we need
+		// to specify them, because the default content type is "application/json; charset=UTF8"
+		res.writeJsonBody(Message("Hello, World!"), HTTPStatus.ok, "application/json");
+	}
+
+	// GET /db
+	void getDB(HTTPServerResponse res)
+	{
+		struct Q { int _id; }
+		auto query = Q(_uniformVariable(_gen));
+		auto w = WorldResponse(_worldCollection.findOne!World(query));
+		res.writeJsonBody(w, HTTPStatus.ok, "application/json");
+	}
+
+	// GET /queries?queries=...
+	void getQueries(HTTPServerResponse res, string queries)
+	{
+		import std.algorithm : min, max;
+
+		// Convert the "queries" parameter to int and ignore any conversion errors
+		// Note that you'd usually declare queries as int instead. However, the
+		// test required to gracefully handle errors here.
+		int count = 1;
+		try count = min(max(queries.to!int, 1), 500);
+		catch (ConvException) {}
+
+		// assemble the response array
+		scope data = new WorldResponse[count];
+		foreach (ref w; data) {
+			static struct Q { int _id; }
+			auto query = Q(_uniformVariable(_gen));
+			w = WorldResponse(_worldCollection.findOne!World(query));
+		}
+
+		// write response as JSON
+		res.writeJsonBody(data, HTTPStatus.ok, "application/json");
+	}
+
+	// GET /fortunes
+	void getFortunes()
+	{
+		import std.algorithm : map, sort;
+
+		FortuneResponse[] data;
+		data = _fortuneCollection.find!Fortune().map!(f => FortuneResponse(f)).array;
+		data ~= FortuneResponse(Fortune(0, "Additional fortune added at request time."));
+		data.sort!((a, b) => a.message < b.message);
+		render!("fortunes.dt", data);
+	}
+
+	// GET /updates?queries=...
+	void getUpdates(HTTPServerResponse res, string queries)
+	{
+		import std.algorithm : min, max;
+
+		int count = 1;
+		try count = min(max(queries.to!int, 1), 500);
+		catch (ConvException e) {}
+
+		scope data = new WorldResponse[count];
+		foreach (ref w; data) {
+			static struct Q { int _id; }
+			auto query = Q(_uniformVariable(_gen));
+			w = WorldResponse(_worldCollection.findOne!World(query));
+
+			// update random number
+			w.randomNumber = _uniformVariable(_gen);
+
+			// persist to DB
+			static struct US {
+				double randomNumber;
+			}
+			static struct U {
+				@name("$set") US set;
+			}
+			_worldCollection.update(query, U(US(w.randomNumber)));
+		}
+
+		// write response as JSON
+		res.writeJsonBody(data, HTTPStatus.ok, "application/json");
+	}
+
+	// GET /plaintext
+	void getPlaintext(HTTPServerResponse res)
+	{
+		res.writeBody("Hello, World!", HTTPStatus.ok, "text/plain");
+	}
+}
+
+struct Message {
+	string message;
+}
+
+struct World {
+	double _id;
+	double randomNumber;
+}
+
+struct Fortune {
+	double _id;
+	string message;
+}
+
+struct WorldResponse {
+	this(World w) { this.id = cast(int)w._id; this.randomNumber = cast(int)w.randomNumber; }
+	int id;
+	int randomNumber;
+}
+
+struct FortuneResponse {
+	this(Fortune f) { this.id = cast(int)f._id; this.message = f.message; }
+	int id;
+	string message;
+}

+ 188 - 0
frameworks/D/vibed/source/postgresql.d

@@ -0,0 +1,188 @@
+import vibe.core.core;
+import vibe.http.router;
+import vibe.http.server;
+import vibe.web.web;
+import vibe.db.postgresql;
+
+import mir.random : unpredictableSeedOf;
+import mir.random.variable : UniformVariable;
+import mir.random.engine.xorshift : Xorshift;
+
+import std.conv : ConvException, to;
+import std.array;
+
+enum worldSize = 10000;
+enum poolSize = 256;
+
+PostgresClient client;
+
+shared static this()
+{
+	import derelict.pq.pq;
+	import derelict.util.exception : ShouldThrow;
+	ShouldThrow myMissingSymCB( string symbolName ) { return ShouldThrow.No; }
+	DerelictPQ.missingSymbolCallback = &myMissingSymCB;
+}
+
+void main()
+{
+	runWorkerTaskDist(&runServer);
+	runApplication();
+}
+
+void runServer()
+{
+	auto router = new URLRouter;
+	router.registerWebInterface(new WebInterface);
+	router.rebuild();
+
+	auto settings = new HTTPServerSettings;
+	settings.options |= HTTPServerOption.reusePort;
+	settings.port = 8080;
+	listenHTTP(settings, router);
+}
+
+class WebInterface {
+	private {
+		UniformVariable!uint _uniformVariable;
+		Xorshift _gen;
+	}
+
+	this()
+	{
+		_gen = Xorshift(unpredictableSeedOf!uint);
+		_uniformVariable = UniformVariable!uint(1, worldSize);
+	}
+
+	// GET /
+	void get()
+	{
+		render!"index.dt";
+	}
+
+	// GET /json
+	void getJson(HTTPServerResponse res)
+	{
+		// NOTE: the status and content type parameters are optional, but we need
+		// to specify them, because the default content type is "application/json; charset=UTF8"
+		res.writeJsonBody(Message("Hello, World!"), HTTPStatus.ok, "application/json");
+	}
+
+	// GET /db
+	void getDB(HTTPServerResponse res)
+	{
+		auto conn = client.lockConnection();
+		scope(exit)	destroy(conn);
+
+		immutable id = _uniformVariable(_gen);
+		immutable query = "SELECT randomNumber FROM world WHERE id = " ~  id.to!string;
+		immutable result = conn.execStatement(query, ValueFormat.BINARY).rangify.front;
+		auto w = WorldResponse(id, result[0].as!PGinteger);
+		res.writeJsonBody(w, HTTPStatus.ok, "application/json");
+	}
+
+	// GET /queries?queries=...
+	void getQueries(HTTPServerResponse res, string queries)
+	{
+		import std.algorithm : min, max;
+
+		auto conn = client.lockConnection();
+		scope(exit)	destroy(conn);
+
+		// Convert the "queries" parameter to int and ignore any conversion errors
+		// Note that you'd usually declare queries as int instead. However, the
+		// test required to gracefully handle errors here.
+		int count = 1;
+		try count = min(max(queries.to!int, 1), 500);
+		catch (ConvException) {}
+
+		// assemble the response array
+		scope data = new WorldResponse[count];
+		foreach (ref w; data) {
+			immutable id = _uniformVariable(_gen);
+			immutable query = "SELECT randomNumber FROM world WHERE id = " ~  id.to!string;
+			immutable result = conn.execStatement(query, ValueFormat.BINARY).rangify.front;
+			w = WorldResponse(id, result[0].as!PGinteger);
+		}
+
+		// write response as JSON
+		res.writeJsonBody(data, HTTPStatus.ok, "application/json");
+	}
+
+	// GET /fortunes
+	void getFortunes()
+	{
+		import std.algorithm : map, sort;
+
+		auto conn = client.lockConnection();
+		scope(exit)	destroy(conn);
+
+		FortuneResponse[] data;
+		immutable query = "SELECT id, message::text FROM Fortune";
+		auto result = conn.execStatement(query, ValueFormat.BINARY).rangify;
+		data = result.map!(f => FortuneResponse(f[0].as!PGinteger, f[1].as!PGtext)).array;
+		data ~= FortuneResponse(0, "Additional fortune added at request time.");
+		data.sort!((a, b) => a.message < b.message);
+		render!("fortunes.dt", data);
+	}
+
+	// GET /updates?queries=...
+	void getUpdates(HTTPServerResponse res, string queries)
+	{
+		import std.algorithm : min, max;
+
+		auto conn = client.lockConnection();
+		scope(exit)	destroy(conn);
+
+		int count = 1;
+		try count = min(max(queries.to!int, 1), 500);
+		catch (ConvException e) {}
+
+		scope data = new WorldResponse[count];
+		foreach (ref w; data) {
+			immutable id = _uniformVariable(_gen);
+			immutable sid = id.to!string;
+			immutable query = "SELECT randomNumber FROM world WHERE id = " ~  sid;
+			immutable result = conn.execStatement(query, ValueFormat.BINARY).rangify.front;
+			w = WorldResponse(id, result[0].as!PGinteger);
+
+			// update random number
+			w.randomNumber = _uniformVariable(_gen);
+
+			// persist to DB
+			conn.execStatement("UPDATE world SET randomNumber = " ~ w.randomNumber.to!string ~ "  WHERE id = " ~ sid);
+
+		}
+
+		// write response as JSON
+		res.writeJsonBody(data, HTTPStatus.ok, "application/json");
+	}
+
+	// GET /plaintext
+	void getPlaintext(HTTPServerResponse res)
+	{
+		res.writeBody("Hello, World!", HTTPStatus.ok, "text/plain");
+	}
+}
+
+struct Message {
+	string message;
+}
+
+struct WorldResponse {
+	int id;
+	int randomNumber;
+}
+
+struct FortuneResponse {
+	int id;
+	string message;
+}
+
+static this()
+{
+	import std.process : environment;
+	auto connectionInfo = "host=tfb-database port=5432 "
+						~ "dbname=hello_world  user=benchmarkdbuser password=benchmarkdbpass";
+	client = new PostgresClient(connectionInfo, poolSize);
+}

+ 10 - 0
frameworks/D/vibed/vibed-dmd-pgsql.dockerfile

@@ -0,0 +1,10 @@
+FROM dlang2/dmd-ubuntu:2.085.1
+
+WORKDIR /dlang/app
+COPY . .
+
+RUN apt update -yqq && apt install -yqq libpq-dev zlib1g-dev
+
+RUN dub build -b release-nobounds --config=postgresql
+
+CMD ["/dlang/app/fwb"]

+ 10 - 0
frameworks/D/vibed/vibed-ldc-pgsql.dockerfile

@@ -0,0 +1,10 @@
+FROM dlang2/ldc-ubuntu:1.15.0
+
+WORKDIR /dlang/app
+COPY . .
+
+RUN apt update -yqq && apt install -yqq libpq-dev zlib1g-dev
+
+RUN dub build -b release-nobounds --compiler=ldc2 --config=postgresql
+
+CMD ["/dlang/app/fwb"]

+ 10 - 0
frameworks/D/vibed/vibed-ldc.dockerfile

@@ -0,0 +1,10 @@
+FROM dlang2/ldc-ubuntu:1.15.0
+
+WORKDIR /dlang/app
+COPY . .
+
+RUN apt update -yqq && apt install -yqq zlib1g-dev
+
+RUN dub build -b release-nobounds --compiler=ldc2 --verbose
+
+CMD ["/dlang/app/fwb"]

+ 10 - 0
frameworks/D/vibed/vibed.dockerfile

@@ -0,0 +1,10 @@
+FROM dlang2/dmd-ubuntu:2.085.1
+
+WORKDIR /dlang/app
+COPY . .
+
+RUN apt update -yqq && apt install -yqq libpq-dev zlib1g-dev
+
+RUN dub build -b release-nobounds --verbose
+
+CMD ["/dlang/app/fwb"]

+ 15 - 0
frameworks/D/vibed/views/fortunes.dt

@@ -0,0 +1,15 @@
+extends layout
+
+block head
+	title Fortunes
+
+block body
+	table
+		tr
+			th id
+			th message
+		- foreach (f; data)
+			tr
+				td= f.id
+				td= f.message
+

+ 19 - 0
frameworks/D/vibed/views/index.dt

@@ -0,0 +1,19 @@
+doctype html
+html
+  head
+    style a { display: block }
+  body
+    ul
+      li
+        a(href="/generate-world") generate world
+      li
+        a(href="/generate-fortunes") generate fortunes
+    ol
+      li
+        a(href="/json") json stringify
+      li
+        a(href="/db") single query
+      li
+        a(href="/queries?queries=5") multiple queries
+      li
+        a(href="/plaintext") plain text

+ 7 - 0
frameworks/D/vibed/views/layout.dt

@@ -0,0 +1,7 @@
+doctype html
+html
+	head
+		block head
+	body
+		block body
+