Skip to content

Commit 2fc2adf

Browse files
committed
#53: Add AmphpPHP HTTP server for performance comparison
Create AmphpPHP-based HTTP server using production-ready components (SocketHttpServer, ClosureRequestHandler, DefaultErrorHandler) for fair benchmark comparison against optimized async extension server. Both servers implement identical endpoint logic and JSON response caching for accurate performance testing.
1 parent 81035b2 commit 2fc2adf

File tree

4 files changed

+415
-0
lines changed

4 files changed

+415
-0
lines changed

benchmarks/amphp/README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# AmphpPHP vs Async Extension Benchmark Comparison
2+
3+
Performance comparison between PHP Async extension and AmphpPHP v3.x
4+
5+
## Setup
6+
7+
### Install AmphpPHP dependencies:
8+
```bash
9+
cd /mnt/c/php/php-src/ext/async/benchmarks/amphp
10+
composer install
11+
```
12+
13+
## Running Servers
14+
15+
### 1. Async Extension Server (Keep-Alive optimized):
16+
```bash
17+
cd /mnt/c/php/php-src/ext/async/benchmarks
18+
php http_server_keepalive.php 127.0.0.1 8080
19+
```
20+
21+
### 2. AmphpPHP Server:
22+
```bash
23+
cd /mnt/c/php/php-src/ext/async/benchmarks/amphp
24+
php http_server_amphp.php 127.0.0.1 8081
25+
```
26+
27+
## Benchmark Tests
28+
29+
### Test Async Extension:
30+
```bash
31+
wrk -t12 -c400 -d30s --http1.1 http://127.0.0.1:8080/benchmark
32+
wrk -t12 -c400 -d30s --http1.1 http://127.0.0.1:8080/small
33+
wrk -t12 -c400 -d30s --http1.1 http://127.0.0.1:8080/json
34+
```
35+
36+
### Test AmphpPHP:
37+
```bash
38+
wrk -t12 -c400 -d30s --http1.1 http://127.0.0.1:8081/benchmark
39+
wrk -t12 -c400 -d30s --http1.1 http://127.0.0.1:8081/small
40+
wrk -t12 -c400 -d30s --http1.1 http://127.0.0.1:8081/json
41+
```
42+
43+
## Expected Metrics to Compare
44+
45+
- **Requests per second (RPS)**
46+
- **Latency (avg/p50/p90/p95/p99)**
47+
- **Memory usage**
48+
- **CPU utilization**
49+
- **Connection handling efficiency**
50+
51+
## Features Comparison
52+
53+
| Feature | Async Extension | AmphpPHP |
54+
|---------|----------------|----------|
55+
| Keep-Alive | ✅ Custom optimized | ✅ Built-in |
56+
| JSON Caching | ✅ Pre-cached | ✅ Pre-cached |
57+
| Event Loop | ✅ libuv-based | ✅ ReactPHP/Revolt |
58+
| Connection Pooling | ✅ Manual | ✅ Automatic |
59+
| HTTP Compliance | ⚡ Minimal (perf) | ✅ Full HTTP/1.1 |
60+
61+
## Notes
62+
63+
- Both servers use identical response caching for fair comparison
64+
- Same endpoints: `/`, `/health`, `/small`, `/json`, `/benchmark`
65+
- Both optimized for maximum performance in benchmark scenarios
66+
- Async extension should show lower latency due to C-level optimizations
67+
- AmphpPHP may show better HTTP compliance and feature richness

