Skip to content

Commit 88f9f61

Browse files
APCng storage - avoid worst-case memory usage in buildPermutationTree
Signed-off-by: Josh Hoffer <[email protected]>
1 parent 82e42b5 commit 88f9f61

File tree

1 file changed

+14
-25
lines changed

1 file changed

+14
-25
lines changed

src/Prometheus/Storage/APCng.php

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -412,33 +412,23 @@ private function metaData(array $data): array
412412
* [9] => ['/private', 'get', 'fail'], [10] => ['/private', 'post', 'success'], [11] => ['/private', 'post', 'fail'],
413413
* [12] => ['/metrics', 'put', 'success'], [13] => ['/metrics', 'put', 'fail'], [14] => ['/metrics', 'get', 'success'],
414414
* [15] => ['/metrics', 'get', 'fail'], [16] => ['/metrics', 'post', 'success'], [17] => ['/metrics', 'post', 'fail']
415-
* @param array<string> $labelNames
416415
* @param array<array> $labelValues
417-
* @return array<array>
416+
* @return Generator<array>
418417
*/
419-
private function buildPermutationTree(array $labelNames, array $labelValues): array /** @phpstan-ignore-line */
420-
{
421-
$treeRowCount = count(array_keys($labelNames));
422-
$numElements = 1;
423-
$treeInfo = [];
424-
for ($i = $treeRowCount - 1; $i >= 0; $i--) {
425-
$treeInfo[$i]['numInRow'] = count($labelValues[$i]);
426-
$numElements *= $treeInfo[$i]['numInRow'];
427-
$treeInfo[$i]['numInTree'] = $numElements;
428-
}
429-
430-
$map = array_fill(0, $numElements, []);
431-
for ($row = 0; $row < $treeRowCount; $row++) {
432-
$col = $i = 0;
433-
while ($i < $numElements) {
434-
$val = $labelValues[$row][$col];
435-
$map[$i] = array_merge($map[$i], array($val));
436-
if (++$i % ($treeInfo[$row]['numInTree'] / $treeInfo[$row]['numInRow']) == 0) {
437-
$col = ++$col % $treeInfo[$row]['numInRow'];
438-
}
418+
private function buildPermutationTree(array $labelValues): \Generator /** @phpstan-ignore-line */
419+
{
420+
if($labelValues){
421+
$lastIndex = array_key_last($labelValues);
422+
if($currentValue = array_pop($labelValues)){
423+
foreach($this->buildPermutationTree($labelValues) as $prefix){
424+
foreach($currentValue as $value){
425+
yield $prefix + [$lastIndex => $value];
426+
}
439427
}
428+
}
429+
} else {
430+
yield [];
440431
}
441-
return $map;
442432
}
443433

444434
/**
@@ -539,10 +529,9 @@ private function getValues(string $type, array $metaData): array /** @phpstan-ig
539529
if (isset($metaData['buckets'])) {
540530
$metaData['buckets'][] = 'sum';
541531
$labels[] = $metaData['buckets'];
542-
$metaData['labelNames'][] = '__histogram_buckets';
543532
}
544533

545-
$labelValuesList = $this->buildPermutationTree($metaData['labelNames'], $labels);
534+
$labelValuesList = $this->buildPermutationTree($labels);
546535
unset($labels);
547536
$histogramBucket = '';
548537
foreach ($labelValuesList as $labelValues) {

0 commit comments

Comments
 (0)