Skip to content

Hide the implementation details of labels.Labels#10887

Closed
bboreham wants to merge 54 commits intoprometheus:mainfrom
bboreham:labels-struct
Closed

Hide the implementation details of labels.Labels#10887
bboreham wants to merge 54 commits intoprometheus:mainfrom
bboreham:labels-struct

Conversation

@bboreham
Copy link
Member

@bboreham bboreham commented Jun 19, 2022

The slice nature of labels.Labels is hard-coded in about 1,000 places in the code of Prometheus, which makes it very difficult to experiment with a different data structure.

This PR changes the type to a struct so that any attempt to use it as a slice generates a compilation error, and introduces some abstractions to allow these errors to be fixed. Some of these abstractions (e.g. Reserve() and Append() are rather thin and we can probably do better; consider them placeholders if you like. A new ScratchBuilder was added, which is like labels.Builder but streamlined for the case where we only add unique labels.

It's not much of a step forward on its own, but it makes things easier for someone (like me) experimenting with the data structure. Mentioned on prometheus-developers.

All tests pass, and benchmarks go broadly at the same speed.

Copy link
Member

@bwplotka bwplotka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good generally 👍🏽

For reviewers: Main file seems to be here

I can see this being a hell for test assertions if someone uses some native slice assertion helpers. But I think it the advantage of this is exceeding the cons.

@roidelapluie
Copy link
Member

Are you able to test this in real condition to better asses the performance impact?

@beorn7
Copy link
Member

beorn7 commented Jun 22, 2022

@roidelapluie maybe let's just run Prombench on this PR?

@roidelapluie
Copy link
Member

/prombench main

@prombot
Copy link
Contributor

prombot commented Jun 22, 2022

⏱️ Welcome to Prometheus Benchmarking Tool. ⏱️

Compared versions: PR-10887 and main

After successful deployment, the benchmarking metrics can be viewed at:

Other Commands:
To stop benchmark: /prombench cancel
To restart benchmark: /prombench restart main

@prombot
Copy link
Contributor

prombot commented Jun 25, 2022

Benchmark tests are running for 3 days! If this is intended ignore this message otherwise you can cancel it by commenting: /prombench cancel

@bboreham
Copy link
Member Author

I see very close correspondance between the 'main' and 'PR' lines on the dashboard, which matches what the benchmarks say.
You can cancel the prombench. (I assume I cannot, as not a maintainer).

@roidelapluie
Copy link
Member

/prombench cancel

@prombot
Copy link
Contributor

prombot commented Jun 27, 2022

Benchmark cancel is in progress.

@bboreham
Copy link
Member Author

bboreham commented Jul 5, 2022

I pushed an update which removes Reserve() and Append(), instead adding a SimpleBuilder which is like labels.Builder but streamlined for the case where we only add unique labels.

@bboreham bboreham force-pushed the labels-struct branch 4 times, most recently from be780fd to 6369b08 Compare July 6, 2022 12:31
@roidelapluie
Copy link
Member

Can you please fix linting?

@bboreham
Copy link
Member Author

bboreham commented Jul 6, 2022

Sure; note #10991 is the interesting one; this is just laying the groundwork.

@roidelapluie
Copy link
Member

I wonder if we could merge this and then feature flag this change

@bboreham
Copy link
Member Author

bboreham commented Jul 6, 2022

I wonder if we could merge this and then feature flag this change

I assume you mean merge #10887 and feature-flag #10991?

That is an interesting idea, however the change pervades many parts of Prometheus so I don't think that is realistic.
For instance labels.Labels, which is embedded into things like Series, will change from 24 bytes to 16 bytes. Everything has to be recompiled.

@roidelapluie
Copy link
Member

Oh, I was thinking we could turn labels into an interface

@bboreham
Copy link
Member Author

Oh, I was thinking we could turn labels into an interface

While conceptually that is a fine idea; in practice we now need 16 bytes for the interface pointer on top of whatever is used to store Labels (e.g. a 24-byte slice header). Also all calls through an interface cause heap escape, which may make some existing operations expensive.

So I'm guessing it will be too expensive.

@beorn7
Copy link
Member

beorn7 commented Jul 13, 2022

Let's reimplement Prometheus in Rust… 🦆

@roidelapluie
Copy link
Member

Can we move this out of draft?

@bboreham
Copy link
Member Author

There have been a few fixes in #10991 which also affect this branch; I should move them here, and particularly the extra tests.

I think this change will be disruptive for projects like Thanos and Mimir. I don't think it's a good idea to merge now without some preparation (e.g. trying the port in a fork).

@roidelapluie
Copy link
Member

Yet it is an ideal time for Prometheus itself since we are far from a release. I'd really like to see this PR happen asap.

Dependencies can decide when they upgrade, I don't think timing is a big issue.

@bboreham
Copy link
Member Author

There have been a few fixes in #10991 which also affect this branch; I should move them here, and particularly the extra tests.

I have done this; unfortunately in the process I broke it. Will fix soon.

Note the IndexReader now changes in this branch, which again is likely to be disruptive.

bboreham and others added 26 commits December 15, 2022 19:51
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Note we avoid calling `Labels.Len()` in `labelProtosToLabels()`.
It isn't necessary - `append()` will enlarge the buffer and we're
expecting to re-use it many times.

Also, we now validate protobuf input before converting to Labels.
This way we can detect errors first, and we don't place unnecessary
requirements on the Labels structure.

Re-do seriesFilter using labels.Builder (albeit N^2).

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Use SimpleBuilder to create labels.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Instead of relying on being able to append to it like a slice.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
This avoids spurious failures in tests.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
In code added since first pass.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
To avoid code breaking when the data structure for labels.Labels changes.

In code added since first pass.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Saves memory allocations when you know the right size.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
It was only called in one place, so move the logic there.

Reduced surface area of labels.Labels is better for understandability.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
It was only called in one place, so move the logic there.

`QueueManager.externalLabels` becomes a slice rather than a `Labels` so
we can index into it when doing the merge operation.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Co-authored-by: Bartlomiej Plotka <bwplotka@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
The requirement is met fairly well by `ScratchBuilder`.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
labels.Labels are always sorted.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Much easier to read.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
@bboreham
Copy link
Member Author

I'm closing this; the bulk of the changes were merged in #11717, and I don't think we would make this change just to enforce them, we would go straight to #10991.

@bboreham bboreham closed this Dec 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants