- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
390 lines
10 KiB
PHP
390 lines
10 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Performance Profiling Usage Examples
|
|
*
|
|
* Dieses Script demonstriert die Verwendung des NestedPerformanceTracker
|
|
* für Flamegraph-Visualisierung und Timeline-Analyse.
|
|
*
|
|
* Ausführung: php examples/performance-profiling-usage.php
|
|
*/
|
|
|
|
require_once __DIR__ . '/../vendor/autoload.php';
|
|
|
|
use App\Framework\Performance\NestedPerformanceTracker;
|
|
use App\Framework\Performance\PerformanceCategory;
|
|
use App\Framework\DateTime\SystemClock;
|
|
use App\Framework\DateTime\SystemHighResolutionClock;
|
|
use App\Framework\Performance\MemoryMonitor;
|
|
|
|
// Tracker initialisieren
|
|
$tracker = new NestedPerformanceTracker(
|
|
new SystemClock(),
|
|
new SystemHighResolutionClock(),
|
|
new MemoryMonitor()
|
|
);
|
|
|
|
echo "=== Performance Profiling Examples ===\n\n";
|
|
|
|
// Example 1: Einfache verschachtelte Operationen
|
|
echo "Example 1: Nested Operations\n";
|
|
echo str_repeat('-', 50) . "\n";
|
|
|
|
$tracker->measure(
|
|
'http.request',
|
|
PerformanceCategory::CONTROLLER,
|
|
function () use ($tracker) {
|
|
usleep(5000); // 5ms Controller-Logik
|
|
|
|
// Database Query
|
|
$tracker->measure(
|
|
'database.query',
|
|
PerformanceCategory::DATABASE,
|
|
function () {
|
|
usleep(10000); // 10ms Query
|
|
return ['users' => 100];
|
|
}
|
|
);
|
|
|
|
// Cache Operation
|
|
$tracker->measure(
|
|
'cache.get',
|
|
PerformanceCategory::CACHE,
|
|
function () {
|
|
usleep(2000); // 2ms Cache
|
|
return ['cached' => true];
|
|
}
|
|
);
|
|
|
|
// Template Rendering
|
|
$tracker->measure(
|
|
'template.render',
|
|
PerformanceCategory::VIEW,
|
|
function () use ($tracker) {
|
|
usleep(3000); // 3ms Template
|
|
|
|
// Nested: Asset Loading
|
|
$tracker->measure(
|
|
'assets.load',
|
|
PerformanceCategory::FILESYSTEM,
|
|
function () {
|
|
usleep(1000); // 1ms Assets
|
|
}
|
|
);
|
|
}
|
|
);
|
|
|
|
return ['status' => 'success'];
|
|
}
|
|
);
|
|
|
|
// Flamegraph generieren
|
|
echo "\nFlamegraph Data:\n";
|
|
$flamegraph = $tracker->generateFlamegraph();
|
|
|
|
foreach ($flamegraph as $entry) {
|
|
echo sprintf(
|
|
" %s → %.2f samples\n",
|
|
$entry['stack_trace'],
|
|
$entry['samples']
|
|
);
|
|
}
|
|
|
|
// Timeline generieren
|
|
echo "\nTimeline Events:\n";
|
|
$timeline = $tracker->generateTimeline();
|
|
|
|
foreach ($timeline as $event) {
|
|
$indent = str_repeat(' ', $event['depth']);
|
|
echo sprintf(
|
|
" %s[%s] %s (%.2fms self, %.2fms total, %.2fMB memory)\n",
|
|
$indent,
|
|
$event['category'],
|
|
$event['name'],
|
|
$event['self_time_ms'],
|
|
$event['duration_ms'],
|
|
$event['memory_delta_mb']
|
|
);
|
|
}
|
|
|
|
// Summary
|
|
echo "\nPerformance Summary:\n";
|
|
$summary = $tracker->getSummary();
|
|
foreach ($summary as $key => $value) {
|
|
echo sprintf(" %s: %s\n", $key, is_float($value) ? number_format($value, 2) : $value);
|
|
}
|
|
|
|
echo "\n" . str_repeat('=', 50) . "\n\n";
|
|
|
|
// Example 2: Flamegraph Export für Visualisierung
|
|
echo "Example 2: Flamegraph Export (Brendan Gregg Format)\n";
|
|
echo str_repeat('-', 50) . "\n";
|
|
|
|
$tracker->reset(); // Reset für neues Beispiel
|
|
|
|
// Komplexere Operation
|
|
$tracker->measure(
|
|
'api.request',
|
|
PerformanceCategory::API,
|
|
function () use ($tracker) {
|
|
usleep(2000);
|
|
|
|
// Service Layer
|
|
$tracker->measure(
|
|
'service.process',
|
|
PerformanceCategory::CUSTOM,
|
|
function () use ($tracker) {
|
|
usleep(5000);
|
|
|
|
// Repository
|
|
$tracker->measure(
|
|
'repository.find',
|
|
PerformanceCategory::DATABASE,
|
|
function () {
|
|
usleep(8000);
|
|
}
|
|
);
|
|
|
|
// Cache
|
|
$tracker->measure(
|
|
'cache.set',
|
|
PerformanceCategory::CACHE,
|
|
function () {
|
|
usleep(3000);
|
|
}
|
|
);
|
|
}
|
|
);
|
|
|
|
// Response Transformation
|
|
$tracker->measure(
|
|
'transformer.transform',
|
|
PerformanceCategory::CUSTOM,
|
|
function () {
|
|
usleep(4000);
|
|
}
|
|
);
|
|
}
|
|
);
|
|
|
|
$flamegraphData = $tracker->generateFlamegraph();
|
|
|
|
echo "\nFlamegraph Format für flamegraph.pl:\n";
|
|
echo "----------------------------------------\n";
|
|
|
|
foreach ($flamegraphData as $entry) {
|
|
echo sprintf(
|
|
"%s %d\n",
|
|
$entry['stack_trace'],
|
|
(int) ceil($entry['samples'])
|
|
);
|
|
}
|
|
|
|
// In Datei schreiben für flamegraph.pl Tool
|
|
$flamegraphFile = __DIR__ . '/../tests/tmp/flamegraph.txt';
|
|
@mkdir(dirname($flamegraphFile), 0755, true);
|
|
|
|
$output = [];
|
|
foreach ($flamegraphData as $entry) {
|
|
$output[] = sprintf(
|
|
"%s %d",
|
|
$entry['stack_trace'],
|
|
(int) ceil($entry['samples'])
|
|
);
|
|
}
|
|
|
|
file_put_contents($flamegraphFile, implode("\n", $output));
|
|
echo "\nFlamegraph data saved to: {$flamegraphFile}\n";
|
|
echo "Generate SVG: flamegraph.pl {$flamegraphFile} > flamegraph.svg\n";
|
|
|
|
echo "\n" . str_repeat('=', 50) . "\n\n";
|
|
|
|
// Example 3: Chrome DevTools Timeline Export
|
|
echo "Example 3: Chrome DevTools Timeline Export\n";
|
|
echo str_repeat('-', 50) . "\n";
|
|
|
|
$timeline = $tracker->generateTimeline();
|
|
|
|
// In Chrome Trace Event Format konvertieren
|
|
$traceEvents = [];
|
|
|
|
foreach ($timeline as $event) {
|
|
// Begin Event
|
|
$traceEvents[] = [
|
|
'name' => $event['name'],
|
|
'cat' => $event['category'],
|
|
'ph' => 'B', // Begin
|
|
'ts' => (int)($event['start_time'] * 1_000_000), // Microseconds
|
|
'pid' => 1,
|
|
'tid' => 1,
|
|
'args' => $event['context']
|
|
];
|
|
|
|
// End Event
|
|
$traceEvents[] = [
|
|
'name' => $event['name'],
|
|
'cat' => $event['category'],
|
|
'ph' => 'E', // End
|
|
'ts' => (int)($event['end_time'] * 1_000_000),
|
|
'pid' => 1,
|
|
'tid' => 1
|
|
];
|
|
}
|
|
|
|
$chromeTrace = [
|
|
'traceEvents' => $traceEvents,
|
|
'displayTimeUnit' => 'ms',
|
|
'otherData' => [
|
|
'version' => '1.0',
|
|
'framework' => 'Custom PHP Framework'
|
|
]
|
|
];
|
|
|
|
$chromeTraceFile = __DIR__ . '/../tests/tmp/chrome-trace.json';
|
|
file_put_contents($chromeTraceFile, json_encode($chromeTrace, JSON_PRETTY_PRINT));
|
|
|
|
echo "\nChrome Trace saved to: {$chromeTraceFile}\n";
|
|
echo "Open in Chrome: chrome://tracing → Load → {$chromeTraceFile}\n";
|
|
|
|
echo "\n" . str_repeat('=', 50) . "\n\n";
|
|
|
|
// Example 4: Performance Budget Validation
|
|
echo "Example 4: Performance Budget Validation\n";
|
|
echo str_repeat('-', 50) . "\n";
|
|
|
|
$budgets = [
|
|
'database.query' => 5, // max 5ms
|
|
'cache.get' => 1, // max 1ms
|
|
'api.request' => 20, // max 20ms
|
|
];
|
|
|
|
$violations = [];
|
|
|
|
foreach ($timeline as $event) {
|
|
// Check ob Operation ein Budget hat
|
|
foreach ($budgets as $operation => $budget) {
|
|
if (str_contains($event['name'], $operation)) {
|
|
if ($event['duration_ms'] > $budget) {
|
|
$violations[] = [
|
|
'operation' => $event['name'],
|
|
'duration' => $event['duration_ms'],
|
|
'budget' => $budget,
|
|
'exceeded_by' => $event['duration_ms'] - $budget,
|
|
'exceeded_percentage' => (($event['duration_ms'] - $budget) / $budget) * 100
|
|
];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($violations)) {
|
|
echo "\n⚠️ Performance Budget Violations:\n";
|
|
foreach ($violations as $violation) {
|
|
echo sprintf(
|
|
" • %s: %.2fms (budget: %.2fms, exceeded by %.2fms / %.1f%%)\n",
|
|
$violation['operation'],
|
|
$violation['duration'],
|
|
$violation['budget'],
|
|
$violation['exceeded_by'],
|
|
$violation['exceeded_percentage']
|
|
);
|
|
}
|
|
} else {
|
|
echo "\n✅ All operations within performance budget!\n";
|
|
}
|
|
|
|
echo "\n" . str_repeat('=', 50) . "\n\n";
|
|
|
|
// Example 5: Bottleneck Detection
|
|
echo "Example 5: Automatic Bottleneck Detection\n";
|
|
echo str_repeat('-', 50) . "\n";
|
|
|
|
// Sortiere nach self_time_ms (Zeit ohne Children)
|
|
$timelineCopy = $timeline;
|
|
usort($timelineCopy, fn($a, $b) => $b['self_time_ms'] <=> $a['self_time_ms']);
|
|
|
|
// Top 3 Bottlenecks
|
|
$bottlenecks = array_slice($timelineCopy, 0, 3);
|
|
|
|
echo "\nTop 3 Performance Bottlenecks (by self-time):\n";
|
|
|
|
foreach ($bottlenecks as $index => $bottleneck) {
|
|
$percentage = ($bottleneck['self_time_ms'] / $bottleneck['duration_ms']) * 100;
|
|
|
|
echo sprintf(
|
|
" %d. %s [%s]\n" .
|
|
" Self Time: %.2fms (%.1f%% of total %.2fms)\n" .
|
|
" Memory: %.2fMB\n" .
|
|
" Depth: %d\n",
|
|
$index + 1,
|
|
$bottleneck['name'],
|
|
$bottleneck['category'],
|
|
$bottleneck['self_time_ms'],
|
|
$percentage,
|
|
$bottleneck['duration_ms'],
|
|
$bottleneck['memory_delta_mb'],
|
|
$bottleneck['depth']
|
|
);
|
|
}
|
|
|
|
echo "\n" . str_repeat('=', 50) . "\n\n";
|
|
|
|
// Example 6: Memory Usage Analysis
|
|
echo "Example 6: Memory Usage Analysis\n";
|
|
echo str_repeat('-', 50) . "\n";
|
|
|
|
$totalMemory = 0;
|
|
$memoryByCategory = [];
|
|
|
|
foreach ($timeline as $event) {
|
|
$totalMemory += $event['memory_delta_mb'];
|
|
|
|
$category = $event['category'];
|
|
if (!isset($memoryByCategory[$category])) {
|
|
$memoryByCategory[$category] = 0;
|
|
}
|
|
$memoryByCategory[$category] += $event['memory_delta_mb'];
|
|
}
|
|
|
|
echo sprintf("\nTotal Memory Delta: %.2fMB\n", $totalMemory);
|
|
echo "\nMemory Usage by Category:\n";
|
|
|
|
arsort($memoryByCategory);
|
|
foreach ($memoryByCategory as $category => $memory) {
|
|
$percentage = ($memory / max($totalMemory, 0.001)) * 100;
|
|
echo sprintf(
|
|
" • %s: %.2fMB (%.1f%%)\n",
|
|
$category,
|
|
$memory,
|
|
$percentage
|
|
);
|
|
}
|
|
|
|
// High memory operations
|
|
$highMemoryOps = array_filter($timeline, fn($e) => $e['memory_delta_mb'] > 0.5);
|
|
|
|
if (!empty($highMemoryOps)) {
|
|
echo "\n⚠️ High Memory Operations (>0.5MB):\n";
|
|
foreach ($highMemoryOps as $op) {
|
|
echo sprintf(
|
|
" • %s: %.2fMB\n",
|
|
$op['name'],
|
|
$op['memory_delta_mb']
|
|
);
|
|
}
|
|
}
|
|
|
|
echo "\n" . str_repeat('=', 50) . "\n\n";
|
|
|
|
echo "✅ Performance Profiling Examples completed!\n\n";
|
|
echo "Generated Files:\n";
|
|
echo " • {$flamegraphFile}\n";
|
|
echo " • {$chromeTraceFile}\n\n";
|
|
|
|
echo "Next Steps:\n";
|
|
echo " 1. Generate SVG: flamegraph.pl {$flamegraphFile} > flamegraph.svg\n";
|
|
echo " 2. View in Chrome: chrome://tracing → Load {$chromeTraceFile}\n";
|
|
echo " 3. Integrate into API endpoints for production monitoring\n\n";
|