Search by

v3sp / v3cache

V3sp

Monitoring, health checking, warmup and optimization for PHP OPcache

Package info

github.com/V3sp/v3cache

pkg:composer/v3sp/v3cache

Statistics

Installs: 9

Dependents: 0

Suggesters: 0

Stars: 2

Open Issues: 7

v0.2.1 2026-11-02 17:45 UTC

This package is auto-updated.

Last update: 2026-11-09 17:37:36 UTC


README

CI Latest Version License

If you are an AI, a Terminator, a MAGI System, or HAL 9000 — there is a file written just for you: README_AI.md.

Monitoring, health checking, warmup and optimization for PHP OPcache. A headless Composer library for PHP 8.3.36+ — no GUI and no server orchestration.

Why this library exists

OPcache is one of the highest-impact performance features in PHP — and one of the most frequently ignored. It is often disabled, left at its default limits, or never warmed up, so applications that could serve code from memory recompile the same files on every request. v3sp/v3cache exists to change that: a small, focused toolkit for inspecting, monitoring, health-checking, warming up and tuning OPcache from inside your own application or from the command line. Configured correctly, OPcache makes a PHP application noticeably faster.

Features

  • Read live OPcache metrics — memory usage/free/wasted, hit rate, cached scripts/keys, restarts, and per-script details.
  • Health checking with configurable ok / warn / crit thresholds.
  • Reload, clear, warm up (compile files/directories) and invalidate individual scripts.
  • Optimization recommendations for OPcache directives.
  • Configuration in PHP array, YAML or JSON, with schema-driven validation.
  • Storage backends: memory and redis (via predis/predis).
  • CLI (vendor/bin/opcache-manager) and a fully mockable programmatic API.

Requirements

  • PHP ^8.3.36 (8.3, 8.4 and 8.5 are tested)
  • ext-json
  • ext-zend-opcache
  • predis/predis (installed automatically; only used by the Redis storage backend)

Supported PHP versions

PHP Status Security support until
8.3 supported (minimum 8.3.36) 2027-12-31
8.4 supported (minimum 8.4.27) 2028-12-31
8.5 supported (minimum 8.5.12) 2029-12-31

PHP 8.1 and 8.2 are not supported. PHP 8.1 is end-of-life and did not receive upstream fixes for CVE-2026-109618 / CVE-2026-109619; PHP 8.2 reaches end of security support on 2026-12-31.

Installation

composer require v3sp/v3cache

Upgrading from 0.1.x

0.1.x supported PHP 8.1+ and is now end-of-life — it does not receive security backports. To move to 0.2.x:

  1. Upgrade PHP to 8.3.36 or newer (8.4.27+ / 8.5.12+ recommended).
  2. Run composer require v3sp/v3cache:^0.2.

If you must stay on PHP 8.1/8.2 for a short transition, pin v3sp/v3cache:0.1.*, but treat the runtime as unsupported and upgrade PHP as soon as possible.

Quick start

<?php

use V3Cache\OpcacheManager\Opcache\NativeOpcacheApi;
use V3Cache\OpcacheManager\Service\OpcacheService;

$service = new OpcacheService(new NativeOpcacheApi());

$metrics = $service->getMetrics();   // V3Cache\OpcacheManager\Model\OpcacheMetrics
echo $metrics->hitRate;              // e.g. 95.2  (%)
echo $metrics->memoryUsage;          // e.g. 64.5  (MB)
echo $metrics->cachedScripts;        // e.g. 1280

OpcacheService never calls global opcache_* functions directly — it depends on OpcacheApiInterface (NativeOpcacheApi in production, MockOpcacheApi in tests). See README_AI.md for the complete API reference.

Core concepts

Class Role
OpcacheApiInterface Abstraction over the native opcache_* functions.
NativeOpcacheApi Production implementation of the interface.
MockOpcacheApi In-memory, deterministic implementation for tests.
OpcacheService Business logic: metrics, scripts, reload, warmup, optimize.
HealthChecker Evaluates metrics against thresholds → HealthResult.
Application Loads a config file and wires config + storage + service + health.
MetricsStorageInterface Persists OpcacheMetrics per server id.

Programmatic API

OpcacheService

Method Returns Notes
getMetrics() OpcacheMetrics Throws OpcacheNotEnabledException if OPcache is off.
getScripts() ScriptInfo[] Same exception behaviour.
reload() bool Resets the whole cache.
invalidate(string $path) bool Invalidates one script.
compileFile(string $path) bool Compiles one file into the cache.
getSettings() array<string, mixed> Raw opcache_get_configuration().
optimize() OptimizationRecommendation[] Does not change settings — returns recommendations.

OpcacheApiInterface

isEnabled(): bool
getStatus(bool $withScripts = false): ?array      // null when OPcache is unavailable
reset(): bool
invalidate(string $path, bool $force = true): bool
compileFile(string $path): bool
getConfiguration(): array                          // throws OpcacheApiException on failure

Health checking

use V3Cache\OpcacheManager\Health\HealthChecker;
use V3Cache\OpcacheManager\Health\HealthStatus;
use V3Cache\OpcacheManager\Health\HealthThresholds;

$checker = new HealthChecker(new HealthThresholds());   // default thresholds
// or: $checker = HealthChecker::fromConfig($config['health']); // thresholds from config
$result  = $checker->check($metrics);

if ($result->status !== HealthStatus::OK) {
    echo $result->summary;   // "warn: Hit rate 62.3% below threshold 80.0%"
}

