本文目录导读:

在Symfony项目中,Stopwatch组件是一个非常强大的性能分析工具,我来详细说明它的使用方法和最佳实践。
基本使用
自动注入使用
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\Stopwatch\StopwatchEvent;
class ProductService
{
public function __construct(
private Stopwatch $stopwatch
) {}
public function processProducts(): void
{
// 开始计时
$this->stopwatch->start('product_processing');
// 业务逻辑
$products = $this->fetchProducts();
$this->processBatch($products);
$this->saveResults();
// 停止计时
$event = $this->stopwatch->stop('product_processing');
$this->logPerformance($event);
}
}
分段计时(Lap功能)
class DataPipeline
{
public function execute(): void
{
$stopwatch = new Stopwatch();
// 主事件
$stopwatch->openSection();
$stopwatch->start('pipeline', 'data_processing');
// 第一阶段
$stopwatch->lap('pipeline');
$this->extractData();
// 第二阶段
$stopwatch->lap('pipeline');
$this->transformData();
// 第三阶段
$stopwatch->lap('pipeline');
$this->loadData();
$event = $stopwatch->stop('pipeline');
$stopwatch->closeSection('pipeline_section');
}
}
多层嵌套计时
class ComplexOperation
{
public function execute(): void
{
$stopwatch = new Stopwatch(true); // true表示启用内存分析
// 外层计时
$stopwatch->start('main_operation');
// 内层计时1
$stopwatch->start('subtask_1');
$this->doTaskOne();
$stopwatch->stop('subtask_1');
// 内层计时2
$stopwatch->start('subtask_2');
$this->doTaskTwo();
$stopwatch->stop('subtask_2');
$event = $stopwatch->stop('main_operation');
// 分析结果
foreach ($event->getPeriods() as $period) {
printf("Duration: %.2f ms\n", $period->getDuration());
}
}
}
高级特性
事件分析
class PerformanceAnalyzer
{
private array $events = [];
public function analyzeEvent(StopwatchEvent $event): array
{
return [
'name' => $event->getName(),
'category' => $event->getCategory(),
'origin' => $event->getOrigin(),
'start_time' => $event->getStartTime(),
'end_time' => $event->getEndTime(),
'duration' => $event->getDuration(),
'memory' => $event->getMemory(),
// 详细分段信息
'periods' => array_map(function($period) {
return [
'start' => $period->getStartTime(),
'end' => $period->getEndTime(),
'duration' => $period->getDuration(),
'memory' => $period->getMemory()
];
}, $event->getPeriods())
];
}
}
自定义分类
class DatabasePerformance
{
public function trackQueries(): void
{
$stopwatch = new Stopwatch();
// 使用分类组织事件
$stopwatch->start('query_1', 'mysql');
$this->executeQuery1();
$stopwatch->stop('query_1');
$stopwatch->start('query_2', 'mysql');
$this->executeQuery2();
$stopwatch->stop('query_2');
$stopwatch->start('cache_lookup', 'redis');
$this->checkCache();
$stopwatch->stop('cache_lookup');
// 按分类获取结果
$mysqlEvents = $stopwatch->getSectionEvents('__root__');
}
}
最佳实践
日志记录集成
class PerformanceLogger
{
public function __construct(
private Stopwatch $stopwatch,
private LoggerInterface $logger
) {}
public function logPerformance(string $eventName): void
{
if ($this->stopwatch->isStarted($eventName)) {
$event = $this->stopwatch->stop($eventName);
$duration = $event->getDuration();
$memory = $event->getMemory() / 1024 / 1024; // MB
// 记录慢操作
if ($duration > 1000) { // 超过1秒
$this->logger->warning("Slow operation detected", [
'event' => $eventName,
'duration_ms' => $duration,
'memory_mb' => round($memory, 2),
'category' => $event->getCategory()
]);
}
// 记录所有操作
$this->logger->info("Performance metrics", [
'event' => $eventName,
'duration_ms' => $duration,
'memory_mb' => round($memory, 2)
]);
}
}
}
Profiler集成
#[AsEventListener]
class PerformanceListener
{
public function __construct(
private Stopwatch $stopwatch,
private Profiler $profiler
) {}
public function onKernelResponse(ResponseEvent $event): void
{
// 收集本请求的所有性能数据
$sections = $this->stopwatch->getSectionEvents('__root__');
foreach ($sections as $name => $sectionEvent) {
$profilerData = new PerformanceDataCollector();
$profilerData->addEvent($name, [
'duration' => $sectionEvent->getDuration(),
'memory' => $sectionEvent->getMemory()
]);
$this->profiler->add($profilerData);
}
}
}
配置优化
条件启用
// config/packages/framework.yaml
framework:
profiler:
only_exceptions: false
collect_serializer_data: true
// 服务配置
services:
App\Service\PerformanceMonitor:
arguments:
$enabled: '%kernel.debug%'
class PerformanceMonitor
{
private bool $enabled;
public function __construct(
private ?Stopwatch $stopwatch,
bool $enabled = false
) {
$this->enabled = $enabled && $stopwatch !== null;
}
public function start(string $name): void
{
if ($this->enabled) {
$this->stopwatch->start($name);
}
}
public function stop(string $name): ?StopwatchEvent
{
if ($this->enabled) {
return $this->stopwatch->stop($name);
}
return null;
}
}
性能分析和可视化
Web Profiler集成
class CustomCollector extends DataCollector
{
public function __construct(
private Stopwatch $stopwatch
) {}
public function collect(Request $request, Response $response, ?Throwable $exception = null): void
{
$sections = $this->stopwatch->getSectionEvents('__root__');
$this->data = [
'total_time' => $this->calculateTotalTime($sections),
'events' => $this->formatEvents($sections),
'memory_peak' => memory_get_peak_usage(true)
];
}
public function getTemplate(): string
{
return '@CustomProfiler/performance.html.twig';
}
}
注意事项
- 性能开销:Stopwatch本身有轻微性能开销,生产环境建议禁用
- 内存使用:大量计时事件会消耗内存,注意清理
- 并发安全:Stopwatch不是线程安全的,在多线程环境下需注意
- 嵌套限制:避免过多嵌套层级,建议不超过3层
- 命名规范:使用有意义的命名,便于分析
这种方式可以帮助你精确定位性能瓶颈,优化应用性能。