Skip to content

Change from dtoa to zmij - #369

Merged
krisztianfekete merged 1 commit into
prometheus:masterfrom
BentEngbers:switch_from_dtoa_to_zmij
Nov 13, 2026
Merged

krisztianfekete merged 1 commit into
prometheus:masterfrom
BentEngbers:switch_from_dtoa_to_zmij

Conversation

@BentEngbers

@BentEngbers BentEngbers commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Both crates are written by dtolnay:

https://github.com/dtolnay/dtoa
https://crates.io/crates/dtoa

https://github.com/dtolnay/zmij
https://crates.io/crates/zmij

Zmij seems more commonly used and should be faster According to dtolnay's own benchmarks (although running the benchmarks in this project on my machine did not show any significant changes). Zmij was already part of this project (See changes in the Cargo.lock).

@BentEngbers
BentEngbers force-pushed the switch_from_dtoa_to_zmij branch from 2fd9523 to bd61497 Compare November 5, 2026 13:26

@krisztianfekete krisztianfekete left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks,

Before merging:

  1. #368 is about to land and adds a few dtoa calls in prometheus_text.rs. Could you rebase after it merges and switch those to zmij too?
  2. Please add a test with fixed expected strings (see my inline comment).
  3. Please add a CHANGELOG.md line under Changed saying float output now uses the shortest form, so some f64 label values (including le) can look different.

I'd like to ship this together with #368 in 0.26.

Comment thread src/encoding.rs
impl EncodeLabelValue for f64 {
fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
encoder.write_str_unescaped(dtoa::Buffer::new().format(*self))
encoder.write_str_unescaped(zmij::Buffer::new().format(*self))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is also used for histogram le labels, so some label strings will change.

For example, with linear_buckets(0.1, 0.1, 20):

  • today: le="0.30000000000000007"
  • with this PR: le="0.30000000000000004"

Very small and very large values change too: 0.000001 becomes 1e-6, and 10000000000000000.0 becomes 1e+16.

The number is the same, but the label is different, so Prometheus sees a new series. I think the change is fine. We just need to tell users (see my top comment).

@BentEngbers BentEngbers Nov 10, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I added a test for histogram le labels in 4df9df3

Comment thread src/encoding/text.rs
+ "# UNIT my_counter_with_exemplar_seconds seconds\n"
+ "my_counter_with_exemplar_seconds_total 2 # {user_id=\"99\"} 1.0 "
+ dtoa::Buffer::new().format(now.duration_since(UNIX_EPOCH).unwrap().as_secs_f64())
+ zmij::Buffer::new().format(now.duration_since(UNIX_EPOCH).unwrap().as_secs_f64())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This test builds the expected value with zmij too, so it can't catch a format change.

Could you add one small test with fixed expected strings? For example: 1e-6, 1e16, 0.1 + 0.2, and one le from linear_buckets. Then a future zmij update can't change our output without us noticing.

@BentEngbers BentEngbers Nov 10, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I added a test in 2f6d04b.

@krisztianfekete

Copy link
Copy Markdown
Member

#368 is merged now. Could you rebase on master?

@BentEngbers

Copy link
Copy Markdown
Contributor Author

Ill have a look at it this week!

@BentEngbers

BentEngbers commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor Author

@krisztianfekete I have implemented all requested changes. Feel free to modify if there are any minor changes needed.
I also had a issue with the python setup in the test code. A potiential fix for that is in #378

@BentEngbers
BentEngbers force-pushed the switch_from_dtoa_to_zmij branch from f84482e to fee89e7 Compare November 10, 2026 16:27

@krisztianfekete krisztianfekete left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, added two small comments, then we can merge this!

Comment thread src/encoding/prometheus_text.rs Outdated
}

#[test]
fn encode_histogram_fixed_le_labels() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the test! Note that in prometheus_text, le uses GoFloat, not zmij`. This test also passes with the old dtoa code, so it doesn't catch your change.

The le that changes is in the OpenMetrics encoder in text.rs. Could you move it there?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

Comment thread CHANGELOG.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

0.26.0 was released in the meantime, can you put it under a new ## [Unreleased] section?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

@krisztianfekete krisztianfekete left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, the tests look good now! One last thing: the changelog diff still removes the PR 370 entry (and the [PR 370] link) from the 0.26.0 section. Could you add them back? After that I'll merge.

@BentEngbers

Copy link
Copy Markdown
Contributor Author

Thanks, the tests look good now! One last thing: the changelog diff still removes the PR 370 entry (and the [PR 370] link) from the 0.26.0 section. Could you add them back? After that I'll merge.

Oeps! Fixed in a4b28bb

@krisztianfekete

Copy link
Copy Markdown
Member

Sign the DCO please.

@krisztianfekete krisztianfekete left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, CI is green now! Your earlier commit a4b28bb had everything right, so please push it as one signed commit on top of master. That puts the changelog line under [Unreleased] and drops the import-style churn, and we'll do the parser fix in encode_flushes_large_output_in_chunks in a separate PR.

Signed-off-by: Bent Engbers <bentengbers@dreamsolution.nl>
@BentEngbers
BentEngbers force-pushed the switch_from_dtoa_to_zmij branch from c810bd1 to bc7a041 Compare November 12, 2026 20:07
@krisztianfekete
krisztianfekete added this pull request to the merge queue Nov 13, 2026
Merged via the queue into prometheus:master with commit 8e96c55 Nov 13, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants