Completed
Push — develop ( 35365a...6b618f )
by Alec
03:18
created

Benchmark::compare()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 0
dl 0
loc 14
ccs 10
cts 10
cp 1
crap 3
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/**
3
 * User: alec
4
 * Date: 29.11.18
5
 * Time: 11:04
6
 */
7
8
namespace AlecRabbit\Tools;
9
10
use AlecRabbit\Rewindable;
11
use AlecRabbit\Tools\Contracts\BenchmarkInterface;
12
use AlecRabbit\Tools\Internal\BenchmarkedFunction;
13
use AlecRabbit\Tools\Reports\Contracts\ReportableInterface;
14
use AlecRabbit\Tools\Reports\Traits\Reportable;
15
use AlecRabbit\Tools\Traits\BenchmarkFields;
16
use function AlecRabbit\typeOf;
17
18
class Benchmark implements BenchmarkInterface, ReportableInterface
19
{
20
    use BenchmarkFields, Reportable;
21
22
    /** @var int */
23
    private $namingIndex = 0;
24
    /** @var Rewindable */
25
    private $iterations; // todo rename field
26
    /** @var null|string */
27
    private $comment;
28
29 3
    public function __construct(int $iterations = 1000)
30
    {
31 3
        $this->iterations =
32 3
            new Rewindable(
33
                function (int $iterations, int $i = 1): \Generator {
34 1
                    while ($i <= $iterations) {
35 1
                        yield $i++;
36
                    }
37 3
                },
38 3
                $iterations
39
            );
40 3
        $this->profiler = new Profiler();
41 3
    }
42
43
    /**
44
     * Launch benchmarking
45
     */
46 1
    public function compare(): void
47
    {
48
        /** @var  BenchmarkedFunction $f */
49 1
        foreach ($this->functions as $name => $f) {
50 1
            $this->profiler->timer($name)->start();
51 1
            $function = $f->getFunction();
52 1
            $args = $f->getArgs();
53 1
            $this->iteration = 0;
54 1
            foreach ($this->iterations as $iteration) {
55
                /** @noinspection VariableFunctionsUsageInspection */
56
                /** @noinspection DisconnectedForeachInstructionInspection */
57 1
                \call_user_func($function, ...$args);
58 1
                $this->profiler->timer($name)->check($iteration);
59 1
                ++$this->iteration;
60
            }
61
        }
62 1
    }
63
64
    /**
65
     * @param callable $func
66
     * @param mixed ...$args
67
     */
68 2
    public function addFunction($func, ...$args): void
69
    {
70 2
        if (!\is_callable($func, false, $name)) {
71 1
            throw new \InvalidArgumentException(
72 1
                sprintf(
73 1
                    '\'%s\' is NOT callable. Function must be callable. Type of "%s" provided instead.',
74 1
                    $name,
75 1
                    typeOf($func)
76
                )
77
            );
78
        }
79 1
        $function = new BenchmarkedFunction($func, $name, $this->namingIndex++, $args, $this->comment);
80 1
        $this->comment = null;
81
82 1
        $this->functions[$function->getEnumeratedName()] = $function;
83 1
    }
84
85
    /**
86
     * @param string $name
87
     * @return Benchmark
88
     */
89 2
    public function withComment(string $name): self
90
    {
91 2
        $this->comment = $name;
92 2
        return $this;
93
    }
94
95 2
    protected function prepareForReport(): void
96
    {
97 2
        $this->getProfiler()->report();
98 2
    }
99
}
100