A lightweight PHP MVC dashboard for viewing and comparing CPU-based TinyGPT training benchmarks stored in MariaDB.
The application is part of the Tiny LLM project and provides a web interface and versioned JSON API for benchmark runs, machines, models, and datasets.
- Dashboard — overview of benchmark results.
- Machines — list machines and inspect individual machine details and runs.
- Models and datasets — browse model and dataset records.
- Benchmark run details — inspect an individual run.
- Benchmark comparison — filter runs by dataset, model, and total training-step count; compare runtime, throughput, and loss values.
- Benchmark history — chronological throughput charts with dataset, model, and machine filters.
- Versioned JSON API — read machines, models, datasets, and benchmark runs under
/api/v1. - Responsive navigation and styling — shared navigation and CSS-based layout.
The comparison page deliberately lists individual matching runs. Repeated measurements are not silently averaged, so results from the same machine remain visible.
- PHP with a small custom MVC structure and router
- MariaDB/MySQL
- PHP's
mysqliextension - Apache-compatible front-controller routing
The application does not require a full-stack PHP framework.
- PHP 8.2 or later (the production development environment has used PHP 8.5)
- PHP
mysqliextension - MariaDB or MySQL
- Apache with PHP support, or another PHP-capable web server configured to route requests to
index.php
The SQL schema and benchmark data are maintained separately in the Tiny LLM training repository.
git clone https://github.com/oppiet30/tiny-llm-web.git
cd tiny-llm-webIf the repository is already cloned, update it with:
git pull --ff-onlyCreate or use the tiny_llm_benchmarks database and load the schema maintained in the Tiny LLM repository.
The application expects the database to contain the machines, models, datasets, and benchmark-runs tables used by the dashboard.
The front controller loads config.php, which in turn loads config.local.php. Create your local configuration by copying the example:
cp config.example.php config.local.phpEdit config.local.php and set the database host, username, password, and database name for your environment. For example:
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$db = new mysqli(
'localhost',
'your_database_user',
'your_database_password',
'tiny_llm_benchmarks'
);
$db->set_charset('utf8mb4');Use a database account with only the permissions the application needs. Do not commit config.local.php, real passwords, or other credentials to Git.
Configure Apache to serve the project directory and allow the repository's .htaccess front-controller rules to work. Ensure the required PHP extensions are enabled.
For a per-user Apache installation, the URL may look like:
http://localhost/~USERNAME/tiny-llm-web/
The exact URL depends on the server configuration. The application derives its base path from the request script location, so links can work when the project is installed in a subdirectory.
| Route | Purpose |
|---|---|
/ |
Dashboard |
/machines |
Machine listing |
/machines/{id} |
Machine details |
/models |
Model listing |
/models/{id} |
Model details |
/datasets |
Dataset listing |
/datasets/{id} |
Dataset details |
/runs/{id} |
Individual benchmark run |
/compare |
Compare matching benchmark runs |
/history |
Historical throughput charts |
| Route | Purpose |
|---|---|
/api/v1/machines |
List machines |
/api/v1/machines/{id} |
Retrieve one machine |
/api/v1/machines/{id}/runs |
List runs for a machine |
/api/v1/models |
List models |
/api/v1/models/{id} |
Retrieve one model |
/api/v1/datasets |
List datasets |
/api/v1/datasets/{id} |
Retrieve one dataset |
/api/v1/runs |
List benchmark runs |
/api/v1/runs/{id} |
Retrieve one benchmark run |
All API routes use GET. Lists return { "data": [...], "count": 2 }; individual records return { "data": {...} }. Machine-run lists also include machine_id and hostname. Empty lists return HTTP 200 with data: [] and count: 0.
Malformed, zero, out-of-range, or missing IDs return HTTP 404 with an error message. IDs must fit PHP's positive integer range. Unknown API routes also return JSON 404; unsupported methods on known routes return JSON 405 with Allow: GET. Unexpected application/database exceptions return JSON 500 with a generic error; details go to the server log. Local configuration should throw exceptions rather than print credentials or call die() (see config.example.php).
When installed below a URL prefix, prepend that prefix to the routes above. For example:
curl -i https://example.com/tiny-llm-web/api/v1/machines
curl -i https://example.com/tiny-llm-web/api/v1/runs/1
curl -i https://example.com/tiny-llm-web/api/v1/runs/0The MariaDB CI job runs python3 scripts/check-api.py against an isolated copy of the application and the disposable fixture database. It checks all nine endpoints, invalid/missing IDs, JSON content types, unsupported methods, subdirectory routing, and safe error responses. It does not access production configuration.
The /compare page filters by:
- Dataset
- Model
- Total training-step count
Only runs matching all three selections are included. Each matching run shows the machine and CPU, runtime, steps per second, training loss, validation loss, and run date. Links lead to the corresponding run and machine detail pages.
Throughput is calculated from the number of steps completed in the run divided by its runtime. For resumed runs, the database query uses steps_this_run when available and otherwise falls back to training_steps.
The Chart view selector offers machine averages and individual runs; both keep the individual results table. See benchmark reproduction and measurement methodology for runnable training commands, timing boundaries, resumed-run calculations, and comparison limitations.
When comparing hardware, keep the dataset, model configuration, and training-step count the same. Repeated runs help reveal normal performance variation; a single run is not enough to estimate that variation.
The application uses a small custom router in core/Router.php, controllers in app/Controllers/, data models in app/Models/, templates in app/Views/, and shared helpers in app/Helpers/.
Before committing PHP changes, check syntax:
find . -path './.git' -prune -o -name '*.php' -type f -print0 \
| xargs -0 -n1 php -lPHPUnit 13 tests and GitHub Actions are established on main. Development tests require PHP 8.5 with mysqli, dom, mbstring, xml, and xmlwriter, plus Composer. Install and run them with:
composer update --no-interaction --prefer-dist
composer testAlternatively, use the isolated PHP 8.5 Docker image:
docker build -f Dockerfile.test -t tiny-llm-web-tests .
docker run --rm tiny-llm-web-testsMariaDB integration tests skip without a configured test database. GitHub Actions runs them separately against a disposable MariaDB 11.8 database initialized from tests/fixtures/mariadb-integration.sql; never load that fixture into the production benchmark database. The workflow also checks PHP syntax, runs the Docker PHPUnit suite, and runs API HTTP checks against the disposable database. Check the Actions tab for the current results.
- Keep database credentials in the ignored local configuration file.
- Do not commit access tokens, passwords, or production secrets.
- Use a least-privilege database account rather than a database administrator account.
- Restrict access to benchmark and API endpoints as appropriate for your deployment environment.
This project is actively developed. Check TODO.md for the current website checklist and planned improvements.
Tiny LLM is free and open source. Optional sponsorships help cover domain renewal, website hosting, and continued development.
Support Tiny LLM on GitHub Sponsors
See LICENSE for the project's license terms.