1515
1616class 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