Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
124 lines
4.7 KiB
PHP
124 lines
4.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Performance Test: Native PHP Reflection vs Cached Reflection
|
|
*
|
|
* This test measures the actual performance difference between
|
|
* native PHP reflection and the cached reflection provider.
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Framework\Core\ValueObjects\ClassName;
|
|
use App\Framework\ReflectionLegacy\CachedReflectionProvider;
|
|
use ReflectionClass;
|
|
use ReflectionMethod;
|
|
|
|
// Test class
|
|
class TestClass {
|
|
public function __construct(
|
|
private string $param1,
|
|
private int $param2,
|
|
private ?object $param3 = null
|
|
) {}
|
|
|
|
public function testMethod(string $arg1, int $arg2): void {}
|
|
}
|
|
|
|
$iterations = 1000;
|
|
$className = TestClass::class;
|
|
|
|
echo "=== Reflection Performance Test ===\n\n";
|
|
echo "Testing $iterations iterations for class: $className\n\n";
|
|
|
|
// Test 1: Native ReflectionClass
|
|
$start = microtime(true);
|
|
for ($i = 0; $i < $iterations; $i++) {
|
|
$reflection = new ReflectionClass($className);
|
|
$methods = $reflection->getMethods();
|
|
$constructor = $reflection->getConstructor();
|
|
if ($constructor) {
|
|
$params = $constructor->getParameters();
|
|
}
|
|
}
|
|
$nativeTime = microtime(true) - $start;
|
|
$nativeTimeMs = ($nativeTime * 1000);
|
|
$nativeTimePerOp = ($nativeTimeMs / $iterations);
|
|
|
|
echo "1. Native ReflectionClass:\n";
|
|
echo " Total: " . round($nativeTimeMs, 2) . " ms\n";
|
|
echo " Per operation: " . round($nativeTimePerOp, 4) . " ms\n";
|
|
echo " Per operation: " . round($nativeTimePerOp * 1000, 2) . " microseconds\n\n";
|
|
|
|
// Test 2: Native ReflectionMethod (most common operation)
|
|
$start = microtime(true);
|
|
for ($i = 0; $i < $iterations; $i++) {
|
|
$reflection = new ReflectionMethod($className, 'testMethod');
|
|
$params = $reflection->getParameters();
|
|
foreach ($params as $param) {
|
|
$type = $param->getType();
|
|
$name = $param->getName();
|
|
$hasDefault = $param->isDefaultValueAvailable();
|
|
}
|
|
}
|
|
$nativeMethodTime = microtime(true) - $start;
|
|
$nativeMethodTimeMs = ($nativeMethodTime * 1000);
|
|
$nativeMethodTimePerOp = ($nativeMethodTimeMs / $iterations);
|
|
|
|
echo "2. Native ReflectionMethod (getParameters):\n";
|
|
echo " Total: " . round($nativeMethodTimeMs, 2) . " ms\n";
|
|
echo " Per operation: " . round($nativeMethodTimePerOp, 4) . " ms\n";
|
|
echo " Per operation: " . round($nativeMethodTimePerOp * 1000, 2) . " microseconds\n\n";
|
|
|
|
// Test 3: Cached ReflectionProvider (first run - no cache)
|
|
$provider = new CachedReflectionProvider();
|
|
$classNameObj = ClassName::create($className);
|
|
|
|
$start = microtime(true);
|
|
for ($i = 0; $i < $iterations; $i++) {
|
|
$class = $provider->getClass($classNameObj);
|
|
$methods = $provider->getMethods($classNameObj);
|
|
$params = $provider->getMethodParameters($classNameObj, '__construct');
|
|
}
|
|
$cachedFirstTime = microtime(true) - $start;
|
|
$cachedFirstTimeMs = ($cachedFirstTime * 1000);
|
|
$cachedFirstTimePerOp = ($cachedFirstTimeMs / $iterations);
|
|
|
|
echo "3. Cached ReflectionProvider (first run - no cache):\n";
|
|
echo " Total: " . round($cachedFirstTimeMs, 2) . " ms\n";
|
|
echo " Per operation: " . round($cachedFirstTimePerOp, 4) . " ms\n";
|
|
echo " Per operation: " . round($cachedFirstTimePerOp * 1000, 2) . " microseconds\n\n";
|
|
|
|
// Test 4: Cached ReflectionProvider (cached - second run)
|
|
$start = microtime(true);
|
|
for ($i = 0; $i < $iterations; $i++) {
|
|
$class = $provider->getClass($classNameObj);
|
|
$methods = $provider->getMethods($classNameObj);
|
|
$params = $provider->getMethodParameters($classNameObj, '__construct');
|
|
}
|
|
$cachedSecondTime = microtime(true) - $start;
|
|
$cachedSecondTimeMs = ($cachedSecondTime * 1000);
|
|
$cachedSecondTimePerOp = ($cachedSecondTimeMs / $iterations);
|
|
|
|
echo "4. Cached ReflectionProvider (cached - second run):\n";
|
|
echo " Total: " . round($cachedSecondTimeMs, 2) . " ms\n";
|
|
echo " Per operation: " . round($cachedSecondTimePerOp, 4) . " ms\n";
|
|
echo " Per operation: " . round($cachedSecondTimePerOp * 1000, 2) . " microseconds\n\n";
|
|
|
|
// Comparison
|
|
echo "=== Comparison ===\n";
|
|
$speedup = $nativeTimePerOp / $cachedSecondTimePerOp;
|
|
echo "Speedup (cached vs native): " . round($speedup, 2) . "x\n";
|
|
echo "Overhead (cached first vs native): " . round(($cachedFirstTimePerOp / $nativeTimePerOp - 1) * 100, 1) . "%\n\n";
|
|
|
|
// Reality check: How many reflection calls per request?
|
|
echo "=== Reality Check ===\n";
|
|
echo "Typical request might call getMethodParameters() 10-50 times\n";
|
|
echo "Native: " . round($nativeMethodTimePerOp * 50, 2) . " ms for 50 calls\n";
|
|
echo "Cached: " . round($cachedSecondTimePerOp * 50, 2) . " ms for 50 calls\n";
|
|
echo "Difference: " . round(($nativeMethodTimePerOp - $cachedSecondTimePerOp) * 50, 2) . " ms\n";
|
|
echo "Is this significant? " . (($nativeMethodTimePerOp - $cachedSecondTimePerOp) * 50 > 1 ? "YES (>1ms)" : "NO (<1ms)") . "\n";
|
|
|