Skip to content

Commit

Permalink
Performance metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
KennedyTedesco committed Dec 15, 2024
1 parent dc70d4d commit b654872
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 58 deletions.
3 changes: 0 additions & 3 deletions monkey
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,15 @@ try {

$outputFormatter = new OutputFormatter($output);
$inputReader = new InputReader($input, $output, $questionHelper);
$performanceTracker = new PerformanceTracker();

$replManager = new ReplManager(
inputReader: $inputReader,
outputFormatter: $outputFormatter,
performanceTracker: $performanceTracker
);

$commandFactory = new CommandFactory(
replManager: $replManager,
outputFormatter: $outputFormatter,
performanceTracker: $performanceTracker
);

$configManager = new ConfigurationManager();
Expand Down
4 changes: 1 addition & 3 deletions src/Monkey/Command/CommandFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace MonkeyLang\Monkey\Command;

use MonkeyLang\Monkey\IO\OutputFormatter;
use MonkeyLang\Monkey\Performance\PerformanceTracker;
use MonkeyLang\Monkey\Repl\ReplManager;
use RuntimeException;

Expand All @@ -17,7 +16,6 @@ final class CommandFactory
public function __construct(
private readonly ReplManager $replManager,
private readonly OutputFormatter $outputFormatter,
private readonly PerformanceTracker $performanceTracker,
) {
$this->registerCommands();
}
Expand All @@ -35,7 +33,7 @@ private function registerCommands(): void
{
$this->commands = [
'repl' => new ReplCommand($this->replManager),
'run' => new RunFileCommand($this->outputFormatter, $this->performanceTracker),
'run' => new RunFileCommand($this->outputFormatter),
'help' => new HelpCommand($this->outputFormatter),
'version' => new VersionCommand($this->outputFormatter),
];
Expand Down
62 changes: 39 additions & 23 deletions src/Monkey/Command/RunFileCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use MonkeyLang\Lang\Evaluator\Environment;
use MonkeyLang\Lang\Evaluator\Evaluator;
use MonkeyLang\Lang\Lexer\Lexer;
use MonkeyLang\Lang\Object\MonkeyObject;
use MonkeyLang\Lang\Parser\Parser;
use MonkeyLang\Lang\Parser\ProgramParser;
use MonkeyLang\Monkey\Config\Configuration;
Expand All @@ -20,7 +19,6 @@
{
public function __construct(
private OutputFormatter $outputFormatter,
private PerformanceTracker $performanceTracker,
) {
}

Expand All @@ -42,17 +40,52 @@ public function execute(Configuration $config): int
throw new RuntimeException("Could not read file: {$filename}");
}

$lexer = new Lexer($contents);
$parser = new Parser($lexer);

if ($parser->errors() !== []) {
throw new RuntimeException(
"Parser errors:\n" . implode("\n", $parser->errors()),
);
}

$parserPerformanceMetrics = null;
$parserPerformanceTracker = null;

if ($config->hasStats()) {
$parserPerformanceTracker = new PerformanceTracker('Parser');
$parserPerformanceTracker->start();
}

$program = new ProgramParser()($parser);

if ($config->hasStats()) {
$parserPerformanceMetrics = $parserPerformanceTracker->stop();
}

$evaluatorPerformanceMetrics = null;
$evaluatorPerformanceTracker = null;

if ($config->hasStats()) {
$this->performanceTracker->start();
$evaluatorPerformanceTracker = new PerformanceTracker('Evaluator');
$evaluatorPerformanceTracker->start();
}

try {
$result = $this->evaluateCode($contents);
$evaluator = new Evaluator();
$result = $evaluator->eval($program, new Environment());

if ($config->hasStats()) {
$evaluatorPerformanceMetrics = $evaluatorPerformanceTracker->stop();
}

$this->outputFormatter->writeOutput($result, $config->hasDebug());
$this->outputFormatter->write('');
$this->outputFormatter->write('');

if ($config->hasStats()) {
$metrics = $this->performanceTracker->stop();
$this->outputFormatter->writePerformanceStats($metrics);
$this->outputFormatter->writePerformanceStats($parserPerformanceMetrics);
$this->outputFormatter->writePerformanceStats($evaluatorPerformanceMetrics);
}

return 0;
Expand All @@ -62,21 +95,4 @@ public function execute(Configuration $config): int
return 1;
}
}

private function evaluateCode(string $contents): MonkeyObject
{
$lexer = new Lexer($contents);
$parser = new Parser($lexer);

if ($parser->errors() !== []) {
throw new RuntimeException(
"Parser errors:\n" . implode("\n", $parser->errors()),
);
}

$program = new ProgramParser()($parser);
$evaluator = new Evaluator();

return $evaluator->eval($program, new Environment());
}
}
15 changes: 3 additions & 12 deletions src/Monkey/IO/OutputFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public function __construct(

public function writeOutput(MonkeyObject $result, bool $debug = false): void
{
// Skip output for NullObject unless in debug mode
if ($result instanceof NullObject && !$debug) {
return;
}
Expand All @@ -49,16 +48,12 @@ public function write(string $message): void

public function writePerformanceStats(PerformanceMetrics $metrics): void
{
$this->output->writeln('');
$this->output->writeln('');
$this->output->writeln('<title>Performance Statistics</title>');

$this->output->writeln("<title>{$metrics->title} Performance Statistics</title>");
$table = new Table($this->output);

$table->setRows([
['Memory used', "<memory>{$this->formatBytes($metrics->memoryUsed)}</memory>"],
['Peak memory', "<peak>{$this->formatBytes($metrics->peakMemory)}</peak>"],
['Time taken', '<time>' . number_format($metrics->timeElapsed, 6) . ' seconds</time>'],
['Memory used', "\033[32m" . $this->formatBytes($metrics->memoryUsed) . "\033[0m"],
['Time taken', "\033[34m" . number_format($metrics->timeElapsed, 6) . " seconds\033[0m"],
]);

$table->render();
Expand All @@ -76,10 +71,6 @@ private function configureStyles(): void
'memory',
new OutputFormatterStyle('green'),
);
$this->output->getFormatter()->setStyle(
'peak',
new OutputFormatterStyle('yellow'),
);
$this->output->getFormatter()->setStyle(
'time',
new OutputFormatterStyle('blue'),
Expand Down
2 changes: 1 addition & 1 deletion src/Monkey/Performance/PerformanceMetrics.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
final readonly class PerformanceMetrics
{
public function __construct(
public string $title,
public float $timeElapsed,
public int $memoryUsed,
public int $peakMemory,
) {
}
}
12 changes: 11 additions & 1 deletion src/Monkey/Performance/PerformanceTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ final class PerformanceTracker

private ?int $startMemory = null;

public function __construct(
private readonly string $title,
) {
}

public static function new(string $title): self
{
return new self($title);
}

public function start(): void
{
$this->startTime = microtime(true);
Expand All @@ -25,9 +35,9 @@ public function stop(): PerformanceMetrics
}

$metrics = new PerformanceMetrics(
title: $this->title,
timeElapsed: microtime(true) - $this->startTime,
memoryUsed: memory_get_usage() - $this->startMemory,
peakMemory: memory_get_peak_usage(true),
);

$this->startTime = null;
Expand Down
28 changes: 13 additions & 15 deletions src/Monkey/Repl/ReplManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ final class ReplManager
public function __construct(
private readonly InputReader $inputReader,
private readonly OutputFormatter $outputFormatter,
private readonly PerformanceTracker $performanceTracker,
private Environment $environment = new Environment() {
get {
return $this->environment;
Expand Down Expand Up @@ -70,7 +69,9 @@ public function start(Configuration $config): int
}

try {
$this->evaluateAndOutput($input, $config);
$result = $this->evaluate($input, $config);

$this->outputFormatter->writeOutput($result, $this->debugMode);
} catch (MonkeyRuntimeException $e) {
$this->outputFormatter->writeError($e->getMessage());
} catch (Throwable $e) {
Expand All @@ -94,23 +95,15 @@ public function start(Configuration $config): int
}
}

private function evaluateAndOutput(string $input, Configuration $config): void
private function evaluate(string $input, Configuration $config): MonkeyObject
{
if ($config->hasStats()) {
$this->performanceTracker->start();
}

$result = $this->evaluate($input);
$this->outputFormatter->writeOutput($result, $this->debugMode);
$parserPerformanceTracker = null;

if ($config->hasStats()) {
$metrics = $this->performanceTracker->stop();
$this->outputFormatter->writePerformanceStats($metrics);
$parserPerformanceTracker = new PerformanceTracker('Parser');
$parserPerformanceTracker->start();
}
}

private function evaluate(string $input): MonkeyObject
{

$lexer = new Lexer($input);
$parser = new Parser($lexer);

Expand All @@ -124,6 +117,11 @@ private function evaluate(string $input): MonkeyObject

$program = new ProgramParser()($parser);

if ($config->hasStats()) {
$metrics = $parserPerformanceTracker->stop();
$this->outputFormatter->writePerformanceStats($metrics);
}

return $this->evaluator->eval($program, $this->environment);
}

Expand Down

0 comments on commit b654872

Please sign in to comment.