Completed
Push — master ( 51c1b8...0f6952 )
by Kacper
03:47
created

RunCommand::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 10
nc 1
nop 0
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Highlighter
4
 *
5
 * Copyright (C) 2016, Some right reserved.
6
 *
7
 * @author Kacper "Kadet" Donat <[email protected]>
8
 *
9
 * Contact with author:
10
 * Xmpp: [email protected]
11
 * E-mail: [email protected]
12
 *
13
 * From Kadet with love.
14
 */
15
16
namespace Kadet\Highlighter\bin\Commands\Benchmark;
17
18
19
use Kadet\Highlighter\Formatter\FormatterInterface;
20
use Kadet\Highlighter\KeyLighter;
21
use Kadet\Highlighter\Language\Language;
22
use Symfony\Component\Console\Command\Command;
23
use Symfony\Component\Console\Input\InputArgument;
24
use Symfony\Component\Console\Input\InputInterface;
25
use Symfony\Component\Console\Input\InputOption;
26
use Symfony\Component\Console\Output\OutputInterface;
27
28
class RunCommand extends Command
29
{
30
    const DIRECTORY = "../../../Tests/Samples/";
31
32
    protected function execute(InputInterface $input, OutputInterface $output)
33
    {
34
        $dir = __DIR__ . 'BenchmarkCommand.php/' .static::DIRECTORY;
35
        $iterator = new \RecursiveIteratorIterator(
36
            new \RecursiveDirectoryIterator(
37
                $dir,
38
                \RecursiveDirectoryIterator::SKIP_DOTS | \RecursiveDirectoryIterator::UNIX_PATHS
39
            ), \RecursiveIteratorIterator::LEAVES_ONLY
40
        );
41
42
        $formatter = $input->hasOption('formatter')
43
            ? KeyLighter::get()->getFormatter($input->getOption('formatter'))
44
            : KeyLighter::get()->getDefaultFormatter();
45
46
        $results = [];
47
48
        /** @var \SplFileInfo $file */
49
        foreach ($iterator as $file) {
50
            $shortname = substr($file->getPathname(), strlen($dir));
51
52
            if (!fnmatch($input->getOption('include'), $shortname)) {
53
                $output->writeln(sprintf('Skipping file <info>%s</info>', $shortname), OutputInterface::VERBOSITY_VERBOSE);
54
55
                continue;
56
            }
57
58
            $language = Language::byFilename($file->getFilename());
59
            $source = file_get_contents($file->getPathname());
60
61
            $output->writeln(sprintf(
62
                'File: <info>%s</info> Size: <info>%s</info> Language: <info>%s</info>',
63
                substr($file->getPathname(), strlen($dir)), $file->getSize(), get_class($language)
64
            ), OutputInterface::VERBOSITY_VERBOSE);
65
66
            // Dry run, to include all necessary files.
67
            $this->benchmark($source, $language, $formatter);
68
69
            $intermediate = [];
70
            for($i = $input->getOption('times'); $i > 0; $i--) {
71
                $intermediate = array_merge_recursive($intermediate, $this->benchmark($source, $language, $formatter));
72
73
                if($input->getOption('geshi') && class_exists('GeSHi')) {
74
                    $intermediate['geshi'][] = $this->geshi($source, $file->getExtension());
75
                }
76
            }
77
78
            $results[$shortname] = [
79
                'language' => get_class($language),
80
                'size' => $file->getSize(),
81
                'times' => $intermediate
82
            ];
83
        }
84
85
        $this->output([
86
            'formatter' => get_class($formatter),
87
            'timestamp' => time(),
88
            'system'    => php_uname(),
89
            'results'   => $results
90
        ], $input, $output);
91
    }
92
93
    protected function configure()
94
    {
95
        $this
96
            ->setName('benchmark:run')
97
            ->setDescription('Tests performance of KeyLighter')
98
            ->addOption('times', 't', InputOption::VALUE_OPTIONAL, 'How many times each test will be run', 50)
99
            ->addOption('include', 'i', InputOption::VALUE_OPTIONAL, 'File mask to include', '*')
100
            ->addOption('pretty', 'p', InputOption::VALUE_NONE, 'Pretty print')
101
            ->addOption('geshi', 'g', InputOption::VALUE_NONE, 'Include GeSHi for comparsion')
102
            ->addOption('formatter', 'f', InputOption::VALUE_OPTIONAL, 'Formatter used for benchmark')
103
            ->addArgument('output', InputArgument::OPTIONAL, 'Output file')
104
        ;
105
    }
106
107
    protected function benchmark($source, Language $language, FormatterInterface $formatter, $geshi = null)
0 ignored issues
show
Unused Code introduced by
The parameter $geshi is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
108
    {
109
        $tokenization = microtime(true);
110
        $tokens = $language->tokenize($source);
111
        $tokenization = microtime(true) - $tokenization;
112
113
        $parsing = microtime(true);
114
        $parsed = $language->parse($tokens);
115
        $parsing = microtime(true) - $parsing;
116
117
        $formatting = microtime(true);
118
        $formatter->format($parsed);
119
        $formatting = microtime(true) - $formatting;
120
121
        $overall = $tokenization + $parsing + $formatting;
122
        return compact('tokenization', 'parsing', 'formatting', 'overall');
123
    }
124
125
    protected function geshi($source, $language)
126
    {
127
        $geshi = microtime(true);
128
        geshi_highlight($source, $language, null, true);
129
        return microtime(true) - $geshi;
130
    }
131
132
    protected function output($results, InputInterface $input, OutputInterface $output)
133
    {
134
        $result = json_encode($results, $input->getOption('pretty') ? JSON_PRETTY_PRINT : 0);
135
136
        if($input->hasArgument('output')) {
137
            file_put_contents($input->getArgument('output'), $result);
138
        } else {
139
            $output->write($result);
140
        }
141
    }
142
}
143