Skip to content

[vm/runtime] Call tzset() before localtime_r(). #61302

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

JesseRiemens
Copy link

@JesseRiemens JesseRiemens commented Aug 13, 2025

Relevant info in #60191 (And duplicate #61303)

POSIX doesn't guarantee that the timezone is set correctly before calling localtime_r(), so we need to call tzset() first to ensure that the timezone information is up-to-date.

As the glibc manual states:

According to POSIX.1-2001, localtime() is required to behave as though tzset(3) was called, while localtime_r() does not
have this requirement. For portable code, tzset(3) should be called before localtime_r().

  • Thanks for your contribution! Please replace this text with a description of what this PR is changing or adding and why, list any relevant issues, and review the contribution guidelines below.

  • I’ve reviewed the contributor guide and applied the relevant portions to this PR.
Contribution guidelines:
  • See our contributor guide for general expectations for PRs.
  • Larger or significant changes should be discussed in an issue before creating a PR.
  • Contributions to our repos should follow the Dart style guide and use dart format.

Note that this repository uses Gerrit for code reviews. Your pull request will be automatically converted into a Gerrit CL and a link to the CL written into this PR. The review will happen on Gerrit but you can also push additional commits to this PR to update the code review.

POSIX doesn't guarantee that the timezone is set correctly before calling `localtime_r()`, so we need to call `tzset()` first to ensure that the timezone information is up-to-date.

As the glibc manual states:
> According to POSIX.1-2001, `localtime()` is required to behave as though `tzset(3)` was called, while `localtime_r()` does not
> have this requirement. For portable code, `tzset(3)` should be called before `localtime_r()`.
Copy link

Thank you for your contribution! This project uses Gerrit for code reviews. Your pull request has automatically been converted into a code review at:

https://dart-review.googlesource.com/c/sdk/+/444983

Please wait for a developer to review your code review at the above link; you can speed up the review if you sign into Gerrit and manually add a reviewer that has recently worked on the relevant code. See CONTRIBUTING.md to learn how to upload changes to Gerrit directly.

Additional commits pushed to this PR will update both the PR and the corresponding Gerrit CL. After the review is complete on the CL, your reviewer will merge the CL (automatically closing this PR).

Copy link

https://dart-review.googlesource.com/c/sdk/+/444983 has been updated with the latest commits from this pull request.

@mraleph
Copy link
Member

mraleph commented Aug 13, 2025

Do you know what is the cost associated with calling tzset here? I would imagine it does a bunch of stuff to figure out the system timezone, how much does this add on top of what localtime_r costs?

Copy link

https://dart-review.googlesource.com/c/sdk/+/444983 has been updated with the latest commits from this pull request.

@JesseRiemens
Copy link
Author

JesseRiemens commented Aug 13, 2025

Do you know what is the cost associated with calling tzset here? I would imagine it does a bunch of stuff to figure out the system timezone, how much does this add on top of what localtime_r costs?

I made a quick benchmark that does ten runs of 10 million DateTime.now() calls, and the results are below:

The modded version, with the tzset() call:

~/Applications/dart-sdk-test/dart-modified/sdk/out/ReleaseX64/dart-sdk/bin/dart run ./bin/time_benchmark.dart  
Total time taken for 10000000 iterations: 345942 microseconds
Average time taken: 0.0345942 microseconds
Total time taken for 10000000 iterations: 345456 microseconds
Average time taken: 0.0345456 microseconds
Total time taken for 10000000 iterations: 387595 microseconds
Average time taken: 0.0387595 microseconds
Total time taken for 10000000 iterations: 344673 microseconds
Average time taken: 0.0344673 microseconds
Total time taken for 10000000 iterations: 343620 microseconds
Average time taken: 0.034362 microseconds
Total time taken for 10000000 iterations: 344166 microseconds
Average time taken: 0.0344166 microseconds
Total time taken for 10000000 iterations: 339798 microseconds
Average time taken: 0.0339798 microseconds
Total time taken for 10000000 iterations: 337510 microseconds
Average time taken: 0.033751 microseconds
Total time taken for 10000000 iterations: 337566 microseconds
Average time taken: 0.0337566 microseconds
Total time taken for 10000000 iterations: 340555 microseconds
Average time taken: 0.0340555 microseconds
Total time taken for all iterations: 3466881 microseconds
Average time taken per iteration: 0.03466881 microseconds

The non-modified version:

~/Applications/dart-sdk-test/dart-without-mod/sdk/out/ReleaseX64/dart-sdk/bin/dart run ./bin/time_benchmark.dart
Total time taken for 10000000 iterations: 344923 microseconds
Average time taken: 0.0344923 microseconds
Total time taken for 10000000 iterations: 350685 microseconds
Average time taken: 0.0350685 microseconds
Total time taken for 10000000 iterations: 355197 microseconds
Average time taken: 0.0355197 microseconds
Total time taken for 10000000 iterations: 338760 microseconds
Average time taken: 0.033876 microseconds
Total time taken for 10000000 iterations: 338500 microseconds
Average time taken: 0.03385 microseconds
Total time taken for 10000000 iterations: 339348 microseconds
Average time taken: 0.0339348 microseconds
Total time taken for 10000000 iterations: 338644 microseconds
Average time taken: 0.0338644 microseconds
Total time taken for 10000000 iterations: 345835 microseconds
Average time taken: 0.0345835 microseconds
Total time taken for 10000000 iterations: 344627 microseconds
Average time taken: 0.0344627 microseconds
Total time taken for 10000000 iterations: 339836 microseconds
Average time taken: 0.0339836 microseconds
Total time taken for all iterations: 3436355 microseconds
Average time taken per iteration: 0.03436355 microseconds

That's 0.03466881 with mod vs 0.03436355 without mod;
That's 0.9% (1.0089) increase.

If you have any improvement to my benchmark method, please let me know.
It seems like the difference compared to the rest of the overhead is very small.

Edit: It actually looks like after repeated testing that the modified build is faster often, and I can't understand why.

@mraleph
Copy link
Member

mraleph commented Aug 15, 2025

I think this looks good to me. Could you apply the same patch to os_android (I assume it has the same problem?) and then I can land it.

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