瀏覽代碼

Initial commit for Comet PHP framework (#5714)

* Initial commit for Comet PHP framework

* Add Comet to travis.yml

* Move PHP/comet within .travis.yml

* Move PHP/comet within .travis.yml

* Fix ORM init

* .travis.yml

* Spasing for plaintext header

* plain/text vs plain/html

* ORM MySQL support

* Correct MYSQL DSN driver string
Serge Gotsuliak 5 年之前
父節點
當前提交
d967b647f3

+ 1 - 1
.travis.yml

@@ -61,7 +61,7 @@ env:
     - "TESTLANG=Lua"
     - "TESTLANG=Nim"
     - "TESTLANG=Perl"
-    - 'TESTDIR="PHP/php"'
+    - 'TESTDIR="PHP/php PHP/comet"'
     - 'TESTDIR="PHP/cakephp PHP/codeigniter PHP/fat-free PHP/fuel PHP/kumbiaphp PHP/phpixie PHP/slim PHP/symfony PHP/yii2 PHP/zend PHP/spiral"'
     - 'TESTDIR="PHP/amp PHP/hhvm PHP/peachpie PHP/php-ngx PHP/workerman PHP/phalcon"'
     - 'TESTDIR="PHP/hamlet PHP/laravel PHP/lumen PHP/swoole PHP/ubiquity PHP/hyperf PHP/sw-fw-less PHP/imi PHP/simps"'

+ 29 - 0
frameworks/PHP/comet/README.md

@@ -0,0 +1,29 @@
+# Comet Benchmarking Test
+
+This is the Comet portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+## Comet
+
+[Comet](https://github.com/gotzmann/comet) is a modern PHP framework for building fast REST APIs and microservices. 
+
+## Test URLs
+
+### Plaintext Test
+
+http://localhost:8080/plaintext
+
+### JSON Encoding Test
+
+http://localhost:8080/json
+
+### DB Test
+
+http://localhost:8080/db
+
+### Query Test
+
+http://localhost:8080/query?q=2
+
+### Update Test
+
+http://localhost:8080/update?q=2

+ 59 - 0
frameworks/PHP/comet/app.php

@@ -0,0 +1,59 @@
+<?php
+declare(strict_types=1);
+
+use App\ORM;
+use Comet\Comet;
+use App\Controllers\DbController;
+use App\Controllers\QueryController;
+use App\Controllers\UpdateController;
+use App\Controllers\FortuneController;
+
+require_once __DIR__ . '/vendor/autoload.php';
+
+// TODO Use Timer to setup Date header once per second!
+
+$app = new Comet([
+    'host' => '0.0.0.0',
+    'port' => 8080,
+    'debug' => false,
+    'logger' => null,
+]);
+
+$app->init(
+    function() {
+        ORM::init();	
+});
+
+// #1 Plaintext
+$app->get('/plaintext',
+    function ($request, $response) {        
+        return $response
+            ->withText('Hello, World!')
+            ->withHeader('Date', gmdate('D, d M Y H:i:s') . ' GMT');
+});
+
+// #2 JSON Serialization
+$app->get('/json', 
+    function ($request, $response) {        
+        return $response            
+            ->with([ 'message' => 'Hello, World!' ])
+            ->withHeader('Date', gmdate('D, d M Y H:i:s') . ' GMT');
+});
+
+// #3 Single Database Query
+$app->get('/db',    
+    DbController::class);
+
+// #4: Multiple Database Queries
+$app->get('/query',    
+    QueryController::class);
+
+// #5: Update Database Rows
+$app->get('/update',    
+    UpdateController::class);
+
+// #6 Return Fortunes
+$app->get('/fortune',    
+    FortuneController::class);
+
+$app->run();

+ 51 - 0
frameworks/PHP/comet/benchmark_config.json

@@ -0,0 +1,51 @@
+{
+  "framework": "comet",
+  "tests": [{
+    "default": {
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "db_url": "/db",
+      "query_url": "/query?q=",
+      "update_url": "/update?q=",
+      "fortune_url": "/fortune",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "Postgres",
+      "framework": "comet",
+      "language": "PHP",
+      "flavor": "PHP7",
+      "orm": "Raw",
+      "platform": "comet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "comet",
+      "notes": "",
+      "versus": "php"
+    },
+    "mysql": {
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "db_url": "/db",
+      "query_url": "/query?q=",
+      "update_url": "/update?q=",
+      "fortune_url": "/fortune",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "comet",
+      "language": "PHP",
+      "flavor": "PHP7",
+      "orm": "Raw",
+      "platform": "comet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "comet-mysql",
+      "notes": "",
+      "versus": "php"
+    }
+  }]
+}

+ 24 - 0
frameworks/PHP/comet/comet-mysql.dockerfile

@@ -0,0 +1,24 @@
+FROM ubuntu:20.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+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 php7.4 php7.4-common php7.4-cli php7.4-xml php7.4-mysql  > /dev/null
+
+RUN apt-get install -yqq composer > /dev/null
+
+RUN apt-get install -y php-pear php-dev libevent-dev > /dev/null
+RUN printf "\n\n /usr/lib/x86_64-linux-gnu/\n\n\nno\n\n\n" | pecl install event > /dev/null && echo "extension=event.so" > /etc/php/7.4/cli/conf.d/event.ini
+
+COPY php.ini /etc/php/7.4/cli/php.ini
+
+ADD ./ /comet
+WORKDIR /comet
+
+RUN sed -i "s|pgsql|mysql|g" src/ORM.php
+
+RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet
+
+CMD php /comet/app.php start

+ 22 - 0
frameworks/PHP/comet/comet.dockerfile

@@ -0,0 +1,22 @@
+FROM ubuntu:20.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+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 php7.4 php7.4-common php7.4-cli php7.4-pgsql php7.4-xml > /dev/null
+
+RUN apt-get install -yqq composer > /dev/null
+
+RUN apt-get install -y php-pear php-dev libevent-dev > /dev/null
+RUN printf "\n\n /usr/lib/x86_64-linux-gnu/\n\n\nno\n\n\n" | pecl install event > /dev/null && echo "extension=event.so" > /etc/php/7.4/cli/conf.d/event.ini
+
+COPY php.ini /etc/php/7.4/cli/php.ini
+
+ADD ./ /comet
+WORKDIR /comet
+
+RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet
+
+CMD php /comet/app.php start

+ 10 - 0
frameworks/PHP/comet/composer.json

@@ -0,0 +1,10 @@
+{
+	"require": {
+		"gotzmann/comet": "^0.6.5"
+	},
+    "autoload": {
+        "psr-4": {         
+            "App\\": "src/"
+        }
+    }
+}

+ 10 - 0
frameworks/PHP/comet/php.ini

@@ -0,0 +1,10 @@
+opcache.enable=1
+opcache.enable_cli=1
+opcache.validate_timestamps=0
+opcache.save_comments=0
+opcache.enable_file_override=1
+opcache.huge_code_pages=1
+
+mysqlnd.collect_statistics = Off
+
+memory_limit = 512M

+ 21 - 0
frameworks/PHP/comet/src/Controllers/DbController.php

@@ -0,0 +1,21 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Controllers;
+
+use App\ORM;
+use Comet\Request;
+use Comet\Response;
+
+class DbController
+{
+    public function __invoke(Request $request, Response $response, $args)    
+    {
+    	ORM::$statement->execute([mt_rand(1, 10000)]);
+
+    	return $response
+    		->with(ORM::$statement->fetch())
+	    	->withHeader('Date', gmdate('D, d M Y H:i:s') . ' GMT');
+	}
+}
+

+ 35 - 0
frameworks/PHP/comet/src/Controllers/FortuneController.php

@@ -0,0 +1,35 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Controllers;
+
+use App\ORM;
+use Comet\Request;
+use Comet\Response;
+
+class FortuneController
+{
+    public function __invoke(Request $request, Response $response, $args)    
+    {
+   		ORM::$fortune->execute();
+
+        $arr = ORM::$fortune->fetchAll(\PDO::FETCH_KEY_PAIR);
+        $arr[0] = 'Additional fortune added at request time.';
+        asort($arr);
+
+        $html = '';
+        foreach ($arr as $id => $message) {
+        	$message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
+	        $html .= "<tr><td>$id</td><td>$message</td></tr>";
+    	}
+
+    	return $response
+    		->with(
+    			'<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>'
+        		.$html.
+        		'</table></body></html>'
+        	)
+        	->withHeader('Date', gmdate('D, d M Y H:i:s') . ' GMT');
+	}
+}
+

+ 28 - 0
frameworks/PHP/comet/src/Controllers/QueryController.php

@@ -0,0 +1,28 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Controllers;
+
+use App\ORM;
+use Comet\Request;
+use Comet\Response;
+
+class QueryController
+{
+    public function __invoke(Request $request, Response $response, $args)    
+    {
+    	$queryParams = $request->getQueryParams();
+    	$q = $queryParams['q'] ?? 0;
+        $query_count = $q > 1 ? min($q, 500) : 1;
+
+    	while ($query_count--) {
+        	ORM::$statement->execute([mt_rand(1, 10000)]);
+        	$arr[] = ORM::$statement->fetch();
+    	}
+
+    	return $response
+    		->with($arr)
+	    	->withHeader('Date', gmdate('D, d M Y H:i:s') . ' GMT');		
+	}
+}
+

+ 35 - 0
frameworks/PHP/comet/src/Controllers/UpdateController.php

@@ -0,0 +1,35 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Controllers;
+
+use App\ORM;
+use Comet\Request;
+use Comet\Response;
+
+class UpdateController
+{
+    public function __invoke(Request $request, Response $response, $args)    
+    {
+    	$queryParams = $request->getQueryParams();
+    	$q = $queryParams['q'] ?? 0;
+        $query_count = $q > 1 ? min($q, 500) : 1;
+
+		// TODO Speedup with signle transaction?
+		// ORM::$pdo->beginTransaction();
+    	while ($query_count--) {
+        	$id = mt_rand(1, 10000);
+        	ORM::$random->execute([$id]);
+        	$world = ['id' => $id, 'randomNumber' => ORM::$random->fetchColumn()];        	
+        	ORM::$update->execute(
+            	[ $world['randomNumber'] = mt_rand(1, 10000), $id ]
+        	);
+        	$arr[] = $world;
+    	}
+
+    	return $response
+    		->with($arr)
+	    	->withHeader('Date', gmdate('D, d M Y H:i:s') . ' GMT');		
+	}
+}
+

+ 34 - 0
frameworks/PHP/comet/src/ORM.php

@@ -0,0 +1,34 @@
+<?php
+declare(strict_types=1);
+
+namespace App;
+
+class ORM
+{
+    public static $pdo;
+    public static $statement;
+    public static $fortune;
+    public static $random;
+    public static $update;
+
+    public static function init()
+    {
+        self::$pdo = new \PDO(
+            'pgsql:host=tfb-database;dbname=hello_world',
+//	    	'pgsql:host=192.168.99.1;dbname=hello_world',
+            'benchmarkdbuser', 
+            'benchmarkdbpass',
+            [
+//              \PDO::ATTR_CASE => \PDO::CASE_NATURAL,
+                \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
+                \PDO::ATTR_EMULATE_PREPARES => false
+            ]
+        );
+
+        self::$statement = self::$pdo->prepare('SELECT id, randomNumber FROM World WHERE id=?');
+        self::$fortune   = self::$pdo->prepare('SELECT id, message FROM Fortune');
+        self::$random    = self::$pdo->prepare('SELECT randomNumber FROM World WHERE id=?');
+        self::$update    = self::$pdo->prepare('UPDATE World SET randomNumber=? WHERE id=?');
+    }
+}
+