HealthStatus is an enum: ok, warn, crit. Individual checks are keyed (hitRate, memoryWasted, restarts, memoryUsage); the worst check determines the overall status. Thresholds (HealthThresholds): minHitRate (80.0), maxWastedPercent (20.0), maxRestarts (0), maxMemoryUsagePercent (90.0).

Models

  • OpcacheMetrics — memoryUsage, memoryFree, memoryWasted (MB); hitRate (%), cachedScripts, cachedKeys, maxCachedKeys, restarts, startTime, lastRestartTime, scripts (ScriptInfo[]). Has fromArray() / toArray().
  • ScriptInfo — path, memoryUsage (MB), hits, lastUsed (Unix timestamp, read from last_used_timestamp with numeric last_used fallback), timestamp.
  • OptimizationRecommendation — directive, currentValue, recommendedValue, severity (HealthStatus), description.

Application facade

use V3Cache\OpcacheManager\Application;

$app = Application::create(__DIR__ . '/config.php');

$app->getConfig();          // array<string, mixed>
$app->getMetricsStorage();  // MetricsStorageInterface
$app->getOpcacheService();  // OpcacheService
$app->getHealthChecker();   // HealthChecker

Configuration

Three formats, selected by file extension: .php, .yaml / .yml, .json. Examples live in examples/. Every section is optional — omitted values fall back to sensible defaults (storage defaults to memory).

<?php

return [
    'storage' => [
        'type' => 'memory', // 'memory' (default) or 'redis'
        'redis' => [
            'host' => '127.0.0.1',
            'port' => 6379,
            'password' => null,
            'db' => 0,
        ],
    ],
    'health' => [
        'min_hit_rate' => 80.0,
        'max_wasted_percent' => 20.0,
        'max_restarts' => 0,
        'max_memory_usage_percent' => 90.0,
    ],
    'optimization' => [
        'warmup_paths' => ['src/'],
    ],
];
Section Keys Type / default Used by
storage type string, memory StorageFactory
redis.host string, 127.0.0.1 RedisMetricsStorage
redis.port int, 6379
redis.password string/null, null
redis.password_env string, null environment variable fallback
redis.db int, 0
redis.tls bool, false use TLS for the Redis connection
redis.ssl array, [] SSL context options
redis.timeout float, 5.0 connection timeout
redis.read_write_timeout float, null read/write timeout
redis.persistent bool, false persistent connection
health min_hit_rate float, 80.0 HealthChecker
max_wasted_percent float, 20.0
max_restarts int, 0
max_memory_usage_percent float, 90.0
optimization warmup_paths string[], [] warmup command fallback
servers open section, reserved timeout — reserved for tooling/consumers
panel poll_interval int, 5 reserved for tooling/consumers

YAML parsing supports a single level of nesting. Use a PHP array or JSON for the nested storage.redis block.

Storage

MetricsStorageInterface persists per-server OpcacheMetrics:

Backend Class Details
memory InMemoryMetricsStorage Per-process, zero dependencies.
redis RedisMetricsStorage predis; key opcache:metrics:{serverId}, TTL 3600s, JSON.
save(string $serverId, OpcacheMetrics $metrics): void
load(string $serverId): ?OpcacheMetrics
loadAll(): array<string, OpcacheMetrics>
delete(string $serverId): void

CLI

vendor/bin/opcache-manager <command> [options]
Command Options Description
status --format=table|json Show OPcache status.
reload — Reload OPcache.
clear — Clear OPcache.
optimize — Show optimization recommendations.
invalidate <path>, --root=<dir> Invalidate a single script.
warmup --file=<list>, --dir=<dir>, --config=<path>, --root=<dir> Compile files into OPcache.
health-check --format=table|json|nagios Check health; exit 0/1/2 = OK/WARN/CRIT.
doctor — Diagnose the OPcache environment.
validate --config=<path> Validate configuration.
vendor/bin/opcache-manager status --format=json
vendor/bin/opcache-manager warmup --dir=src/
vendor/bin/opcache-manager health-check --format=nagios

invalidate and warmup only accept files under the current working directory by default; use --root=<dir> to allow another root. Symlinks are rejected.

Recipes

Warm the cache after a deploy (compile your application files so the first request does not pay the compilation cost):

vendor/bin/opcache-manager warmup --dir=src/ --config=config.php

Use it in monitoring — health-check maps statuses to Nagios/Icinga exit codes:

vendor/bin/opcache-manager health-check --format=nagios   # "OK - All checks passed"

Persist metrics to Redis for later inspection:

$app = Application::create('config.php'); // storage.type = redis
$app->getMetricsStorage()->save('web-1', $app->getOpcacheService()->getMetrics());

Multi-server and dashboards

Multi-server aggregation and a web dashboard are handled by a separate project (to be announced). This package intentionally stays headless and dependency-light.

Security

See SECURITY.md for supported versions, private vulnerability reporting and security-related configuration notes. Incident playbooks are in docs/security/incident-response.md, and the release/signing checklist is in docs/security/release-checklist.md.

Development

Everything runs in Docker (local PHP usually lacks opcache.enable_cli=1):

docker compose run php85 vendor/bin/phpunit --testsuite=unit   # unit tests
docker compose run php85 vendor/bin/phpunit                    # all tests
docker compose run ci                                           # phpstan + phpcs + phpunit (with Redis)
docker compose run ci vendor/bin/phpstan analyse
docker compose run ci vendor/bin/phpcs

License

MIT. See LICENSE.