util: cache local GTimeZone

This ensures that we do not create a new GTimeZone with
g_time_zone_new_local() repeatedly. Currently, that will cause GTimeZone
to open(), mmap() and parse /etc/localtime while on the main thread.

We already track timezone changes, so we can cache this value and reuse
it if we:

 1) Clear the cache when timezone changes
 2) Use the only GDateTime API available to us here, which means we
    imply the current time. But this is how environment.js uses the
    date and time anyway, so no loss.

We maintain the old form for plugin compatibility.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2279
This commit is contained in:
Christian Hergert 2020-02-26 19:34:15 -08:00
parent 3f35ad0cbf
commit f597a0a11c
4 changed files with 34 additions and 1 deletions

View File

@ -573,6 +573,11 @@ var DateMenuButton = new Lang.Class({
// https://bugzilla.gnome.org/show_bug.cgi?id=678507
System.clearDateCaches();
// To reduce the number of times that Shell opens /etc/localtime on
// the main thread to parse timezone info, we cache the result. That
// needs to be cleared when we change timezones.
Shell.util_clear_timezone_cache();
this._calendar.updateTimeZone();
},

View File

@ -118,7 +118,7 @@ function init() {
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
Date.prototype.toLocaleFormat = function(format) {
return Shell.util_format_date(format, this.getTime());
return Shell.util_format_now(format);
};
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');

View File

@ -20,6 +20,8 @@
#include <langinfo.h>
#endif
static GTimeZone *local_tz;
static void
stop_pick (ClutterActor *actor,
const ClutterColor *color)
@ -154,6 +156,30 @@ shell_util_format_date (const char *format,
return result;
}
char *
shell_util_format_now (const char *format)
{
GDateTime *datetime;
char *ret;
if (local_tz == NULL)
local_tz = g_time_zone_new_local ();
datetime = g_date_time_new_now (local_tz);
if (!datetime)
return g_strdup ("");
ret = g_date_time_format (datetime, format);
g_date_time_unref (datetime);
return ret;
}
void
shell_util_clear_timezone_cache (void)
{
g_clear_pointer (&local_tz, g_time_zone_unref);
}
/**
* shell_util_get_week_start:
*

View File

@ -22,6 +22,8 @@ int shell_util_get_week_start (void);
char *shell_util_format_date (const char *format,
gint64 time_ms);
char *shell_util_format_now (const char *format);
void shell_util_clear_timezone_cache (void);
const char *shell_util_translate_time_string (const char *str);
char *shell_util_regex_escape (const char *str);