Test Failed
Push — master ( 2bc697...ec556c )
by Maciej
02:06
created

bin/Commands/Benchmark/RunCommand.php (1 issue)

parameters are used.

Unused Code Minor

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Highlighter
5
 *
6
 * Copyright (C) 2016, Some right reserved.
7
 *
8
 * @author Kacper "Kadet" Donat <[email protected]>
9
 *
10
 * Contact with author:
11
 * Xmpp: [email protected]
12
 * E-mail: [email protected]
13
 *
14
 * From Kadet with love.
15
 */
16
17
namespace Kadet\Highlighter\bin\Commands\Benchmark;
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\Helper\ProgressBar;
24
use Symfony\Component\Console\Input\InputArgument;
25
use Symfony\Component\Console\Input\InputInterface;
26
use Symfony\Component\Console\Input\InputOption;
27
use Symfony\Component\Console\Output\OutputInterface;
28
29
class RunCommand extends Command
30
{
31
    const DIRECTORY = "/../../../Tests/Samples/";
32
33
    protected function execute(InputInterface $input, OutputInterface $output)
34
    {
35
        $dir = __DIR__ . static::DIRECTORY;
36
        $iterator = new \RecursiveIteratorIterator(
37
            new \RecursiveDirectoryIterator(
38
                $dir,
39
                \RecursiveDirectoryIterator::SKIP_DOTS | \RecursiveDirectoryIterator::UNIX_PATHS
40
            ),
41
            \RecursiveIteratorIterator::LEAVES_ONLY
42
        );
43
44
        $formatter = $input->getOption('formatter')
45
            ? KeyLighter::get()->getFormatter($input->getOption('formatter'))
46
            : KeyLighter::get()->getDefaultFormatter();
47
48
        $results = [];
49
50
        /** @var \SplFileInfo $file */
51
        foreach ($iterator as $file) {
52
            $shortname = substr($file->getPathname(), strlen($dir));
53
54
            if (!fnmatch($input->getOption('include'), $shortname)) {
55
                $output->writeln(sprintf('Skipping file <info>%s</info>', $shortname), OutputInterface::VERBOSITY_VERBOSE);
56
57
                continue;
58
            }
59
60
            $language = Language::byFilename($file->getFilename());
61
            $source = file_get_contents($file->getPathname());
62
63
            $output->writeln(sprintf(
64
                'File: <info>%s</info> Size: <info>%s</info> Language: <info>%s</info>',
65
                substr($file->getPathname(), strlen($dir)),
66
                $file->getSize(),
67
                get_class($language)
68
            ), OutputInterface::VERBOSITY_VERBOSE);
69
70
            // Dry run, to include all necessary files.
71
            $this->benchmark($source, $language, $formatter);
72
73
            $times  = [];
74
            $memory = [];
75
76
            for ($i = $input->getOption('times'), $progress = new ProgressBar($output, $i); $i > 0; $i--) {
77
                $progress->display();
78
                $result = $this->benchmark($source, $language, $formatter);
79
                $times  = array_merge_recursive($times, $result['times']);
80
                $memory = array_merge_recursive($memory, $result['memory']);
81
82
                if ($input->getOption('geshi') && class_exists('GeSHi')) {
83
                    $times['geshi'][] = $this->geshi($source, $file->getExtension());
84
                }
85
86
                $progress->advance();
87
            }
88
            $output->write(PHP_EOL);
89
90
            $results[$shortname] = [
91
                'language' => get_class($language),
92
                'size'     => $file->getSize(),
93
                'times'    => $times,
94
                'memory'   => $memory
95
            ];
96
        }
97
98
        $this->output([
99
            'formatter' => get_class($formatter),
100
            'timestamp' => time(),
101
            'system'    => php_uname(),
102
            'comment'   => $input->getOption('comment'),
103
            'results'   => $results
104
        ], $input, $output);
105
    }
106
107
    protected function configure()
108
    {
109
        $this
110
            ->setName('benchmark:run')
111
            ->setDescription('Tests performance of KeyLighter')
112
            ->addOption('times', 't', InputOption::VALUE_OPTIONAL, 'How many times each test will be run', 50)
113
            ->addOption('include', 'i', InputOption::VALUE_OPTIONAL, 'File mask to include', '*')
114
            ->addOption('comment', 'm', InputOption::VALUE_OPTIONAL, 'Comment to include in file')
115
            ->addOption('pretty', 'p', InputOption::VALUE_NONE, 'Pretty print')
116
            ->addOption('geshi', 'g', InputOption::VALUE_NONE, 'Include GeSHi for comparsion')
117
            ->addOption('formatter', 'f', InputOption::VALUE_OPTIONAL, 'Formatter used for benchmark')
118
            ->addArgument('output', InputArgument::OPTIONAL, 'Output file')
119
        ;
120
    }
121
122
    protected function benchmark($source, Language $language, FormatterInterface $formatter, $geshi = null)
0 ignored issues
show
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...
123
    {
124
        gc_collect_cycles(); // force garbage collector
125
        $memory = $this->getMemory();
126
127
        $tokenization = $this->_benchmark(function () use ($language, $source) {
128
            return $language->tokenize($source);
129
        });
130
        $tokens = $tokenization['result'];
131
132
        $parsing = $this->_benchmark(function () use ($language, $tokens) {
133
            return $language->parse($tokens);
134
        });
135
        $parsed = $tokenization['result'];
136
137
        $formatting = $this->_benchmark(function () use ($formatter, $parsed) {
138
            return $formatter->format($parsed);
139
        });
140
141
        return [
142
            'times' => [
143
                'tokenization' => $tokenization['time'],
144
                'parsing'      => $parsing['time'],
145
                'formatting'   => $formatting['time'],
146
                'overall'      => $tokenization['time'] + $parsing['time'] + $formatting['time']
147
            ],
148
            'memory' => [
149
                'start' => $memory,
150
                'tokenization' => $tokenization['memory'],
151
                'parsing'      => $parsing['memory'],
152
                'formatting'   => $formatting['memory'],
153
                'overall' => $this->getMemory() - $memory,
154
                'end'   => $this->getMemory()
155
            ]
156
        ];
157
    }
158
159
    private function _benchmark(\Closure $function)
160
    {
161
        $memory = $this->getMemory();
162
        $time   = $this->getTime();
163
164
        $result = $function();
165
166
        return [
167
            'result' => $result,
168
            'time'   => $this->getTime() - $time,
169
            'memory' => $this->getMemory() - $memory,
170
        ];
171
    }
172
173
    protected function geshi($source, $language)
174
    {
175
        // Silence GeSHi notices
176
        $previousErrorReporting = error_reporting(E_ALL ^ E_NOTICE);
177
178
        $geshi = microtime(true);
179
        geshi_highlight($source, $language, null, true);
180
        $time = microtime(true) - $geshi;
181
182
        // Restore previous error reporting level
183
        error_reporting($previousErrorReporting);
184
185
        return $time;
186
    }
187
188
    protected function output($results, InputInterface $input, OutputInterface $output)
189
    {
190
        /**
191
         * @noinspection PhpComposerExtensionStubsInspection
192
         * Adding ext-json as dev-only dependency still doesn't
193
         * prevent this issue so we have to ignore this inspection
194
         */
195
        $result = json_encode($results, $input->getOption('pretty') ? JSON_PRETTY_PRINT : 0);
196
197
        if ($input->getArgument('output')) {
198
            file_put_contents($input->getArgument('output'), $result);
199
        } else {
200
            $output->write($result);
201
        }
202
    }
203
204
    protected function getMemory()
205
    {
206
        return memory_get_usage();
207
    }
208
209
    protected function getTime()
210
    {
211
        return microtime(true);
212
    }
213
}
214