Completed
Push — master ( 04cf1c...b0b733 )
by Kacper
03:57
created

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

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
 * 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\Helper\Table;
24
use Symfony\Component\Console\Helper\TableCell;
25
use Symfony\Component\Console\Helper\TableSeparator;
26
use Symfony\Component\Console\Input\InputArgument;
27
use Symfony\Component\Console\Input\InputInterface;
28
use Symfony\Component\Console\Input\InputOption;
29
use Symfony\Component\Console\Output\OutputInterface;
30
31
class AnalyzeCommand extends Command
32
{
33
    protected function execute(InputInterface $input, OutputInterface $output)
34
    {
35
        $json = json_decode(file_get_contents($input->getArgument('input')[0]), true);
36
37
        $output->writeln(sprintf(
38
            "Date: <info>%s</info> Formatter: <info>%s</info>, Comment: <info>%s</info>",
39
            date('d.m.Y H:i:s', $json['timestamp']), $json['formatter'], isset($json['comment']) ? $json['comment'] : 'none'
40
        ));
41
42
        $table = new Table($output);
43
44
        $suffix = $input->getOption('relative') ? 'bytes/s' : 'ms';
45
        $table->addRow(['set', "min [$suffix]", "avg [$suffix]", "max [$suffix]", "std dev [$suffix]"]);
46
47
        $summary = [];
48
        foreach ($json['results'] as $file => $data) {
49
            $this->separator($file, $table);
50
51
            foreach ($data['times'] as $set => $times) {
52
                $result = array_map(function ($time) use ($data, $input) {
53
                    return $input->getOption('relative') ? $data['size'] / $time : $time * 1000;
54
                }, $times);
55
56
                $this->entry($result, $set, $table);
57
58
                $summary[$set][] = array_sum($result) / count($result);
59
            }
60
61
            if (!isset($data['memory'])) {
62
                continue;
63
            }
64
65
            foreach ($data['memory'] as $set => $memory) {
66
                $result = array_map(function ($memory) use ($data, $input) {
67
                    $bytes = $input->getOption('relative') ? $memory/$data['size'] : $memory;
68
                    return $this->formatBytes($bytes, (bool)$input->getOption('relative'));
69
                }, $memory);
70
71
                $this->entry($result, $set, $table);
72
            }
73
        }
74
75
//        if(!$input->hasParameterOption('--summary')) {
76
            $table->render();
77
//        }
78
79
        $summary = array_filter($summary, function($key) use ($input) {
80
            return fnmatch($input->getOption('summary') ?: '*', $key);
81
        }, ARRAY_FILTER_USE_KEY);
82
83
        $max = max(array_map('strlen', array_keys($summary)));
84
        foreach($summary as $name => $set) {
85
            $output->writeln(sprintf(
86
                "<comment>%s</comment> %s %s",
87
                str_pad($name, $max, ' ', STR_PAD_LEFT),
88
                $this->format($input->getOption('relative') ? array_sum($set) / count($set) : array_sum($set)),
89
                $suffix
90
            ));
91
        }
92
    }
93
94
    protected function separator($file, Table $table)
95
    {
96
        $table->addRows([
97
            new TableSeparator(),
98
            [new TableCell($file, ['colspan' => 5])],
99
            new TableSeparator(),
100
        ]);
101
    }
102
103
    protected function entry($result, $set, Table $table)
104
    {
105
        $min = min($result);
106
        $avg = $this->avarage($result);
107
        $max = max($result);
108
        $dev = $this->stddev($result);
109
110
        $table->addRow([
111
            $set,
112
            $this->format($min),
113
            $this->format($avg),
114
            $this->format($max),
115
            sprintf("%s (%d%%)", $this->format($dev), $dev / $avg * 100),
116
        ]);
117
    }
118
119
    private function format($number)
120
    {
121
        return is_numeric($number) ? number_format($number, 2) : $number;
122
    }
123
124
    private function avarage(array $result)
125
    {
126
        return array_sum($result) / count($result);
127
    }
128
129
    private function stddev($result)
130
    {
131
        $mean = array_sum($result) / count($result);
132
133
        return sqrt(array_sum(array_map(function ($result) use ($mean) {
134
            return pow($result - $mean, 2);
135
        }, $result)) / count($result));
136
    }
137
138
    function formatBytes($bytes, $relative = false) {
0 ignored issues
show
The parameter $relative 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...
139
        $units = array('B', 'KB', 'MB', 'GB', 'TB');
140
141
        $bytes = max($bytes, 0);
142
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
143
        $pow = min($pow, count($units) - 1);
144
145
        $bytes /= (1 << (10 * $pow));
146
147
        return $this->format($bytes);//.$units[$pow].($relative ? '/byte' : '');
148
    }
149
150
    protected function configure()
151
    {
152
        $this
153
            ->setName('benchmark:analyze')
154
            ->setDescription('Tests performance of KeyLighter')
155
            ->addArgument('input', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Input JSON file(s)')
156
            ->addOption('relative', 'r', InputOption::VALUE_NONE, 'Show relative times?')
157
            ->addOption('summary', 'u', InputOption::VALUE_OPTIONAL, 'Show summary times?', '*');
158
    }
159
}
160