# Ví dụ QHturbo: tự chạy thử và tự đo hiệu năng

[English](README.md) · **Tiếng Việt**

Mỗi ví dụ có hai phiên bản: `fpm.php` viết theo kiểu truyền thống (script chạy lại từ đầu ở mỗi request, giống PHP-FPM) và `app.php` là cùng chức năng đó cho QHturbo Performance (chỉ khởi động một lần cho mỗi worker). `compare.sh` khởi động cả hai, tạo tải bằng `bench.php` rồi in số request/giây và độ trễ cạnh nhau để so sánh.

## Chuẩn bị

```bash
git clone https://github.com/qhsvn/QHTurbo.git && cd QHTurbo
cp -r /duong-dan/toi/examples ./examples     # để script tìm thấy ../runtime/bin/qhturbo-serve
php -v                                       # cần 8.1+ có curl, pcntl, posix (mysqli cho 04-mysql)
```

Nếu đã cài PHP của QHturbo thì dùng luôn: `PHP=/opt/qhturbo/8.5/bin/php ./examples/compare.sh all`.

## Chạy

```bash
bash examples/compare.sh hello        # 01: không có chi phí khởi động, dùng làm mốc
bash examples/compare.sh framework    # 02: khởi động framework mỗi request so với một lần mỗi worker
bash examples/compare.sh async-io     # 03: 3 lời gọi backend 20 ms, tuần tự so với song song
bash examples/compare.sh mysql        # 04: cần MySQL/MariaDB, xem 04-mysql/README.vi.md
php examples/06-async/demo.php        # 06: các mẫu async ngay trên terminal, không cần server
bash examples/compare.sh all          # 01 + 02 + 03
php examples/05-cpu-jit/cpu.php --compare     # trình thông dịch, OPcache và JIT
```

Tuỳ chỉnh: `WORKERS=2` (số tiến trình mỗi bên), `C=64` (số kết nối), `D=10` (số giây), `P=1` (số tiến trình tạo tải). Nên để `WORKERS` nhỏ hơn số CPU vì công cụ tạo tải cũng cần CPU.

Muốn so với nginx + PHP-FPM thật thay cho `php -S`: chép `fpm.php` của ví dụ vào một site rồi đặt `CLASSIC_URL=http://site-cua-ban/fpm.php`.

## Mỗi ví dụ cho thấy điều gì

| Ví dụ | File | Cần chú ý |
|---|---|---|
| `01-hello` | `fpm.php`, `app.php` | Không có framework, không có gì để khởi động. **Không kỳ vọng tăng nhiều**: QHturbo nhanh hơn nhờ bỏ bớt việc phải làm, không phải nhờ PHP chạy nhanh hơn. |
| `02-framework` | `common/framework.php` + `fpm.php`, `app.php` | Một framework mô phỏng (300 class, 40 file config, DI container, 200 route). Cách truyền thống tốn `boot_ms` ở mỗi request, worker chỉ tốn một lần. |
| `03-async-io` | `backend.php`, `fpm.php`, `app.php` | Mỗi request gọi 3 service, mỗi service mất 20 ms. Truyền thống: ~60 ms và tiến trình bị chặn. QHturbo: `async()` + `all()` chỉ mất ~20 ms và worker vẫn phục vụ request khác trong lúc chờ. |
| `04-mysql` | API cửa hàng hoàn chỉnh: `schema.sql`, `seed.php`, `.env`, `app.php` (bất đồng bộ), `fpm.php` (PDO), `deploy/` | Sẵn sàng đưa lên máy chủ thật và đo từng route bằng `bench-server.sh`. Xem [04-mysql/README.vi.md](04-mysql/README.vi.md). |
| `06-async` | `demo.php`, `app.php`, `lib.php` | Các mẫu async: `all`, `timeout`, `settle`, `race`, `mapLimit`, `retry`, cache Redis. `php examples/06-async/demo.php` chạy ngay không cần server. Xem [06-async/README.vi.md](06-async/README.vi.md). |
| `05-cpu-jit` | `cpu.php` | Tác vụ thuần CPU (đệ quy, tính số thực, vòng lặp, mảng, chuỗi, JSON, object). Dùng `--php=/usr/bin/php,/opt/qhturbo/8.5/bin/php` để so hai bản PHP. |

## Kết quả đo thử (chỉ để tham khảo)

PHP 8.3.6, container cloud dùng chung 4 vCPU, mỗi bên 2 tiến trình, 64 kết nối, công cụ tạo tải chạy cùng máy, 5 giây mỗi lượt:

| Ví dụ | Truyền thống (`php -S`) | Worker QHturbo | |
|---|---|---|---|
| 01 hello | 14.507 req/s, p50 4,2 ms | 9.083 req/s, p50 1,4 ms | 0,6× |
| 02 framework | 4.720 req/s, p50 11,9 ms | 18.781 req/s, p50 3,3 ms | **4,0×** |
| 03 I/O bất đồng bộ | 48 req/s, p50 1.321 ms | 1.618 req/s, p50 40 ms | **33,7×** |
| 05 CPU (trung bình nhân) | thông dịch 1,00× | OPcache 1,25×, JIT 1,82× | |

Số liệu của bạn sẽ khác: hãy đo trên máy chủ của bạn, với ứng dụng của bạn, và chạy mỗi bài vài lần. `php -S` gần giống PHP-FPM cho mục đích này (chạy lại script ở mỗi request) nhưng không phải server dùng cho production.

## Dùng riêng bench.php

```bash
php examples/bench.php http://127.0.0.1:8080/ -c 64 -d 10          # một tiến trình tạo tải
php examples/bench.php http://127.0.0.1:8080/ -c 256 -d 15 -p 4    # 4 tiến trình tạo tải
php examples/bench.php http://127.0.0.1:8080/ --json
```

Kết quả gồm request/giây, độ trễ trung bình/p50/p90/p99/max, mã trạng thái và số lỗi. Trên khoảng 10–20 nghìn req/s thì chính client PHP trở thành nút thắt; hãy thêm `-p` hoặc dùng `wrk`.
