[前][次][番号順一覧][スレッド一覧]

ruby-changes:59028

From: KOSAKI <ko1@a...>
Date: Mon, 2 Dec 2019 01:34:57 +0900 (JST)
Subject: [ruby-changes:59028] 4d7a6d04b2 (master): Avoid unnecessary tzset() call

https://git.ruby-lang.org/ruby.git/commit/?id=4d7a6d04b2

From 4d7a6d04b2c71aabb9d6e619f4405887806a5be8 Mon Sep 17 00:00:00 2001
From: KOSAKI Motohiro <kosaki.motohiro@g...>
Date: Sun, 1 Dec 2019 16:21:05 +0000
Subject: Avoid unnecessary tzset() call

Akatsuki reported ENV['TZ'] = 'UTC' improved 7x-8x faster on following code.
t = Time.now; 100000.times { Time.new(2019) }; Time.now - t
https://hackerslab.aktsk.jp/2019/12/01/141551

commit 4bc1669127(reduce tzset) dramatically improved this situation. But still,
TZ=UTC is faster than default.

This patch removs unnecessary tzset() call completely.

Performance check
  ----------------------
test program: t = Time.now; 100000.times { Time.new(2019) }; Time.now - t
before:         0.387sec
before(w/ TZ):  0.197sec
after:          0.162sec
after(w/ TZ):   0.165sec

OK. Now, Time creation 2x faster *and* TZ=UTC doesn't improve anything.
We can forget this hack completely. :)

Side note:
This patch slightly changes Time.new(t) behavior implicitly. Before this patch, it might changes
default timezone implicitly. But after this patch, it doesn't. You need to reset TZ
(I mean ENV['TZ'] = nil) explicitly.
But I don't think this is big impact. Don't try to change /etc/localtime on runtime.

Side note2: following test might be useful for testing "ENV['TZ'] = nil".
  -----------------------------------------
% cat <<'End' | sudo sh -s
rm -f /etc/localtime-; cp -a /etc/localtime /etc/localtime-
rm /etc/localtime; ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
./ruby -e '
p Time.new(2000).zone # JST
File.unlink("/etc/localtime"); File.symlink("/usr/share/zoneinfo/America/Los_Angeles", "/etc/localtime")
p Time.new(2000).zone # JST (ruby does not follow /etc/localtime modification automatically)
ENV["TZ"] = nil
p Time.new(2000).zone # PST (ruby detect /etc/localtime modification)
'
rm /etc/localtime; cp -a /etc/localtime- /etc/localtime; rm /etc/localtime-
End

diff --git a/hash.c b/hash.c
index 6b3f844..0b3745c 100644
--- a/hash.c
+++ b/hash.c
@@ -4711,6 +4711,17 @@ env_delete(VALUE name) https://github.com/ruby/ruby/blob/trunk/hash.c#L4711
 
     nam = env_name(name);
     val = getenv(nam);
+
+    /*
+     * ENV['TZ'] = nil has a special meaning.
+     * TZ is no longer considered up-to-date and ruby call tzset() as needed.
+     * It could be useful if sysadmin change /etc/localtime.
+     * This hack might works only on Linux glibc.
+     */
+    if (ENVMATCH(nam, TZ_ENV)) {
+        ruby_tz_uptodate_p = FALSE;
+    }
+
     if (val) {
 	VALUE value = env_str_new2(val);
 
@@ -4718,9 +4729,6 @@ env_delete(VALUE name) https://github.com/ruby/ruby/blob/trunk/hash.c#L4729
 	if (ENVMATCH(nam, PATH_ENV)) {
 	    RB_GC_GUARD(name);
 	}
-	else if (ENVMATCH(nam, TZ_ENV)) {
-	    ruby_tz_uptodate_p = false;
-	}
 	return value;
     }
     return Qnil;
diff --git a/time.c b/time.c
index 3cb5a06..137d5e0 100644
--- a/time.c
+++ b/time.c
@@ -3139,15 +3139,10 @@ find_time_t(struct tm *tptr, int utc_p, time_t *tp) https://github.com/ruby/ruby/blob/trunk/time.c#L3139
 
     find_dst = 0 < tptr->tm_isdst;
 
-#if defined(HAVE_MKTIME)
-    tm0 = *tptr;
-    if (!utc_p && (guess = mktime(&tm0)) != -1) {
-        tm = GUESS(&guess);
-        if (tm && tmcmp(tptr, tm) == 0) {
-            goto found;
-        }
+    /* /etc/localtime might be changed. reload it. */
+    if (!ruby_tz_uptodate_p) {
+        tzset();
     }
-#endif
 
     tm0 = *tptr;
     if (tm0.tm_mon < 0) {
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]