Skip to content

Commit e6967ce

Browse files
Merge pull request #108
Refactor `DeviationService`
2 parents 70b4f5a + 51b010c commit e6967ce

1 file changed

Lines changed: 49 additions & 52 deletions

File tree

src/Services/DeviationService.php

Lines changed: 49 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515

1616
class DeviationService
1717
{
18+
protected const MetricKeys = ['min', 'max', 'avg', 'total'];
19+
protected const TimeIndex = 0;
20+
protected const MemoryIndex = 1;
21+
1822
public function __construct(
1923
protected ResultService $result = new ResultService,
2024
) {}
@@ -23,39 +27,29 @@ public function __construct(
2327
* Calculates final results with deviations based on multiple runs.
2428
*
2529
* @param array<int, array<int|string, ResultData>> $collection A collection of results from multiple runs.
30+
*
2631
* @return array<int|string, ResultData>
2732
*/
2833
public function calculate(array $collection): array
2934
{
30-
return $this->map(
31-
$this->flatten($collection)
32-
);
33-
}
35+
$grouped = $this->group($collection);
3436

35-
/**
36-
* Transforms grouped data into an array of ResultData.
37-
*
38-
* @param array $collection Grouped measurement data.
39-
* @return array<int|string, ResultData>
40-
*/
41-
protected function map(array $collection): array
42-
{
43-
return array_map(fn (array $item): ResultData => $this->make($item), $collection);
37+
return array_map(fn (array $item): ResultData => $this->buildResultData($item), $grouped);
4438
}
4539

4640
/**
4741
* Creates a ResultData object with metrics and deviations from grouped data.
4842
*
4943
* @param array $item Grouped data for a single callback.
5044
*/
51-
protected function make(array $item): ResultData
45+
protected function buildResultData(array $item): ResultData
5246
{
5347
return new ResultData(
54-
min : $this->metric($item, 'min'),
55-
max : $this->metric($item, 'max'),
56-
avg : $this->metric($item, 'avg'),
57-
total : $this->metric($item, 'total'),
58-
deviation: $this->deviationMetric($item),
48+
min : $this->buildMetric($item, 'min'),
49+
max : $this->buildMetric($item, 'max'),
50+
avg : $this->buildMetric($item, 'avg'),
51+
total : $this->buildMetric($item, 'total'),
52+
deviation: $this->buildDeviation($item),
5953
);
6054
}
6155

@@ -65,60 +59,63 @@ protected function make(array $item): ResultData
6559
* @param array $item Grouped data for a single callback.
6660
* @param string $key The metric key (min, max, avg, total).
6761
*/
68-
protected function metric(array $item, string $key): MetricData
62+
protected function buildMetric(array $item, string $key): MetricData
6963
{
7064
return $this->result->$key(
71-
$this->result->values($item[$key], 0, false),
72-
$this->result->values($item[$key], 1, false),
65+
$this->extract($item[$key], self::TimeIndex),
66+
$this->extract($item[$key], self::MemoryIndex),
7367
);
7468
}
7569

70+
/**
71+
* Extracts time or memory values from grouped metric data.
72+
*
73+
* @param array $data Grouped metric entries.
74+
* @param int $index The index to extract (TIME_INDEX or MEMORY_INDEX).
75+
*
76+
* @return array<float>
77+
*/
78+
protected function extract(array $data, int $index): array
79+
{
80+
return $this->result->values($data, $index, false);
81+
}
82+
7683
/**
7784
* Calculates deviation data based on average values.
7885
*
7986
* @param array $item Grouped data for a single callback.
8087
*/
81-
protected function deviationMetric(array $item): DeviationData
88+
protected function buildDeviation(array $item): DeviationData
8289
{
83-
$time = $this->result->values($item['avg'], 0, false);
84-
$memory = $this->result->values($item['avg'], 1, false);
90+
$timeValues = $this->extract($item['avg'], self::TimeIndex);
91+
$memoryValues = $this->extract($item['avg'], self::MemoryIndex);
8592

86-
$avg = $this->metric($item, 'avg');
93+
$avg = $this->buildMetric($item, 'avg');
8794

8895
return new DeviationData(
89-
percent: $this->metricData(
90-
$this->percentage($avg->time, $this->deviation($time)),
91-
$this->percentage($avg->memory, $this->deviation($memory)),
96+
percent: new MetricData(
97+
$this->percentage($avg->time, $this->deviation($timeValues)),
98+
$this->percentage($avg->memory, $this->deviation($memoryValues)),
9299
),
93100
);
94101
}
95102

96-
/**
97-
* Creates a MetricData object with the specified values.
98-
*
99-
* @param float $time Time value is specified in milliseconds.
100-
* @param float $memory Memory value is specified in bytes.
101-
*/
102-
protected function metricData(float $time, float $memory): MetricData
103-
{
104-
return new MetricData($time, $memory);
105-
}
106-
107103
/**
108104
* Groups results from multiple runs by callback names and metric types.
109105
*
110-
* @param array $collection A collection of results from multiple runs.
106+
* @param array<int, array<int|string, ResultData>> $collection A collection of results from multiple runs.
107+
*
108+
* @return array<int|string, array<string, array<int, array{float, float}>>>
111109
*/
112-
protected function flatten(array $collection): array
110+
protected function group(array $collection): array
113111
{
114112
$result = [];
115113

116114
foreach ($collection as $items) {
117115
foreach ($items as $key => $item) {
118-
$result[$key]['min'][] = [$item->min->time, $item->min->memory];
119-
$result[$key]['max'][] = [$item->max->time, $item->max->memory];
120-
$result[$key]['avg'][] = [$item->avg->time, $item->avg->memory];
121-
$result[$key]['total'][] = [$item->total->time, $item->total->memory];
116+
foreach (self::MetricKeys as $metric) {
117+
$result[$key][$metric][] = [$item->$metric->time, $item->$metric->memory];
118+
}
122119
}
123120
}
124121

@@ -128,24 +125,24 @@ protected function flatten(array $collection): array
128125
/**
129126
* Calculates the standard deviation for an array of values.
130127
*
131-
* @param array $values An array of numeric values.
128+
* @param array<float> $values An array of numeric values.
132129
*/
133130
protected function deviation(array $values): float
134131
{
135-
$avg = array_sum($values) / count($values);
132+
$count = count($values);
133+
$avg = array_sum($values) / $count;
136134

137-
foreach ($values as &$value) {
138-
$value = ($value - $avg) ** 2;
139-
}
135+
$squared = array_map(static fn (float $value): float => ($value - $avg) ** 2, $values);
140136

141-
return sqrt(array_sum($values) / count($values));
137+
return sqrt(array_sum($squared) / $count);
142138
}
143139

144140
/**
145141
* Calculates the percentage ratio of two values.
146142
*
147143
* @param float $value1 The base value.
148144
* @param float $value2 The compared value.
145+
*
149146
* @return float The result is specified in percentages.
150147
*/
151148
protected function percentage(float $value1, float $value2): float

0 commit comments

Comments
 (0)