benchmarks/amphp/composer.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "async-vs-amphp/benchmark",
3+
"description": "Performance comparison between async extension and AmphpPHP",
4+
"type": "project",
5+
"require": {
6+
"php": "^8.1",
7+
"amphp/http-server": "^3.0",
8+
"amphp/socket": "^2.0"
9+
},
10+
"autoload": {
11+
"psr-4": {
12+
"AsyncBench\\": "src/"
13+
}
14+
},
15+
"config": {
16+
"optimize-autoloader": true
17+
}
18+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
/**
3+
* HTTP Server using AmphpPHP Built-in Server for Performance Comparison
4+
* Uses AmphpPHP v3.x ready-made HTTP server implementation
5+
*
6+
* Usage:
7+
* composer install
8+
* php http_server_amphp.php [host] [port]
9+
*
10+
* Test with wrk:
11+
* wrk -t12 -c400 -d30s --http1.1 http://127.0.0.1:8080/
12+
*/
13+
14+
require_once __DIR__ . '/vendor/autoload.php';
15+
16+
use Amp\Http\Server\DefaultErrorHandler;
17+
use Amp\Http\Server\Request;
18+
use Amp\Http\Server\RequestHandler\ClosureRequestHandler;
19+
use Amp\Http\Server\Response;
20+
use Amp\Http\Server\SocketHttpServer;
21+
use Amp\Socket\InternetAddress;
22+
use Psr\Log\NullLogger;
23+
24+
// Increase memory limit
25+
ini_set('memory_limit', '512M');
26+
27+
// Configuration
28+
$host = $argv[1] ?? '127.0.0.1';
29+
$port = (int)($argv[2] ?? 8080);
30+
31+
echo "=== AmphpPHP Built-in HTTP Server ===\n";
32+
echo "Starting server on http://$host:$port\n";
33+
echo "Press Ctrl+C to stop\n\n";
34+
35+
// Cached JSON responses for performance (same as async version)
36+
$cachedResponses = [
37+
'/' => json_encode(['message' => 'Hello from AmphpPHP Server!', 'server' => 'amphp'], JSON_UNESCAPED_SLASHES),
38+
'/health' => json_encode(['status' => 'healthy', 'keepalive' => true], JSON_UNESCAPED_SLASHES),
39+
'/small' => json_encode(['ok' => true], JSON_UNESCAPED_SLASHES),
40+
'/json' => json_encode(['data' => range(1, 100)], JSON_UNESCAPED_SLASHES),
41+
];
42+
43+
// Create request handler using AmphpPHP's ready-made components
44+
$requestHandler = new ClosureRequestHandler(function (Request $request): Response {
45+
global $cachedResponses;
46+
47+
$uri = $request->getUri()->getPath();
48+
49+
// Use cached responses for static content
50+
if (isset($cachedResponses[$uri])) {
51+
return new Response(
52+
status: 200,
53+
headers: [
54+
'content-type' => 'application/json',
55+
'server' => 'AmphpBuiltIn/1.0'
56+
],
57+
body: $cachedResponses[$uri]
58+
);
59+
}
60+
61+
// Dynamic endpoints
62+
if ($uri === '/benchmark') {
63+
$responseBody = json_encode([
64+
'id' => uniqid(),
65+
'time' => microtime(true)
66+
], JSON_UNESCAPED_SLASHES);
67+
68+
return new Response(
69+
status: 200,
70+
headers: [
71+
'content-type' => 'application/json',
72+
'server' => 'AmphpBuiltIn/1.0'
73+
],
74+
body: $responseBody
75+
);
76+
}
77+
78+
// 404 response
79+
$responseBody = json_encode([
80+
'error' => 'Not Found',
81+
'uri' => $uri
82+
], JSON_UNESCAPED_SLASHES);
83+
84+
return new Response(
85+
status: 404,
86+
headers: [
87+
'content-type' => 'application/json',
88+
'server' => 'AmphpBuiltIn/1.0'
89+
],
90+
body: $responseBody
91+
);
92+
});
93+
94+
// Create and start HTTP server using AmphpPHP's production-ready server
95+
try {
96+
$server = SocketHttpServer::createForDirectAccess(new NullLogger());
97+
98+
$server->expose(new InternetAddress($host, $port));
99+
$server->start($requestHandler, new DefaultErrorHandler());
100+
101+
echo "Server listening on $host:$port using AmphpPHP built-in components\n";
102+
echo "Try: curl http://$host:$port/\n";
103+
echo "Benchmark: wrk -t12 -c400 -d30s --http1.1 http://$host:$port/benchmark\n\n";
104+
105+
// Keep server running
106+
Amp\trapSignal(SIGINT);
107+
$server->stop();
108+
109+
} catch (Exception $e) {
110+
echo "Server error: " . $e->getMessage() . "\n";
111+
exit(1);
112+
}

0 commit comments

Comments
 (0)