Skip to content

Commit 6b0996c

Browse files
authored
speedup collection of counters and histograms (#120)
Replace collection for counters and histograms with optimized version. The collection functions for them had geometric complexity in the number of metrics. That made them unsusable for large datasets.
1 parent 520d137 commit 6b0996c

File tree

2 files changed

+45
-37
lines changed

2 files changed

+45
-37
lines changed

src/metrics/prometheus_counter.erl

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,9 @@ values(Registry, Name) ->
288288
MF ->
289289
Labels = prometheus_metric:mf_labels(MF),
290290
MFValues = load_all_values(Registry, Name),
291-
[begin
292-
Value = reduce_label_values(LabelValues, MFValues),
293-
{lists:zip(Labels, LabelValues), Value}
294-
end ||
295-
LabelValues <- collect_unique_labels(MFValues)]
291+
LabelValues = reduce_label_values(MFValues),
292+
serialize_label_values(
293+
fun(VLabels, Value) -> {VLabels, Value} end, Labels, LabelValues)
296294
end.
297295

298296
%%====================================================================
@@ -315,12 +313,12 @@ collect_mf(Registry, Callback) ->
315313
%% @private
316314
collect_metrics(Name, {CLabels, Labels, Registry}) ->
317315
MFValues = load_all_values(Registry, Name),
318-
[begin
319-
Value = reduce_label_values(LabelValues, MFValues),
320-
prometheus_model_helpers:counter_metric(
321-
CLabels ++ lists:zip(Labels, LabelValues), Value)
322-
end ||
323-
LabelValues <- collect_unique_labels(MFValues)].
316+
LabelValues = reduce_label_values(MFValues),
317+
serialize_label_values(
318+
fun(VLabels, Value) ->
319+
prometheus_model_helpers:counter_metric(
320+
CLabels ++ VLabels, Value)
321+
end, Labels, LabelValues).
324322

325323
%%====================================================================
326324
%% Private Parts
@@ -350,11 +348,18 @@ key(Registry, Name, LabelValues) ->
350348
Rnd = X band (?WIDTH-1),
351349
{Registry, Name, LabelValues, Rnd}.
352350

353-
collect_unique_labels(MFValues) ->
354-
lists:usort([L || [L, _, _] <- MFValues]).
355-
356-
reduce_label_values(Labels, MFValues) ->
357-
lists:sum([I + F || [L, I, F] <- MFValues, L == Labels]).
351+
reduce_label_values(MFValues) ->
352+
lists:foldl(
353+
fun([Labels, I, F], ResAcc) ->
354+
PrevSum = maps:get(Labels, ResAcc, 0),
355+
ResAcc#{Labels => PrevSum + I + F}
356+
end, #{}, MFValues).
357+
358+
serialize_label_values(Fun, Labels, Values) ->
359+
maps:fold(
360+
fun(LabelValues, Value, L) ->
361+
[Fun(lists:zip(Labels, LabelValues), Value)|L]
362+
end, [], Values).
358363

359364
create_counter(Name, Help, Data) ->
360365
prometheus_model_helpers:create_mf(Name, Help, counter, ?MODULE, Data).

src/metrics/prometheus_histogram.erl

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -366,17 +366,18 @@ values(Registry, Name) ->
366366
DU = prometheus_metric:mf_duration_unit(MF),
367367
Labels = prometheus_metric:mf_labels(MF),
368368
Bounds = prometheus_metric:mf_data(MF),
369+
369370
MFValues = load_all_values(Registry, Name, Bounds),
370-
[begin
371-
[ISum, FSum | BCounters] = reduce_label_values(LabelValues, MFValues),
372-
Bounds1 = lists:zipwith(fun(Bound, Bucket) ->
373-
{Bound, Bucket}
374-
end,
375-
Bounds, BCounters),
376-
{lists:zip(Labels, LabelValues), Bounds1,
377-
prometheus_time:maybe_convert_to_du(DU, ISum + FSum)}
378-
end ||
379-
LabelValues <- collect_unique_labels(MFValues)]
371+
LabelValuesMap = reduce_label_values(MFValues),
372+
maps:fold(
373+
fun(LabelValues, [ISum, FSum | BCounters], L) ->
374+
Bounds1 = lists:zipwith(fun(Bound, Bucket) ->
375+
{Bound, Bucket}
376+
end,
377+
Bounds, BCounters),
378+
[{lists:zip(Labels, LabelValues), Bounds1,
379+
prometheus_time:maybe_convert_to_du(DU, ISum + FSum)}|L]
380+
end, [], LabelValuesMap)
380381
end.
381382

382383
%% @equiv buckets(default, Name, [])
@@ -415,11 +416,11 @@ collect_mf(Registry, Callback) ->
415416
%% @private
416417
collect_metrics(Name, {CLabels, Labels, Registry, DU, Bounds}) ->
417418
MFValues = load_all_values(Registry, Name, Bounds),
418-
[begin
419-
Stat = reduce_label_values(LabelValues, MFValues),
420-
create_histogram_metric(CLabels, Labels, DU, Bounds, LabelValues, Stat)
421-
end ||
422-
LabelValues <- collect_unique_labels(MFValues)].
419+
LabelValuesMap = reduce_label_values(MFValues),
420+
maps:fold(
421+
fun(LabelValues, Stat, L) ->
422+
[create_histogram_metric(CLabels, Labels, DU, Bounds, LabelValues, Stat)|L]
423+
end, [], LabelValuesMap).
423424

424425
%%====================================================================
425426
%% Private Parts
@@ -564,12 +565,14 @@ key(Registry, Name, LabelValues) ->
564565
Rnd = X band (?WIDTH-1),
565566
{Registry, Name, LabelValues, Rnd}.
566567

567-
collect_unique_labels(MFValues) ->
568-
lists:usort([L || [L | _] <- MFValues]).
569-
570-
reduce_label_values(Labels, MFValues) ->
571-
[lists:sum(C)
572-
|| C <- transpose([V || [L | V] <- MFValues, L == Labels])].
568+
reduce_label_values(MFValues) ->
569+
lists:foldl(
570+
fun([Labels | V], ResAcc) when is_map_key(Labels, ResAcc) ->
571+
PrevSum = maps:get(Labels, ResAcc),
572+
ResAcc#{Labels => [lists:sum(C) || C <- transpose([PrevSum, V])]};
573+
([Labels | V], ResAcc) ->
574+
ResAcc#{Labels => V}
575+
end, #{}, MFValues).
573576

574577
create_histogram(Name, Help, Data) ->
575578
prometheus_model_helpers:create_mf(Name, Help, histogram, ?MODULE, Data).

0 commit comments

Comments
 (0)