symfony

Track Memory Usage and Runtime of Symfony Commands

If you write lots of Console Commands in your Symfony application you sure want to know more about their memory and time consumption. To collect the necessary data you can make use of the Stopwatch Component:

use SymfonyComponentStopwatchStopwatch;

$stopwatch = Stopwatch();
$stopwatch->start('my event');
// do something important
$stopwatchEvent = $stopwatch->stop('my event');

echo $stopwatchEvent->getDuration();
echo $stopwatchEvent->getMemory();

First we need to define a service for our Stopwatch in our services.yml to have it available where we want it:

services:
    flagbit_core.stopwatch:
        class: SymfonyComponentStopwatchStopwatch

You could implement the Stopwatch in each and every command by hand but this is tiresome and error-prone. So we make use of the Console Events and attach to them:

    flagbit_core.console_stopwatch.command:
        class: FlagbitCoreBundleEventListenerConsoleStopwatchListener
        arguments: [ "@flagbit_core.stopwatch" ]
        tags:
            - { name: kernel.event_listener, event: console.command }

    flagbit_core.console_stopwatch.terminate:
        class: FlagbitCoreBundleEventListenerConsoleStopwatchListener
        arguments: [ "@flagbit_core.stopwatch" ]
        tags:
            - { name: kernel.event_listener, event: console.terminate }

Ok, let’s walk through the ConsoleStopwatchListener. First we start with the Constructor to inject the Stopwatch into our Service:

<?php

namespace QuantumCoreBundleEventListener;

use SymfonyComponentConsoleEventConsoleCommandEvent;
use SymfonyComponentConsoleEventConsoleTerminateEvent;
use SymfonyComponentConsoleOutputOutputInterface;
use SymfonyComponentStopwatchStopwatch;

class ConsoleStopwatchListener
{
    /**
     * @var Stopwatch
     */
    private $stopwatch;

    /**
     * @param Stopwatch $stopwatch
     */
    public function __construct(Stopwatch $stopwatch)
    {
        $this->stopwatch = $stopwatch;
    }

The console.command Event is dispatched just before command execution. So it is the perfect place to start our Stopwatch:

    /**
     * @param ConsoleCommandEvent $event
     */
    public function onConsoleCommand(ConsoleCommandEvent $event)
    {
        $this->stopwatch->start($event->getCommand()->getName());
    }

The second Event we attached to is console.terminate which is triggered after the command has been executed. So we attach our stats to the Output there:

    /**
     * @param ConsoleTerminateEvent $event
     */
    public function onConsoleTerminate(ConsoleTerminateEvent $event)
    {
        $stopwatchEvent = $this->stopwatch->stop($event->getCommand()->getName());

        $output = $event->getOutput();
        if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
            $output->writeln(
                '' . $this->formatDuration($stopwatchEvent->getDuration()) . ' / '
                . $this->formatMemory($stopwatchEvent->getMemory()) . ''
            );
        }
    }

    /**
     * @param int $bytes Memory in bytes
     * @return string
     */
    private function formatMemory($bytes)
    {
        return round($bytes / 1000 / 1000, 2) . ' MB';
    }

    /**
     * @param int $microseconds Time in microseconds
     * @return string
     */
    private function formatDuration($microseconds)
    {
        return $microseconds / 1000 . ' s';
    }
}

You might also have noticed the Verbosity check which causes our stats only to be printed if the command is run with -v. Symfony >= 2.4 allows to do this a little bit cleaner with $output->isVerbose().

Hinterlasse einen Kommentar

1 Kommentar auf "Track Memory Usage and Runtime of Symfony Commands"

Benachrichtige mich zu:
avatar

Sortiert nach:   neuste | älteste | beste Bewertung
Claudio Zizza
Gast
Claudio Zizza
4 Jahre 4 Monate her

In Addition to David’s Blog Post:
Stopwatch is a debugging tool that has already an own service called debug.stopwatch. Since Stopwatch is meant to be debug only a new service like flagbit_core.stopwatch was created for usage on a production system.

wpDiscuz
Weitere Beiträge zum Thema
CObject im Backend
Modul für Gutscheinconnection veröffentlicht
Icon für verschiedene Zustände der Extension-Records (z.B. versteckt / hidden)
Visualisierung von Logdaten