-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
linux: free datetime interface from tz #3420
Conversation
obastemur
commented
Jul 24, 2017
•
edited
Loading
edited
- Improves performance on XPLAT (up to 10 times)
- New OSX Date interface had dropped old Windows specific date tests. Do the same for Linux
- XPLAT DST for BC (negative years) doesn't have to match to Windows.
How much of a performance change do you see here? Removing the redundant |
tzset(); | ||
time_t ltime = timegm(&utc_tm); | ||
time_t ltime = mktime(&utc_tm); | ||
ltime += -(utc_tm.tm_isdst * 3600) + (utc_tm.tm_gmtoff); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this behave around a DST transition? And the docs seem to indicate that tm_isdst
can be negative if it is unknown, which would cause an incorrect conversion here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the docs seem to indicate that tm_isdst can be negative if it is unknown
We fix the date at the other part of the same file. If system really doesn't know DST for a modern date, we will end-up showing the wrong date.
Besides, same opposite calculation was already being done under LocalToUTC. So, it's a give/take situation.
@MSLaguana Could you please share a reference for this claim? It reaches to DB for only negative dst value. There is no other way around. |
That comment was based on the man page and experimentation. The man page actually only seemed to mention it for
Experimenting myself, I do see the behavior that I mention though. Compile this program: #include <time.h>
#include <stdio.h>
int main() {
struct tm tm = {};
time_t t = mktime(&tm);
printf("%u\n", t);
tm.tm_sec = 1;
t = mktime(&tm);
printf("%u\n", t);
return 0;
} and note that I never invoke
|
We do not use localtime either. From your comment;
For the example you have shared; again, |
This implementation replaces timegm to mktime with an additional arithmetic operation. Otherwise we would have to do below;
|
I don't understand your comment there. I just added to my example to use all values of int main() {
struct tm tm = {};
time_t t = mktime(&tm);
printf("%u\n", t);
tm.tm_sec = 1;
tm.tm_isdst = -1;
t = mktime(&tm);
printf("%u\n", t);
tm.tm_sec = 2;
tm.tm_isdst = 0;
t = mktime(&tm);
printf("%u\n", t);
tm.tm_sec = 3;
tm.tm_isdst = 1;
t = mktime(&tm);
printf("%u\n", t);
tzset();
tzset();
return 0;
}
Whenever |
@MSLaguana I see what you are comparing. See my sample above (#3420 (comment)) In order to produce a correct result, we have to do the same. However, this PR replaces that with a single mktime instead. |
How does performance compare? From what I can see, we will still be waiting on syscalls that may touch the disk every time we call one of our date conversion functions because they still implicitly call |
No they won't. Once again, there is no timezone set. You are mixing tzset with reaching to db for getting DST. We've been both setting tz (forth and back) and environment. Now we don't. We still reach DB. We have to. |
Then let me put it this way: We still make system calls each time we perform date conversions, which will still have an adverse perf impact. Do you actually see perf improvements? When I was experimenting previously, I didn't see gains until I had removed everything that would make the stat system calls. |
- New OSX Date interface had dropped old Windows specific date tests. Do the same for Linux - Up to 10 times better perf.
Simplified the interface further. Performance gain is up to 10 times! Please review. See also updated PR comment #3420 (comment) |
@MSLaguana we have to make some calls to get DST. We could embed a DST db but that would be beyond the scope. |
I think that this newest change looks good, but I have one concern: The docs for
I think that for portability, we might need to guarantee that we invoke I'm also not sure what the behavior would be around daylight savings changes in that case, if it would not update until the next time |
Looks like my DST concern is backed up by some SO questions: https://stackoverflow.com/questions/19170721/real-time-awareness-of-timezone-change-in-localtime-vs-localtime-r |
@MSLaguana I would leave this (system timezone change) responsibility to host application. If we will be caring about TZ changes, we could do it under If host cares about TZ changes, they can sync in fitting time frame easily. They have to do it for their application anyways! I'm not sure why we need to invest 10% perf on something won't be used? |
My perspective here is that since by-spec the JS engine is expected to deal with computing the timezone offset and daylight savings time, the host should be able to rely on that behavior and not have to know about internal details like how timezones are handled. I'd prefer an approach more similar to what we do on windows, where we have a cache that expires every ~second. In the xplat case that could be invoking |
@MSLaguana well, once we trigger tzset, we do the math for host app too. no? Besides, node doesn't do anything for this? Also, having time zone changed for a server or user machine is not something in common? So, why do we bother dealing with it? ChakraCore is a library and handles timezone for datetime stuff according to spec. We just don't care if system timezone has changed. It is up to host app? On Windows, system deals with that, not the host app or chakracore. |
Right: On windows, the system deals with it, and ChakraCore asks the system. On xplat, if we don't invoke However, I just ran an experiment. On node running v8 on linux, if you change the system timezone, then it behaves in an inconsistent way: > var d = new Date()
undefined
> d.toString()
'Mon Jul 31 2017 13:17:33 GMT-0700 (PDT)'
// System timezone change
> d.toString()
'Mon Jul 31 2017 13:17:33 GMT-0700 (ACST)'
> var d2 = new Date()
undefined
> d2.toString()
'Mon Jul 31 2017 12:19:48 GMT-0800 (ACST)'
> d.toString()
'Mon Jul 31 2017 13:17:33 GMT-0700 (ACST)'
// System timezone change
> d.toString()
'Mon Jul 31 2017 13:17:33 GMT-0700 (PDT)'
> d2.toString()
'Mon Jul 31 2017 12:19:48 GMT-0800 (PDT)' Currently node-chakracore behaves in a way that I feel is more correct, because we do check the system timezone every time: > var d = new Date()
undefined
> d.toString()
'Mon Jul 31 2017 13:26:11 GMT-0700 (PDT)'
// Change system timezone
> d.toString()
'Mon Jul 31 2017 13:26:11 GMT-0700 (ACST)'
> var d2 = new Date()
undefined
> d2.toString()
'Tue Aug 01 2017 05:56:30 GMT+0930 (ACST)'
// Change system timezone
> d2.toString()
'Tue Aug 01 2017 05:56:30 GMT+0930 (PDT)'
> d.toString()
'Mon Jul 31 2017 13:26:11 GMT-0700 (PDT)' This is still arguably wrong, since the timezone abbreviation always reports the current timezone and not the timezone of the date, but at least times are correctly converted to local time. However, given the behavior of node-v8, I am not opposed to matching that behavior by only checking the system timezone once, as long as daylight savings behaves correctly (I'm not sure how best to check that experimentally). |
https://tc39.github.io/ecma262/#sec-local-time-zone-adjustment
If the timezone did change and as a result this computation did not show the current local standard time, we would be in violation of the spec (at a minimum, in violation of the spirit of the spec). https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment
There's always potential for being incorrect on the edge cases, no matter how frequently you check, unless you ensure that the exact time you get when you determine the TZ is the same as the time you are formatting. Worst case, there's a glitch in those edge cases and maybe someone notices (or not) but the glitch goes away when you make a new request because the TZ will be corrected at that time. best effort tells us we should do the best we can, but if we're out of date by a small interval or the system is wrong (which we can't do anything about) then we're okay as far as the spec is concerned.
It's a good point that this isn't especially likely to come up in practice. However, there will be long running server processes which would probably like to have the current date and timezone information if something changed (including political changes). Which is precisely why we can cache the result and only check occasionally (~1s = 1000-2000 requests). We should take the spirit of the spec and do best effort to get the best possible answer while getting good performance. Making the expensive check only every ~1s seems like a good compromise here. |
@MSLaguana @dilijev Thanks for the comments. I understand your points. Well, on OSX, we could listen to an event. Although we do cache the time and make sure it's going forward, we could arrange some tricks. However, we can not sync to tz instantly; unless there is any trigger to UTCToLocal / Get new time etc.! (which I understood you give a 1s update time if any of these are being called, please read more.)On Linux, timezone data is cached when the process is started. Unless process calls tzset, the mapped data will remain as is. tzset is used to read the database and update process's mapping. Nothing more. Heck, that's why it's slow and implemented this way.One more interesting part; If a particular time zone data is not available?? not sure the behavior. If system tzdata is updated? this will require system restart on linux. Concern; One example;My host app (along with the many child processes) don't care about time zone changes (including political ones) and use time as a going forward piece of variable. If, for any reason, time goes to backwards, what will happen? One may argue that time goes backwards (an hour) during DST? Well, that's part of the current tz configuration and applies to all processes simultaneously. Previously, every piece of time information we provide was synced hence the behavior across the processes were consistent. (hence extremely slow) I'm okay with the best efforts. I'm just against altering the host behavior other than the currently expected behavior while sacrificing performance and other potential issues. |
@MSLaguana @dilijev opened #3467 to track the problem and continue to discussion on updating tzdata if system timezone changes while a process is actively running. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now since this isn't any worse than v8's behavior I'm happy to take the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with Jimmy. This is an improvement. Happy to continue the discussion later.
@MSLaguana @dilijev Thanks for the review |
Merge pull request #3420 from obastemur:time_faster - Improves performance on XPLAT (up to 10 times) - New OSX Date interface had dropped old Windows specific date tests. Do the same for Linux - XPLAT DST for BC (negative years) doesn't have to match to Windows.
…from tz Merge pull request #3420 from obastemur:time_faster - Improves performance on XPLAT (up to 10 times) - New OSX Date interface had dropped old Windows specific date tests. Do the same for Linux - XPLAT DST for BC (negative years) doesn't have to match to Windows.
…from tz Merge pull request #3420 from obastemur:time_faster - Improves performance on XPLAT (up to 10 times) - New OSX Date interface had dropped old Windows specific date tests. Do the same for Linux - XPLAT DST for BC (negative years) doesn't have to match to Windows.