Skip to content

Commit 5a7fb74

Browse files
Merge branch 'MDA2AV:main' into sch/native-sha1
2 parents cf62cbf + e0a682e commit 5a7fb74

81 files changed

Lines changed: 1847 additions & 154 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

frameworks/rack-falcon/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
"pipelined",
1212
"limited-conn"
1313
],
14-
"maintainers": []
14+
"maintainers": ["p8"]
1515
}

frameworks/rack-iodine/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
"pipelined",
1212
"limited-conn"
1313
],
14-
"maintainers": []
14+
"maintainers": ["p8"]
1515
}

frameworks/rage/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@
1818
"async-db",
1919
"static"
2020
],
21-
"maintainers": []
21+
"maintainers": ["p8"]
2222
}

frameworks/rails/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@
1919
"async-db",
2020
"static"
2121
],
22-
"maintainers": []
22+
"maintainers": ["p8"]
2323
}

frameworks/roda/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@
1919
"async-db",
2020
"static"
2121
],
22-
"maintainers": []
22+
"maintainers": ["p8"]
2323
}

frameworks/sinatra/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@
1919
"async-db",
2020
"static"
2121
],
22-
"maintainers": []
22+
"maintainers": ["p8"]
2323
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM trueasync/php-true-async:0.7.0-beta.4-php8.6
2+
3+
RUN printf '%s\n' \
4+
'opcache.jit=1255' \
5+
'opcache.jit_buffer_size=128M' \
6+
'opcache.memory_consumption=256' \
7+
'opcache.max_accelerated_files=10000' \
8+
'opcache.validate_timestamps=0' \
9+
'memory_limit=1024M' \
10+
> /etc/php.d/99-arena.ini \
11+
&& rm -f /etc/php.d/xdebug.ini
12+
13+
WORKDIR /app
14+
COPY entry.php PostgreSQL.php SQLite.php /app/
15+
16+
EXPOSE 8080 8443
17+
18+
CMD ["php", "/app/entry.php"]
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* Postgres access for TrueAsync HTTP handlers.
7+
*
8+
* Uses the native PDO connection pool shipped with ext-async (PDO::ATTR_POOL_*)
9+
* — each PDO method call grabs an idle connection, runs, and returns it to the
10+
* pool. Coroutines that find the pool exhausted park on the libuv reactor
11+
* instead of blocking the worker thread.
12+
*/
13+
final class PostgreSQL
14+
{
15+
private static ?PDO $pdo = null;
16+
private static bool $available = false;
17+
private const SQL =
18+
'SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count '
19+
. 'FROM items WHERE price BETWEEN ? AND ? LIMIT ?';
20+
private const FORTUNES_SQL = 'SELECT id, message FROM fortune';
21+
22+
public static function init(): void
23+
{
24+
$url = getenv('DATABASE_URL') ?: '';
25+
if ($url === '') {
26+
return;
27+
}
28+
29+
$parts = parse_url($url);
30+
$dsn = sprintf(
31+
'pgsql:host=%s;port=%s;dbname=%s',
32+
$parts['host'] ?? 'localhost',
33+
$parts['port'] ?? 5432,
34+
ltrim($parts['path'] ?? '/benchmark', '/')
35+
);
36+
37+
// PG sweet spot is ~4×CPU backends; more = lock/context contention.
38+
// Cap total at min(DATABASE_MAX_CONN, 4×CPU), split per worker.
39+
$cpus = \Async\available_parallelism();
40+
$workers = max(1, (int)(getenv('WORKERS') ?: $cpus));
41+
$envCap = (int)(getenv('DATABASE_MAX_CONN') ?: 4 * $cpus);
42+
$totalMax = min($envCap, 4 * $cpus);
43+
$maxConn = max(2, intdiv($totalMax, $workers));
44+
$minConn = (int)(getenv('DATABASE_MIN_CONN') ?: max(1, intdiv($maxConn, 2)));
45+
46+
self::$pdo = new PDO(
47+
$dsn,
48+
$parts['user'] ?? 'bench',
49+
$parts['pass'] ?? 'bench',
50+
[
51+
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
52+
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
53+
PDO::ATTR_EMULATE_PREPARES => false,
54+
PDO::ATTR_POOL_ENABLED => true,
55+
PDO::ATTR_POOL_MIN => $minConn,
56+
PDO::ATTR_POOL_MAX => $maxConn,
57+
PDO::ATTR_POOL_STMT_CACHE_SIZE => 32,
58+
]
59+
);
60+
61+
self::$available = true;
62+
}
63+
64+
public static function query(float $min, float $max, int $limit = 50): string
65+
{
66+
if (!self::$available) {
67+
self::init();
68+
if (!self::$available) {
69+
return '{"items":[],"count":0}';
70+
}
71+
}
72+
73+
try {
74+
$stmt = self::$pdo->prepare(self::SQL);
75+
$stmt->execute([$min, $max, $limit]);
76+
$rows = [];
77+
while ($row = $stmt->fetch()) {
78+
$rows[] = [
79+
'id' => $row['id'],
80+
'name' => $row['name'],
81+
'category' => $row['category'],
82+
'price' => $row['price'],
83+
'quantity' => $row['quantity'],
84+
'active' => (bool)$row['active'],
85+
'tags' => json_decode($row['tags'], true),
86+
'rating' => [
87+
'score' => $row['rating_score'],
88+
'count' => $row['rating_count'],
89+
],
90+
];
91+
}
92+
return json_encode(
93+
['items' => $rows, 'count' => count($rows)],
94+
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
95+
);
96+
} catch (\Throwable) {
97+
return '{"items":[],"count":0}';
98+
}
99+
}
100+
101+
/**
102+
* @return list<array{id:int,message:string}>
103+
*/
104+
public static function fortunes(): array
105+
{
106+
if (!self::$available) {
107+
self::init();
108+
if (!self::$available) {
109+
return [];
110+
}
111+
}
112+
113+
try {
114+
$stmt = self::$pdo->prepare(self::FORTUNES_SQL);
115+
$stmt->execute();
116+
$rows = [];
117+
while ($row = $stmt->fetch()) {
118+
$rows[] = ['id' => (int)$row['id'], 'message' => (string)$row['message']];
119+
}
120+
return $rows;
121+
} catch (\Throwable) {
122+
return [];
123+
}
124+
}
125+
}

0 commit comments

Comments
 (0)