grafana / loki

Like Prometheus, but for logs.
https://grafana.com/loki
GNU Affero General Public License v3.0
24k stars 3.46k forks source link

chore(metric_extraction): Optimize labels result #15068

Closed shantanualsi closed 3 days ago

shantanualsi commented 3 days ago

What this PR does / why we need it:

The current implementation of LabelsResult method used in critical flows within metrics_generation, pipeline, etc fetched UnsortedLabels in the buffer for each category (ParsedLabel, structured metadata, StreamLabel) and individually sorts them. The sorted results are cached in memory. Majority of resource utilisation here was on sorting labels of each of the categories and creating a copy from buffer.

The new implementation fetches all Unsorted Labels and sorts them collectively and caches the result first. Individual categories are segregated after caching.

(notice the labels.Copy is gone in the newer implementation in memory profile)

Results:

BenchmarkStreamLineSampleExtractor_Process

Cpu before:

cpu_before

Cpu after

cpu_aft

Mem before:

mem_before

Cpu after:

mem_after

BenchmarkReadWithStructuredMetadata: create a memchunk and iterate on it

cpu and memory

Screenshot 2024-11-22 at 14 05 34

benchstat result -

benchstat

Overall Summary from the results:

Excluding some variability in the measurements, The new implementation is at least 28% faster than the older one with a dramatic 89% improvement in memory usage. Each run also took 79.8% fewer allocs/op than the old implementation.

Which issue(s) this PR fixes:

Special notes for your reviewer:

Checklist

shantanualsi commented 3 days ago

Thanks! Will address the comments separately in a separate PR.

shantanualsi commented 19 hours ago

To address the comments here, re-using the slices as expected seem to increase in-use memory as opposed to initializing the slices for parsed, SM and stream labels. https://github.com/grafana/loki/compare/main...shantanu/improve-iterator-optimization

Also, the call func (l labelsResult) Labels() is now only used in tests, not in the critical path anymore. We don't need flattenLabels as all the labels are stored alreayd in the buffer and then sorted.