Skip to content

Commit 317ee2c

Browse files
APCng storage - avoid worst-case memory usage in buildPermutationTree
1 parent 82e42b5 commit 317ee2c

File tree

1 file changed

+14
-24
lines changed

1 file changed

+14
-24
lines changed

src/Prometheus/Storage/APCng.php

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -414,31 +414,22 @@ private function metaData(array $data): array
414414
* [15] => ['/metrics', 'get', 'fail'], [16] => ['/metrics', 'post', 'success'], [17] => ['/metrics', 'post', 'fail']
415415
* @param array<string> $labelNames
416416
* @param array<array> $labelValues
417-
* @return array<array>
417+
* @return Generator<array>
418418
*/
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-
}
419+
private function buildPermutationTree(array $labelValues): \Generator /** @phpstan-ignore-line */
420+
{
421+
if($labelValues){
422+
$lastIndex = array_key_last($labelValues);
423+
if($currentValue = array_pop($labelValues)){
424+
foreach($this->buildPermutationTree($labelValues) as $prefix){
425+
foreach($currentValue as $value){
426+
yield $prefix + [$lastIndex => $value];
427+
}
439428
}
429+
}
430+
} else {
431+
yield [];
440432
}
441-
return $map;
442433
}
443434

444435
/**
@@ -539,10 +530,9 @@ private function getValues(string $type, array $metaData): array /** @phpstan-ig
539530
if (isset($metaData['buckets'])) {
540531
$metaData['buckets'][] = 'sum';
541532
$labels[] = $metaData['buckets'];
542-
$metaData['labelNames'][] = '__histogram_buckets';
543533
}
544534

545-
$labelValuesList = $this->buildPermutationTree($metaData['labelNames'], $labels);
535+
$labelValuesList = $this->buildPermutationTree($labels);
546536
unset($labels);
547537
$histogramBucket = '';
548538
foreach ($labelValuesList as $labelValues) {

0 commit comments

Comments
 (0)