Browse Source

[dlang/vibed] add postgresql test (#3251)

Daniel Kozak 7 years ago
parent
commit
fd51687add

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

@@ -25,6 +25,30 @@
       "notes": "",
       "versus": "vibed"
     },
+    "dmd-pgsql": {
+      "setup_file": "setup_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": {
       "setup_file": "setup_ldc",
       "json_url": "/json",
@@ -48,6 +72,30 @@
       "display_name": "vibe.d-ldc",
       "notes": "",
       "versus": "vibed"
+    },
+    "ldc-pgsql": {
+      "setup_file": "setup_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"
     }
   }]
 }

+ 11 - 2
frameworks/D/vibed/dub.json

@@ -9,12 +9,14 @@
   "dependencies": {
     "vibe-d": "0.8.2",
     "vibe-core": "1.3.0",
-    "mir-random": "0.3.2"
+    "mir-random": "0.3.2",
+    "vibe-d:tls": "0.8.2"
   },
   "targetType": "executable",
   "sourcePaths": [],
   "subConfigurations": {
-    "vibe-d": "vibe-core"
+    "vibe-d": "vibe-core",
+    "vibe-d:tls": "notls"
   },
   "versions": [
     "VibeManualMemoryManagement"
@@ -23,6 +25,13 @@
     {
       "name": "mongodb",
       "mainSourceFile": "source/mongodb.d"
+    },
+    {
+      "name": "postgresql",
+      "mainSourceFile": "source/postgresql.d",
+      "dependencies": {
+        "vibe-d-postgresql": "1.0.0-alpha.2"
+      }
     }
   ]
 }

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

@@ -1,16 +0,0 @@
-{
-	"fileVersion": 1,
-	"versions": {
-		"botan": "1.12.9",
-		"botan-math": "1.0.3",
-		"diet-ng": "1.4.3",
-		"eventcore": "0.8.27",
-		"libasync": "0.8.3",
-		"libevent": "2.0.2+2.0.16",
-		"memutils": "0.4.9",
-		"openssl": "1.1.6+1.0.1g",
-		"taggedalgebraic": "0.10.9",
-		"vibe-core": "1.3.0",
-		"vibe-d": "0.8.2"
-	}
-}

+ 2 - 0
frameworks/D/vibed/setup_ldc.sh

@@ -6,6 +6,8 @@ fw_depends mongodb dlang
 rm -f fwb
 rm -rf .dub
 
+dub upgrade --verbose
+
 dub build -b release --compiler=ldc2 --combined --verbose
 
 ./fwb &

+ 13 - 0
frameworks/D/vibed/setup_ldc_pgsql.sh

@@ -0,0 +1,13 @@
+#!/bin/bash
+
+fw_depends postgresql dlang
+
+# Clean any files from last run
+rm -f fwb
+rm -rf .dub
+
+dub upgrade --verbose
+
+dub build -b release --compiler=ldc2 --combined --config=postgresql
+
+./fwb &

+ 13 - 0
frameworks/D/vibed/setup_pgsql.sh

@@ -0,0 +1,13 @@
+#!/bin/bash
+
+fw_depends postgresql dlang
+
+# Clean any files from last run
+rm -f fwb
+rm -rf .dub
+
+dub upgrade --verbose
+
+dub build -b release --combined --config=postgresql
+
+./fwb &

+ 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)	delete 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)	delete 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)	delete 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)	delete 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=" ~ environment.get("DBHOST", "127.0.0.1") ~ " port=5432 "
+						~ "dbname=hello_world  user=benchmarkdbuser password=benchmarkdbpass";
+	client = new PostgresClient(connectionInfo, poolSize);
+}