Browse Source

Add database test types for Amp (#3679)

Niklas Keller 7 years ago
parent
commit
5fd731660e

+ 4 - 0
frameworks/PHP/amp/benchmark_config.json

@@ -3,6 +3,9 @@
   "tests": [{
     "default": {
       "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
@@ -10,6 +13,7 @@
       "framework": "None",
       "language": "PHP",
       "flavor": "PHP7",
+      "database": "MySQL",
       "orm": "Raw",
       "platform": "None",
       "webserver": "amphp/http-server",

+ 2 - 1
frameworks/PHP/amp/composer.json

@@ -1,7 +1,8 @@
 {
     "require": {
+        "amphp/cluster": "dev-master#8ba0a45aea1ac86b368254f0868ca3568744b679",
         "amphp/http-server": "^0.8.2",
         "amphp/http-server-router": "^1",
-        "amphp/cluster": "dev-master#8ba0a45aea1ac86b368254f0868ca3568744b679"
+        "amphp/mysql": "^0.3"
     }
 }

+ 56 - 6
frameworks/PHP/amp/composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "content-hash": "28215008cf7e94aaa431bfbc416e652d",
+    "content-hash": "3bb2a266958d9be1f9efc24a2c736f34",
     "packages": [
         {
             "name": "amphp/amp",
@@ -267,16 +267,16 @@
         },
         {
             "name": "amphp/dns",
-            "version": "v0.9.12",
+            "version": "v0.9.13",
             "source": {
                 "type": "git",
                 "url": "https://github.com/amphp/dns.git",
-                "reference": "2c8133a7b4267ba570f473abe4b08b01a0c8238a"
+                "reference": "4647e5f58263ffdeff7da5c269f517cb48cff84f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/amphp/dns/zipball/2c8133a7b4267ba570f473abe4b08b01a0c8238a",
-                "reference": "2c8133a7b4267ba570f473abe4b08b01a0c8238a",
+                "url": "https://api.github.com/repos/amphp/dns/zipball/4647e5f58263ffdeff7da5c269f517cb48cff84f",
+                "reference": "4647e5f58263ffdeff7da5c269f517cb48cff84f",
                 "shasum": ""
             },
             "require": {
@@ -288,6 +288,7 @@
                 "amphp/uri": "^0.1",
                 "amphp/windows-registry": "^0.3",
                 "daverandom/libdns": "^2.0.1",
+                "ext-filter": "*",
                 "php": ">=7.0"
             },
             "require-dev": {
@@ -340,7 +341,7 @@
                 "dns",
                 "resolve"
             ],
-            "time": "2018-01-10T16:26:11+00:00"
+            "time": "2018-05-01T18:08:54+00:00"
         },
         {
             "name": "amphp/file",
@@ -705,6 +706,55 @@
             ],
             "time": "2018-03-22T19:39:52+00:00"
         },
+        {
+            "name": "amphp/mysql",
+            "version": "v0.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/amphp/mysql.git",
+                "reference": "1f4a2229832b38eeb94154296c9f3cbcb4362b38"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/amphp/mysql/zipball/1f4a2229832b38eeb94154296c9f3cbcb4362b38",
+                "reference": "1f4a2229832b38eeb94154296c9f3cbcb4362b38",
+                "shasum": ""
+            },
+            "require": {
+                "amphp/amp": "^2",
+                "amphp/socket": "^0.10"
+            },
+            "require-dev": {
+                "amphp/phpunit-util": "^1",
+                "friendsofphp/php-cs-fixer": "^2.3",
+                "phpunit/phpunit": "^6"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Amp\\Mysql\\": "lib/"
+                },
+                "files": [
+                    "lib/functions.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Bob Weinand",
+                    "email": "[email protected]"
+                },
+                {
+                    "name": "Aaron Piotrowski",
+                    "email": "[email protected]"
+                }
+            ],
+            "description": "Asynchronous parallel Mysql client built on the Amp concurrency framework",
+            "time": "2017-12-15T16:08:04+00:00"
+        },
         {
             "name": "amphp/parallel",
             "version": "v0.2.5",

+ 4 - 0
frameworks/PHP/amp/fortunes.php

@@ -0,0 +1,4 @@
+<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>
+<?php foreach ($items as $id => $fortune): ?>
+<tr><td><?php echo $id ?></td><td><?php echo \htmlspecialchars($fortune, ENT_QUOTES, 'UTF-8') ?></td></tr>
+<?php endforeach ?></table></body></html>

+ 123 - 3
frameworks/PHP/amp/server.php

@@ -2,13 +2,14 @@
 
 require __DIR__ . '/vendor/autoload.php';
 
+use Amp\Cluster\Cluster;
+use Amp\Coroutine;
 use Amp\Http\Server\Request;
 use Amp\Http\Server\RequestHandler;
 use Amp\Http\Server\Response;
 use Amp\Http\Server\Router;
 use Amp\Http\Server\Options;
 use Amp\Http\Server\Server;
-use Amp\Cluster\Cluster;
 use Amp\Promise;
 use Amp\Success;
 use Psr\Log\NullLogger;
@@ -20,6 +21,8 @@ Amp\Loop::run(function () {
     ];
 
     $router = new Router;
+
+    // Case 1 - JSON
     $router->addRoute("GET", "/json", new class implements RequestHandler {
         public function handleRequest(Request $request): Promise {
             return new Success(new Response(200, [
@@ -31,6 +34,124 @@ Amp\Loop::run(function () {
         }
     });
 
+    // Case 2 - Single Query
+    $router->addRoute("GET", "/db", new class implements RequestHandler {
+        private $mysql;
+
+        public function __construct() {
+            $this->mysql = Amp\Mysql\pool("host=tfb-database user=benchmarkdbuser password=benchmarkdbpass db=hello_world");
+        }
+
+        public function handleRequest(Request $request): Promise {
+            return new Coroutine($this->doHandleRequest($request));
+        }
+
+        private function doHandleRequest($request) {
+            $statement = yield $this->mysql->prepare("SELECT * FROM World WHERE id = ?");
+            $result = yield $statement->execute([mt_rand(1, 10000)]);
+
+            if (yield $result->advance()) {
+                $item = $result->getCurrent();
+            } else {
+                $item = null;
+            }
+
+            return new Response(200, [
+                "content-type" => "application/json",
+                "server" => "amphp/http-server",
+            ], \json_encode($item));
+        }
+    });
+
+    // Case 3 - Multiple Queries
+    $router->addRoute("GET", "/queries", new class implements RequestHandler {
+        private $mysql;
+
+        public function __construct() {
+            $this->mysql = Amp\Mysql\pool("host=tfb-database user=benchmarkdbuser password=benchmarkdbpass db=hello_world");
+        }
+
+        public function handleRequest(Request $request): Promise {
+            return new Coroutine($this->doHandleRequest($request));
+        }
+
+        private function doHandleRequest($request) {
+            $query = $request->getUri()->getQuery();
+            \parse_str($query, $queryParams);
+
+            $queries = (int) ($queryParams["queries"] ?? 1);
+            if ($queries < 1) {
+                $queries = 1;
+            } elseif ($queries > 500) {
+                $queries = 500;
+            }
+
+            $items = [];
+
+            $statement = yield $this->mysql->prepare("SELECT * FROM World WHERE id = ?");
+
+            for ($i = 0; $i < $queries; $i++) {
+                $items[] = new Coroutine($this->execute($statement));
+            }
+
+            return new Response(200, [
+                "content-type" => "application/json",
+                "server" => "amphp/http-server",
+            ], \json_encode(yield $items));
+        }
+
+        private function execute($statement) {
+            $result = yield $statement->execute([mt_rand(1, 10000)]);
+            yield $result->advance();
+
+            return $result->getCurrent();
+        }
+    });
+
+    // Case 4 - Fortunes
+    $router->addRoute("GET", "/fortunes", new class implements RequestHandler {
+        private $mysql;
+
+        public function __construct() {
+            $this->mysql = Amp\Mysql\pool("host=tfb-database user=benchmarkdbuser password=benchmarkdbpass db=hello_world");
+        }
+
+        public function handleRequest(Request $request): Promise {
+            return new Coroutine($this->doHandleRequest($request));
+        }
+
+        private function doHandleRequest($request) {
+            $result = yield $this->mysql->query("SELECT * FROM Fortune");
+            $items = [];
+
+            while (yield $result->advance()) {
+                $item = $result->getCurrent();
+                $items[$item["id"]] = $item["message"];
+            }
+
+            $items[0] = "Additional fortune added at request time.";
+
+            \asort($items);
+
+            \ob_start();
+
+            require __DIR__ . '/fortunes.php';
+
+            return new Response(200, [
+                "content-type" => "text/html; charset=utf-8",
+                "server" => "amphp/http-server",
+            ], \ob_get_clean());
+        }
+
+        private function execute($statement) {
+            $result = yield $statement->execute([mt_rand(1, 10000)]);
+            yield $result->advance();
+
+            return $result->getCurrent();
+        }
+    });
+
+    // Case 6 - Plaintext
     $router->addRoute("GET", "/plaintext", new class implements RequestHandler {
         public function handleRequest(Request $request): Promise {
             return new Success(new Response(200, [
@@ -40,9 +161,8 @@ Amp\Loop::run(function () {
         }
     });
 
-    $logHandler = Amp\Cluster\createLogHandler();
     $logger = new Monolog\Logger("server");
-    $logger->pushHandler($logHandler);
+    $logger->pushHandler(Amp\Cluster\createLogHandler());
 
     $logger->info("Using " . get_class(Amp\Loop::get()));