Browse Source

Updating Hamlet framework (#4660)

* Updating Hamlet framework, using entities instead of raw ORM, removing roadrunner, react and amp.

* adding missing template file

* updates
vka 6 years ago
parent
commit
755e16a5c6
36 changed files with 453 additions and 315 deletions
  1. 4 0
      frameworks/PHP/hamlet/.gitignore
  2. 27 29
      frameworks/PHP/hamlet/Benchmark/Application.php
  3. 3 6
      frameworks/PHP/hamlet/Benchmark/Entities/FortuneEntity.php
  4. 39 0
      frameworks/PHP/hamlet/Benchmark/Entities/Message.php
  5. 44 0
      frameworks/PHP/hamlet/Benchmark/Entities/RandomNumber.php
  6. 4 4
      frameworks/PHP/hamlet/Benchmark/Entities/fortune.mustache
  7. 11 26
      frameworks/PHP/hamlet/Benchmark/Resources/DbResource.php
  8. 11 10
      frameworks/PHP/hamlet/Benchmark/Resources/FortuneResource.php
  9. 18 0
      frameworks/PHP/hamlet/Benchmark/Resources/HelloJsonResource.php
  10. 0 30
      frameworks/PHP/hamlet/Benchmark/Resources/HelloResource.php
  11. 18 0
      frameworks/PHP/hamlet/Benchmark/Resources/HelloTextResource.php
  12. 48 0
      frameworks/PHP/hamlet/Benchmark/Resources/QueriesResource.php
  13. 15 12
      frameworks/PHP/hamlet/Benchmark/Resources/UpdateResource.php
  14. 3 20
      frameworks/PHP/hamlet/README.md
  15. 12 0
      frameworks/PHP/hamlet/Website.msbuildproj
  16. 0 6
      frameworks/PHP/hamlet/amp.php
  17. 7 12
      frameworks/PHP/hamlet/benchmark_config.json
  18. 6 10
      frameworks/PHP/hamlet/composer.json
  19. 0 8
      frameworks/PHP/hamlet/deploy/.rr.yaml
  20. 10 6
      frameworks/PHP/hamlet/deploy/fpm/nginx.conf
  21. 3 4
      frameworks/PHP/hamlet/deploy/fpm/php-fpm.conf
  22. 0 0
      frameworks/PHP/hamlet/deploy/fpm/php.ini
  23. 3 0
      frameworks/PHP/hamlet/deploy/peachpie/.gitignore
  24. 48 0
      frameworks/PHP/hamlet/deploy/peachpie/Benchmarks.sln
  25. 46 0
      frameworks/PHP/hamlet/deploy/peachpie/Server/Program.cs
  26. 17 0
      frameworks/PHP/hamlet/deploy/peachpie/Server/Server.csproj
  27. 0 29
      frameworks/PHP/hamlet/hamlet-amp.dockerfile
  28. 21 0
      frameworks/PHP/hamlet/hamlet-peachpie.dockerfile
  29. 0 23
      frameworks/PHP/hamlet/hamlet-react.dockerfile
  30. 0 44
      frameworks/PHP/hamlet/hamlet-roadrunner.dockerfile
  31. 4 5
      frameworks/PHP/hamlet/hamlet-swoole.dockerfile
  32. 15 15
      frameworks/PHP/hamlet/hamlet.dockerfile
  33. 8 2
      frameworks/PHP/hamlet/index.php
  34. 0 6
      frameworks/PHP/hamlet/react.php
  35. 0 6
      frameworks/PHP/hamlet/roadrunner.php
  36. 8 2
      frameworks/PHP/hamlet/swoole.php

+ 4 - 0
frameworks/PHP/hamlet/.gitignore

@@ -0,0 +1,4 @@
+obj/
+bin/
+vendor/
+composer.lock

+ 27 - 29
frameworks/PHP/hamlet/Benchmark/Application.php

@@ -4,13 +4,16 @@ namespace Benchmark;
 
 use Benchmark\Resources\DbResource;
 use Benchmark\Resources\FortuneResource;
-use Benchmark\Resources\HelloResource;
+use Benchmark\Resources\HelloJsonResource;
+use Benchmark\Resources\HelloTextResource;
+use Benchmark\Resources\QueriesResource;
 use Benchmark\Resources\UpdateResource;
-use Cache\Adapter\Apcu\ApcuCachePool;
-use Hamlet\Applications\AbstractApplication;
+use Cache\Adapter\PHPArray\ArrayCachePool;
 use Hamlet\Database\Database;
-use Hamlet\Requests\Request;
-use Hamlet\Resources\WebResource;
+use Hamlet\Http\Applications\AbstractApplication;
+use Hamlet\Http\Requests\Request;
+use Hamlet\Http\Resources\HttpResource;
+use Hamlet\Http\Resources\NotFoundResource;
 use Psr\Cache\CacheItemPoolInterface;
 
 class Application extends AbstractApplication
@@ -18,41 +21,36 @@ class Application extends AbstractApplication
     /** @var CacheItemPoolInterface|null */
     private $cache;
 
-    /** @var Database|null */
+    /** @var Database */
     private $database;
 
-    public function findResource(Request $request): WebResource
+    public function __construct(Database $database)
     {
-        if ($request->pathMatches('/plaintext')) {
-            return new HelloResource(false);
-        } elseif ($request->pathMatches('/json')) {
-            return new HelloResource(true);
-        } elseif ($request->pathMatches('/db') || $request->pathMatches('/queries')) {
-            return new DbResource($this->database());
-        } elseif ($request->pathMatches('/fortunes')) {
-            return new FortuneResource($this->database());
-        } elseif ($request->pathMatches('/update')) {
-            return new UpdateResource($this->database());
-        }
+        $this->database = $database;
     }
-
-    private function database(): Database
+    public function findResource(Request $request): HttpResource
     {
-        if (!$this->database) {
-            $this->database = Database::mysql(
-                'p:tfb-database',
-                'benchmarkdbuser',
-                'benchmarkdbpass',
-                'hello_world'
-            );
+        switch ($request->getPath()) {
+            case '/plaintext':
+                return new HelloTextResource();
+            case '/json':
+                return new HelloJsonResource();
+            case '/db':
+                return new DbResource($this->database);
+            case '/queries':
+                return new QueriesResource($this->database);
+            case '/fortunes':
+                return new FortuneResource($this->database);
+            case '/update':
+                return new UpdateResource($this->database);
         }
-        return $this->database;
+        return new NotFoundResource();
     }
 
     protected function getCache(Request $request): CacheItemPoolInterface
     {
         if (!$this->cache) {
-            $this->cache = new ApcuCachePool();
+            $this->cache = new ArrayCachePool();
         }
         return $this->cache;
     }

+ 3 - 6
frameworks/PHP/hamlet/Benchmark/Entities/FortuneEntity.php

@@ -2,9 +2,9 @@
 
 namespace Benchmark\Entities;
 
-use Hamlet\Entities\AbstractTwigEntity;
+use Hamlet\Http\Entities\AbstractMustacheEntity;
 
-class FortuneEntity extends AbstractTwigEntity
+class FortuneEntity extends AbstractMustacheEntity
 {
     private $messages;
 
@@ -22,12 +22,9 @@ class FortuneEntity extends AbstractTwigEntity
 
     protected function getTemplatePath(): string
     {
-        return __DIR__ . '/fortune.twig';
+        return __DIR__ . '/fortune.mustache';
     }
 
-    /**
-     * Get cache key of the entity
-     */
     public function getKey(): string
     {
         return md5(var_export($this->messages, true));

+ 39 - 0
frameworks/PHP/hamlet/Benchmark/Entities/Message.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace Benchmark\Entities;
+
+use Hamlet\Database\Entity;
+use JsonSerializable;
+
+class Message implements Entity, JsonSerializable
+{
+    /** @var int */
+    private $id;
+
+    /** @var string */
+    private $message;
+
+    public function __construct(int $id, string $message)
+    {
+        $this->id = $id;
+        $this->message = $message;
+    }
+
+    public function id(): int
+    {
+        return $this->id;
+    }
+
+    public function message(): string
+    {
+        return $this->message;
+    }
+
+    public function jsonSerialize()
+    {
+        return [
+            'id' => $this->id,
+            'message' => $this->message
+        ];
+    }
+}

+ 44 - 0
frameworks/PHP/hamlet/Benchmark/Entities/RandomNumber.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace Benchmark\Entities;
+
+use Hamlet\Database\Entity;
+use JsonSerializable;
+
+class RandomNumber implements Entity, JsonSerializable
+{
+    /** @var int */
+    private $id;
+
+    /** @var int */
+    private $randomNumber;
+
+    public function __construct(int $id, int $randomNumber)
+    {
+        $this->id = $id;
+        $this->randomNumber = $randomNumber;
+    }
+
+    public function id(): int
+    {
+        return $this->id;
+    }
+
+    public function number(): int
+    {
+        return $this->randomNumber;
+    }
+
+    public function withNumber(int $number): RandomNumber
+    {
+        return new self($this->id, $number);
+    }
+
+    public function jsonSerialize()
+    {
+        return [
+            'id' => $this->id,
+            'randomNumber' => $this->randomNumber
+        ];
+    }
+}

+ 4 - 4
frameworks/PHP/hamlet/Benchmark/Entities/fortune.twig → frameworks/PHP/hamlet/Benchmark/Entities/fortune.mustache

@@ -7,12 +7,12 @@
         <th>id</th>
         <th>message</th>
     </tr>
-    {% for id, message in messages %}
+    {{# messages }}
         <tr>
-            <td>{{id}}</td>
-            <td>{{message|escape}}</td>
+            <td>{{ id }}</td>
+            <td>{{ message }}</td>
         </tr>
-    {% endfor %}
+    {{/ messages }}
 </table>
 </body>
 </html>

+ 11 - 26
frameworks/PHP/hamlet/Benchmark/Resources/DbResource.php

@@ -2,14 +2,15 @@
 
 namespace Benchmark\Resources;
 
+use Benchmark\Entities\RandomNumber;
 use Hamlet\Database\Database;
-use Hamlet\Entities\JsonEntity;
-use Hamlet\Requests\Request;
-use Hamlet\Resources\WebResource;
-use Hamlet\Responses\Response;
-use Hamlet\Responses\SimpleOKResponse;
+use Hamlet\Http\Entities\JsonEntity;
+use Hamlet\Http\Requests\Request;
+use Hamlet\Http\Resources\HttpResource;
+use Hamlet\Http\Responses\Response;
+use Hamlet\Http\Responses\SimpleOKResponse;
 
-class DbResource implements WebResource
+class DbResource implements HttpResource
 {
     private $database;
 
@@ -20,14 +21,7 @@ class DbResource implements WebResource
 
     public function getResponse(Request $request): Response
     {
-        $queryParams = $request->getQueryParams();
-        $count = $queryParams['queries'] ?? null;
-        if ($count !== null && $count > 0) {
-            $count = min($count, 500);
-        } else {
-            $count = 1;
-        }
-
+        $id = mt_rand(1, 10000);
         $query = '
             SELECT id,
                    randomNumber 
@@ -35,18 +29,9 @@ class DbResource implements WebResource
              WHERE id = ?
         ';
         $procedure = $this->database->prepare($query);
+        $procedure->bindInteger($id);
+        $record = $procedure->processOne()->selectAll()->cast(RandomNumber::class)->collectHead();
 
-        $payload = [];
-        while ($count-- > 0) {
-            $id = mt_rand(1, 10000);
-            $procedure->bindInteger($id);
-            $payload[] = $procedure->fetchOne();
-        }
-
-        if (!isset($queryParams['queries'])) {
-            $payload = $payload[0];
-        }
-
-        return new SimpleOKResponse(new JsonEntity($payload));
+        return new SimpleOKResponse(new JsonEntity($record));
     }
 }

+ 11 - 10
frameworks/PHP/hamlet/Benchmark/Resources/FortuneResource.php

@@ -3,13 +3,14 @@
 namespace Benchmark\Resources;
 
 use Benchmark\Entities\FortuneEntity;
+use Benchmark\Entities\Message;
 use Hamlet\Database\Database;
-use Hamlet\Requests\Request;
-use Hamlet\Resources\WebResource;
-use Hamlet\Responses\Response;
-use Hamlet\Responses\SimpleOKResponse;
+use Hamlet\Http\Requests\Request;
+use Hamlet\Http\Resources\HttpResource;
+use Hamlet\Http\Responses\Response;
+use Hamlet\Http\Responses\SimpleOKResponse;
 
-class FortuneResource implements WebResource
+class FortuneResource implements HttpResource
 {
     private $database;
 
@@ -26,11 +27,11 @@ class FortuneResource implements WebResource
               FROM Fortune
         ';
         $procedure = $this->database->prepare($query);
-        $messages = $procedure->processAll()
-            ->map('id', 'message')->flatten()
-            ->collectAll();
-        $messages[0] = 'Additional fortune added at request time.';
-        asort($messages);
+        $messages = $procedure->processAll()->selectAll()->cast(Message::class)->collectAll();
+        $messages[] = new Message(0, 'Additional fortune added at request time.');
+        usort($messages, function (Message $a, Message $b): int {
+            return $a->message() <=> $b->message();
+        });
         return new SimpleOKResponse(new FortuneEntity($messages));
     }
 }

+ 18 - 0
frameworks/PHP/hamlet/Benchmark/Resources/HelloJsonResource.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace Benchmark\Resources;
+
+use Hamlet\Http\Entities\JsonEntity;
+use Hamlet\Http\Requests\Request;
+use Hamlet\Http\Resources\HttpResource;
+use Hamlet\Http\Responses\Response;
+use Hamlet\Http\Responses\SimpleOKResponse;
+
+class HelloJsonResource implements HttpResource
+{
+    public function getResponse(Request $request): Response
+    {
+        $entity = new JsonEntity(['message' => 'Hello, World!']);
+        return new SimpleOKResponse($entity);
+    }
+}

+ 0 - 30
frameworks/PHP/hamlet/Benchmark/Resources/HelloResource.php

@@ -1,30 +0,0 @@
-<?php
-
-namespace Benchmark\Resources;
-
-use Hamlet\Entities\JsonEntity;
-use Hamlet\Entities\PlainTextEntity;
-use Hamlet\Requests\Request;
-use Hamlet\Resources\WebResource;
-use Hamlet\Responses\Response;
-use Hamlet\Responses\SimpleOKResponse;
-
-class HelloResource implements WebResource
-{
-    private $json;
-
-    public function __construct(bool $json)
-    {
-        $this->json = $json;
-    }
-
-    public function getResponse(Request $request): Response
-    {
-        if ($this->json) {
-            $entity = new JsonEntity(['message' => 'Hello, World!']);
-        } else {
-            $entity = new PlainTextEntity('Hello, World!');
-        }
-        return new SimpleOKResponse($entity);
-    }
-}

+ 18 - 0
frameworks/PHP/hamlet/Benchmark/Resources/HelloTextResource.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace Benchmark\Resources;
+
+use Hamlet\Http\Entities\PlainTextEntity;
+use Hamlet\Http\Requests\Request;
+use Hamlet\Http\Resources\HttpResource;
+use Hamlet\Http\Responses\Response;
+use Hamlet\Http\Responses\SimpleOKResponse;
+
+class HelloTextResource implements HttpResource
+{
+    public function getResponse(Request $request): Response
+    {
+        $entity = new PlainTextEntity('Hello, World!');
+        return new SimpleOKResponse($entity);
+    }
+}

+ 48 - 0
frameworks/PHP/hamlet/Benchmark/Resources/QueriesResource.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace Benchmark\Resources;
+
+use Benchmark\Entities\RandomNumber;
+use Hamlet\Database\Database;
+use Hamlet\Http\Entities\JsonEntity;
+use Hamlet\Http\Requests\Request;
+use Hamlet\Http\Resources\HttpResource;
+use Hamlet\Http\Responses\Response;
+use Hamlet\Http\Responses\SimpleOKResponse;
+
+class QueriesResource implements HttpResource
+{
+    private $database;
+
+    public function __construct(Database $database)
+    {
+        $this->database = $database;
+    }
+
+    public function getResponse(Request $request): Response
+    {
+        $count = $request->parameter('queries');
+        if ($count === null || $count < 1) {
+            $count = 1;
+        } else {
+            $count = min($count, 500);
+        }
+
+        $query = '
+            SELECT id,
+                   randomNumber 
+              FROM World 
+             WHERE id = ?
+        ';
+        $procedure = $this->database->prepare($query);
+
+        $payload = [];
+        while ($count-- > 0) {
+            $id = mt_rand(1, 10000);
+            $procedure->bindInteger($id);
+            $payload[] = $procedure->processOne()->selectAll()->cast(RandomNumber::class)->collectHead();
+        }
+
+        return new SimpleOKResponse(new JsonEntity($payload));
+    }
+}

+ 15 - 12
frameworks/PHP/hamlet/Benchmark/Resources/UpdateResource.php

@@ -2,14 +2,15 @@
 
 namespace Benchmark\Resources;
 
+use Benchmark\Entities\RandomNumber;
 use Hamlet\Database\Database;
-use Hamlet\Entities\JsonEntity;
-use Hamlet\Requests\Request;
-use Hamlet\Resources\WebResource;
-use Hamlet\Responses\Response;
-use Hamlet\Responses\SimpleOKResponse;
+use Hamlet\Http\Entities\JsonEntity;
+use Hamlet\Http\Requests\Request;
+use Hamlet\Http\Resources\HttpResource;
+use Hamlet\Http\Responses\Response;
+use Hamlet\Http\Responses\SimpleOKResponse;
 
-class UpdateResource implements WebResource
+class UpdateResource implements HttpResource
 {
     private $database;
 
@@ -20,7 +21,7 @@ class UpdateResource implements WebResource
 
     public function getResponse(Request $request): Response
     {
-        $count = $request->getQueryParams()['queries'] ?? null;
+        $count = $request->parameter('queries');
         if ($count !== null && $count > 0) {
             $count = min($count, 500);
         } else {
@@ -48,14 +49,16 @@ class UpdateResource implements WebResource
             $randomNumber = mt_rand(1, 10000);
 
             $selectProcedure->bindInteger($id);
-            $entry = $selectProcedure->fetchOne();
-            $entry['randomNumber'] = $randomNumber;
+            /** @var RandomNumber $entry */
+            $entry = $selectProcedure->processOne()->selectAll()->cast(RandomNumber::class)->collectHead();
 
-            $updateProcedure->bindInteger($randomNumber);
-            $updateProcedure->bindInteger($id);
+            $modifiedEntry = $entry->withNumber($randomNumber);
+
+            $updateProcedure->bindInteger($modifiedEntry->number());
+            $updateProcedure->bindInteger($modifiedEntry->id());
             $updateProcedure->execute();
 
-            $payload[] = $entry;
+            $payload[] = $modifiedEntry;
         }
 
         return new SimpleOKResponse(new JsonEntity($payload));

+ 3 - 20
frameworks/PHP/hamlet/README.md

@@ -1,31 +1,14 @@
 # Hamlet Framework Benchmarking Test
 
-This is the [Hamlet Core](https://github.com/vasily-kartashov/hamlet-core) portion of a [benchmarking test suite](../)
+This is the [Hamlet Framework](https://github.com/hamlet-framework) portion of a [benchmarking test suite](../)
 
 Current submission tests the following configurations:
 
-- Hamlet + PHP FPM
-- Hamlet + ReactPHP
-- Hamlet + RoadRunner
+- Hamlet
 - Hamlet + Swoole
+- Hamlet + PeachPie
 
 ## (Some) Documentation
 
 - [Short overview of framework's architecture](https://notes.kartashov.com/2016/07/08/simple-caching-web-framework/)
 - [Data processor](https://notes.kartashov.com/2017/05/09/result-set-processor/)
-
-## Dependency
-
-```json
-{
-  ...
-  "require": {
-    "hamlet/hamlet-core" : "^3"
-    ...
-  }
-}
-```
-
-## Local test
-
-ab -c 1 -n 100 "http://127.0.0.1:8089/json"

+ 12 - 0
frameworks/PHP/hamlet/Website.msbuildproj

@@ -0,0 +1,12 @@
+<Project Sdk="Peachpie.NET.Sdk/0.9.40">
+  <PropertyGroup>
+    <OutputType>Library</OutputType>
+    <TargetFramework>netstandard2.0</TargetFramework>
+    <AssemblyName>Website</AssemblyName>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile
+        Include="index.php;Benchmark/**/*.php;vendor/**/*.php;"
+        Exclude="**/phpunit/**;**/tests/**;**/*Test.php;**/*TestCase.php"/>
+  </ItemGroup>
+</Project>

+ 0 - 6
frameworks/PHP/hamlet/amp.php

@@ -1,6 +0,0 @@
-<?php
-
-require_once __DIR__ . '/vendor/autoload.php';
-
-$application = new \Benchmark\Application;
-\Hamlet\Bootstraps\AmpBootstrap::run(8080, $application);

+ 7 - 12
frameworks/PHP/hamlet/benchmark_config.json

@@ -15,7 +15,7 @@
       "framework": "hamlet",
       "language": "PHP",
       "flavor": "PHP7",
-      "orm": "Raw",
+      "orm": "micro",
       "platform": "None",
       "webserver": "nginx",
       "os": "Linux",
@@ -25,7 +25,6 @@
       "versus": "php"
     },
     "swoole": {
-      "plaintext_url": "/plaintext",
       "json_url": "/json",
       "db_url": "/db",
       "query_url": "/queries?queries=",
@@ -38,7 +37,7 @@
       "framework": "hamlet",
       "language": "PHP",
       "flavor": "PHP7",
-      "orm": "Raw",
+      "orm": "micro",
       "platform": "None",
       "webserver": "swoole",
       "os": "Linux",
@@ -47,13 +46,9 @@
       "notes": "",
       "versus": "php"
     },
-    "react": {
+    "peachpie": {
       "plaintext_url": "/plaintext",
       "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/update?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Fullstack",
@@ -61,12 +56,12 @@
       "framework": "hamlet",
       "language": "PHP",
       "flavor": "PHP7",
-      "orm": "Raw",
-      "platform": "None",
-      "webserver": "react",
+      "orm": "micro",
+      "platform": ".NET",
+      "webserver": "kestrel",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "hamlet-react",
+      "display_name": "hamlet-peachpie",
       "notes": "",
       "versus": "php"
     }

+ 6 - 10
frameworks/PHP/hamlet/composer.json

@@ -1,17 +1,13 @@
 {
+  "minimum-stability": "dev",
   "config": {
-    "discard-changes": true
+    "optimize-autoloader": true,
+    "classmap-authoritative": true
   },
   "require": {
-    "hamlet/hamlet-core" : "^3.2",
-    "cache/apcu-adapter": "^1",
-    "react/http": "*",
-    "spiral/roadrunner": "*",
-    "swoft/swoole-ide-helper": "*",
-    "amphp/amp": "*",
-    "amphp/http-server": "*",
-    "amphp/http-server-router": "*",
-    "amphp/cluster": "@dev"
+    "hamlet-framework/http" : "dev-master",
+    "hamlet-framework/db-mysql": "dev-master",
+    "cache/array-adapter": "^1"
   },
   "autoload": {
     "psr-4": {

+ 0 - 8
frameworks/PHP/hamlet/deploy/.rr.yaml

@@ -1,8 +0,0 @@
-http:
-  enable: true
-  address: 0.0.0.0:8080
-  workers:
-    command: php /php/roadrunner.php
-    relay: pipes
-    pool:
-      numWorkers: WORKERS

+ 10 - 6
frameworks/PHP/hamlet/deploy/nginx-fpm.conf → frameworks/PHP/hamlet/deploy/fpm/nginx.conf

@@ -1,11 +1,11 @@
 user www-data;
-worker_processes  auto;
+worker_processes auto;
 error_log stderr error;
 worker_rlimit_nofile 200000;
 
 events {
     worker_connections 32768;
-    multi_accept off;
+    multi_accept on;
 }
 
 http {
@@ -33,7 +33,7 @@ http {
     server_names_hash_bucket_size 100;
 
     upstream fastcgi_backend {
-        server unix:/var/run/php/php7.3-fpm.sock;
+        server unix:/var/run/php7.3-fpm.sock;
         keepalive 50;
     }
 
@@ -41,14 +41,18 @@ http {
         listen 8080;
         server_name localhost;
 
-        root /php;
+        root /app;
         index  index.php;
 
         location / {
+            try_files $uri $uri/ /index.php?$uri&$args;
+        }
+
+        location ~ \.php$ {
             fastcgi_pass   fastcgi_backend;
             fastcgi_keep_conn on;
-            fastcgi_param  SCRIPT_FILENAME  $document_root/index.php;
-            fastcgi_param  PATH_INFO        $uri;
+            fastcgi_index  index.php;
+            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
             include        /etc/nginx/fastcgi_params;
         }
     }

+ 3 - 4
frameworks/PHP/hamlet/deploy/conf/php-fpm.conf → frameworks/PHP/hamlet/deploy/fpm/php-fpm.conf

@@ -1,18 +1,17 @@
 [global]
-pid = /run/php/php7.3-fpm.pid
+pid = /var/run/php7.3-fpm.pid
 error_log = /dev/stderr
 systemd_interval = 0
 
 [www]
 user = www-data
 group = www-data
-listen = /run/php/php7.3-fpm.sock
+listen = /var/run/php7.3-fpm.sock
 listen.backlog = 65535
 listen.owner = www-data
 listen.group = www-data
-
 pm = static
-pm.max_children = 1024
+pm.max_children = 2048
 pm.start_servers = 512
 pm.min_spare_servers = 50
 pm.max_spare_servers = 512

+ 0 - 0
frameworks/PHP/hamlet/deploy/conf/php.ini → frameworks/PHP/hamlet/deploy/fpm/php.ini


+ 3 - 0
frameworks/PHP/hamlet/deploy/peachpie/.gitignore

@@ -0,0 +1,3 @@
+.idea/
+*/bin/
+*/obj/

+ 48 - 0
frameworks/PHP/hamlet/deploy/peachpie/Benchmarks.sln

@@ -0,0 +1,48 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Website", "../../Website.msbuildproj", "{A271793F-72BF-429D-9EC8-83C03559CBD6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server/Server.csproj", "{AF5D53C1-32B5-473F-9229-817608068701}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|x64.ActiveCfg = Debug|x64
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|x64.Build.0 = Debug|x64
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|x86.ActiveCfg = Debug|x86
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|x86.Build.0 = Debug|x86
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|x64.ActiveCfg = Release|x64
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|x64.Build.0 = Release|x64
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|x86.ActiveCfg = Release|x86
+		{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|x86.Build.0 = Release|x86
+		{AF5D53C1-32B5-473F-9229-817608068701}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{AF5D53C1-32B5-473F-9229-817608068701}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AF5D53C1-32B5-473F-9229-817608068701}.Debug|x64.ActiveCfg = Debug|x64
+		{AF5D53C1-32B5-473F-9229-817608068701}.Debug|x64.Build.0 = Debug|x64
+		{AF5D53C1-32B5-473F-9229-817608068701}.Debug|x86.ActiveCfg = Debug|x86
+		{AF5D53C1-32B5-473F-9229-817608068701}.Debug|x86.Build.0 = Debug|x86
+		{AF5D53C1-32B5-473F-9229-817608068701}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{AF5D53C1-32B5-473F-9229-817608068701}.Release|Any CPU.Build.0 = Release|Any CPU
+		{AF5D53C1-32B5-473F-9229-817608068701}.Release|x64.ActiveCfg = Release|x64
+		{AF5D53C1-32B5-473F-9229-817608068701}.Release|x64.Build.0 = Release|x64
+		{AF5D53C1-32B5-473F-9229-817608068701}.Release|x86.ActiveCfg = Release|x86
+		{AF5D53C1-32B5-473F-9229-817608068701}.Release|x86.Build.0 = Release|x86
+	EndGlobalSection
+EndGlobal

+ 46 - 0
frameworks/PHP/hamlet/deploy/peachpie/Server/Program.cs

@@ -0,0 +1,46 @@
+using System.IO;
+using System.Threading;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Peachpie.AspNetCore.Web;
+
+namespace Server
+{
+    class Program
+    {
+        static void Main(string[] args)
+        {
+            ThreadPool.GetMinThreads(out int workerThread, out int completionThread);
+            ThreadPool.SetMinThreads(workerThread * 2, completionThread);
+
+            var host = new WebHostBuilder()
+                .UseKestrel()
+                .UseUrls("http://0.0.0.0:8080")
+                .UseStartup<Startup>()
+                .Build();
+
+            host.Run();
+        }
+    }
+
+    class Startup
+    {
+        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
+        {
+            // loggerFactory.AddConsole();
+
+            app.UseRewriter(new RewriteOptions().Add(ShortUrlRule));
+            void ShortUrlRule(RewriteContext context)
+            {
+                var req = context.HttpContext.Request;
+                req.Path = new PathString("/index.php");
+                context.Result = RuleResult.SkipRemainingRules;
+            }
+            app.UsePhp(new PhpRequestOptions(scriptAssemblyName: "Website"));
+        }
+    }
+}

+ 17 - 0
frameworks/PHP/hamlet/deploy/peachpie/Server/Server.csproj

@@ -0,0 +1,17 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+    <OutputType>Exe</OutputType>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
+    <PackageReference Include="Microsoft.AspNetCore.Buffering" Version="0.2.2" />
+    <PackageReference Include="Microsoft.AspNetCore.Rewrite" Version="2.2.0" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.2.0" />
+    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.2.0" />
+    <PackageReference Include="Peachpie.AspNetCore.Web" Version="0.9.40" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="../../../Website.msbuildproj" />
+  </ItemGroup>
+</Project>

+ 0 - 29
frameworks/PHP/hamlet/hamlet-amp.dockerfile

@@ -1,29 +0,0 @@
-FROM ubuntu:18.10
-
-ENV PHP_VERSION="7.3"
-
-ARG DEBIAN_FRONTEND=noninteractive
-
-RUN apt-get update -yqq > /dev/null && \
-    apt-get install -yqq software-properties-common > /dev/null
-
-RUN add-apt-repository -y ppa:ondrej/php && \
-    apt-get update -yqq > /dev/null && \
-    apt-get install -yqq \
-        curl \
-        git \
-        unzip \
-        php${PHP_VERSION}-cli \
-        php${PHP_VERSION}-mysqli \
-        php${PHP_VERSION}-apcu \
-        php${PHP_VERSION}-opcache > /dev/null
-
-RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
-
-ADD ./ /php
-WORKDIR /php
-RUN chmod -R 777 /php
-
-RUN composer update --quiet --no-dev --optimize-autoloader --classmap-authoritative
-
-CMD php /php/amp.php

+ 21 - 0
frameworks/PHP/hamlet/hamlet-peachpie.dockerfile

@@ -0,0 +1,21 @@
+FROM microsoft/dotnet:2.2-sdk-stretch
+
+COPY . /wwwroot
+WORKDIR /wwwroot
+
+RUN apt update -y \
+    && apt install -y ca-certificates apt-transport-https \
+    && wget -q https://packages.sury.org/php/apt.gpg -O- | apt-key add - \
+    && echo "deb https://packages.sury.org/php/ stretch main" | tee /etc/apt/sources.list.d/php.list \
+    && apt-get update -y \
+    && apt-get install -y nginx git unzip php7.3 php7.3-common php7.3-cli php7.3-fpm php7.3-mysql
+
+RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
+    && composer update --no-dev
+
+RUN dotnet publish -c Release -o /wwwroot /wwwroot/deploy/peachpie/Server
+
+EXPOSE 8080/tcp
+ENV ASPNETCORE_URLS="http://+:8080"
+
+ENTRYPOINT ["dotnet", "Server.dll"]

+ 0 - 23
frameworks/PHP/hamlet/hamlet-react.dockerfile

@@ -1,23 +0,0 @@
-FROM php:7.3-rc-cli
-
-RUN docker-php-ext-install mysqli > /dev/null && \
-    docker-php-ext-enable mysqli
-
-RUN docker-php-ext-install opcache > /dev/null && \
-    docker-php-ext-enable opcache
-
-RUN pecl install apcu > /dev/null && \
-    docker-php-ext-enable apcu
-
-RUN apt-get update > /dev/null && \
-    apt-get install -y git unzip > /dev/null
-
-RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
-
-ADD ./ /php
-WORKDIR /php
-RUN chmod -R 777 /php
-
-RUN composer update --quiet --no-dev --optimize-autoloader --classmap-authoritative
-
-CMD php /php/react.php

+ 0 - 44
frameworks/PHP/hamlet/hamlet-roadrunner.dockerfile

@@ -1,44 +0,0 @@
-FROM ubuntu:18.10
-
-ENV PHP_VERSION="7.3"
-ENV RR_VERSION="1.2.6"
-
-ENV RR_URL="https://github.com/spiral/roadrunner/archive/v${RR_VERSION}.tar.gz"
-ENV GOPATH="/php/go"
-
-ARG DEBIAN_FRONTEND=noninteractive
-
-RUN apt-get update -yqq > /dev/null && \
-    apt-get install -yqq software-properties-common > /dev/null
-
-RUN add-apt-repository -y ppa:ondrej/php && \
-    apt-get update -yqq > /dev/null && \
-    apt-get install -yqq \
-        curl \
-        git \
-        php${PHP_VERSION}-cli \
-        php${PHP_VERSION}-mysqli \
-        php${PHP_VERSION}-apcu \
-        php${PHP_VERSION}-opcache \
-        golang-go > /dev/null
-
-RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
-
-ADD ./ /php
-WORKDIR /php
-RUN chmod -R 777 /php
-
-RUN mkdir "${GOPATH}"
-
-RUN curl -sSL "${RR_URL}" | tar xzf - && \
-    cd "roadrunner-${RR_VERSION}" && \
-    go get -d ./... && \
-    make && \
-    cp rr /usr/local/bin/rr && \
-    chmod +x /usr/local/bin/rr
-
-RUN sed -i 's|WORKERS|'"$(nproc)"'|g' /php/deploy/.rr.yaml
-
-RUN composer update --quiet --no-dev --optimize-autoloader --classmap-authoritative
-
-CMD rr -c /php/deploy/.rr.yaml serve

+ 4 - 5
frameworks/PHP/hamlet/hamlet-swoole.dockerfile

@@ -1,4 +1,4 @@
-FROM php:7.3-rc-cli
+FROM php:7.3
 
 RUN pecl install swoole > /dev/null && \
     docker-php-ext-enable swoole
@@ -6,9 +6,6 @@ RUN pecl install swoole > /dev/null && \
 RUN docker-php-ext-install mysqli > /dev/null && \
     docker-php-ext-enable mysqli
 
-RUN pecl install apcu > /dev/null && \
-    docker-php-ext-enable apcu
-
 RUN apt-get update > /dev/null && \
     apt-get install -y git unzip > /dev/null
 
@@ -18,6 +15,8 @@ ADD ./ /php
 WORKDIR /php
 RUN chmod -R 777 /php
 
-RUN composer update --quiet --no-dev --optimize-autoloader --classmap-authoritative
+RUN composer require hamlet-framework/http-swoole:dev-master
+RUN composer require hamlet-framework/db-mysql-swoole:dev-master
+RUN composer update --no-dev
 
 CMD php /php/swoole.php

+ 15 - 15
frameworks/PHP/hamlet/hamlet.dockerfile

@@ -1,22 +1,22 @@
-FROM ubuntu:18.10
+FROM debian:stretch
 
-ARG DEBIAN_FRONTEND=noninteractive
+RUN apt update -y \
+    && apt install -y gnupg ca-certificates apt-transport-https wget curl \
+    && wget -q https://packages.sury.org/php/apt.gpg -O- | apt-key add - \
+    && echo "deb https://packages.sury.org/php/ stretch main" | tee /etc/apt/sources.list.d/php.list \
+    && apt-get update -y \
+    && apt-get install -y nginx git unzip php7.3 php7.3-common php7.3-cli php7.3-fpm php7.3-mysql
 
-RUN apt-get update -yqq && apt-get install -yqq software-properties-common > /dev/null
-RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
-RUN apt-get update -yqq > /dev/null && \
-    apt-get install -yqq nginx git unzip curl php7.3 php7.3-common php7.3-cli php7.3-fpm php7.3-mysql php7.3-opcache > /dev/null
+COPY deploy/fpm/php-fpm.conf /etc/php/7.3/fpm/php-fpm.conf
+COPY deploy/fpm/php.ini /etc/php/7.3/fpm/php.ini
 
-COPY deploy/conf/* /etc/php/7.3/fpm/
-
-ADD ./ /php
-WORKDIR /php
-RUN chmod -R 777 /php
+ADD ./ /app
+WORKDIR /app
 
 RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/7.3/fpm/php-fpm.conf ; fi;
 
-RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
-RUN composer update --no-dev --optimize-autoloader --classmap-authoritative
+RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
+    && composer update --no-dev
 
-CMD service php7.3-fpm start && \
-    nginx -c /php/deploy/nginx-fpm.conf -g "daemon off;"
+CMD service php7.3-fpm start \
+    && nginx -c /app/deploy/fpm/nginx.conf -g "daemon off;"

+ 8 - 2
frameworks/PHP/hamlet/index.php

@@ -2,5 +2,11 @@
 
 require_once __DIR__ . '/vendor/autoload.php';
 
-$application = new \Benchmark\Application;
-\Hamlet\Bootstraps\ServerBootstrap::run($application);
+$database = new \Hamlet\Database\MySQL\MySQLDatabase(
+    'p:tfb-database',
+    'benchmarkdbuser',
+    'benchmarkdbpass',
+    'hello_world'
+);
+$application = new \Benchmark\Application($database);
+\Hamlet\Http\Bootstraps\ServerBootstrap::run($application);

+ 0 - 6
frameworks/PHP/hamlet/react.php

@@ -1,6 +0,0 @@
-<?php
-
-require_once __DIR__ . '/vendor/autoload.php';
-
-$application = new \Benchmark\Application;
-\Hamlet\Bootstraps\ReactBootstrap::run('0.0.0.0', 8080, $application);

+ 0 - 6
frameworks/PHP/hamlet/roadrunner.php

@@ -1,6 +0,0 @@
-<?php
-
-require_once __DIR__ . '/vendor/autoload.php';
-
-$application = new \Benchmark\Application;
-\Hamlet\Bootstraps\RoadRunnerBootstrap::run($application);

+ 8 - 2
frameworks/PHP/hamlet/swoole.php

@@ -2,5 +2,11 @@
 
 require_once __DIR__ . '/vendor/autoload.php';
 
-$application = new \Benchmark\Application;
-\Hamlet\Bootstraps\SwooleBootstrap::run('0.0.0.0', 8080, $application);
+$database = new \Hamlet\Database\MySQLSwoole\MySQLSwooleDatabase(
+    'tfb-database',
+    'benchmarkdbuser',
+    'benchmarkdbpass',
+    'hello_world'
+);
+$application = new \Benchmark\Application($database);
+\Hamlet\Http\Swoole\Bootstraps\SwooleBootstrap::run('0.0.0.0', 8080, $application);