summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Chimento <philip.chimento@gmail.com>2023-02-26 21:03:00 -0800
committerPhilip Chimento <philip.chimento@gmail.com>2023-03-04 23:40:32 -0800
commite9dfa02f1d7df0ef2155600633b833efb3fa5477 (patch)
treeefb2b8741774057ac666fe09dc8e072dea518f39
parentde647bbfaf7964edf520a96212755c9a3dfc5c2c (diff)
downloadgjs-e9dfa02f1d7df0ef2155600633b833efb3fa5477.tar.gz
esm: Improve startup time by delaying imports of native and GI modules
By avoiding using import.meta.importSync() and imports.gi at the top level of modules that we import during the bootstrap process, we speed up the execution of a blank file by 15%, because we don't need to go into any of the GI typelib machinery. Now, the only modules imported at startup are _print, _encoding, _timers, and console, in order to provide public global APIs. I measured the 15% speedup with `perf stat -r 10 -B`. I also used Meson's measurements of the test suite to see a noticeable effect: for example, running the CommandLine test (which starts many instances of GJS) goes goes from 5.4 to 4.9 seconds. The cost of importing these modules is instead paid at the first time they're used. This assumes that it's nearly zero cost to import the modules a second time, because they're cached. In addition, this should make debugging easier because you don't get a big log spew of importing GLib if your script doesn't import GLib.
-rw-r--r--modules/esm/_encoding/encoding.js5
-rw-r--r--modules/esm/_timers.js23
-rw-r--r--modules/esm/console.js12
3 files changed, 17 insertions, 23 deletions
diff --git a/modules/esm/_encoding/encoding.js b/modules/esm/_encoding/encoding.js
index 41261b96..60cc0494 100644
--- a/modules/esm/_encoding/encoding.js
+++ b/modules/esm/_encoding/encoding.js
@@ -1,8 +1,6 @@
// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
// SPDX-FileCopyrightText: 2021 Evan Welsh <contact@evanwelsh.com>
-const Encoding = import.meta.importSync('_encodingNative');
-
import {getEncodingFromLabel} from './encodingMap.js';
class TextDecoder {
@@ -128,6 +126,7 @@ class TextDecoder {
input = new Uint8Array(buffer, byteOffset + 3, byteLength - 3);
}
+ const Encoding = import.meta.importSync('_encodingNative');
return Encoding.decode(input, this._internalEncoding, this.fatal);
}
}
@@ -142,11 +141,13 @@ class TextEncoder {
}
encode(input = '') {
+ const Encoding = import.meta.importSync('_encodingNative');
// The TextEncoder specification only allows for UTF-8 encoding.
return Encoding.encode(`${input}`, 'utf-8');
}
encodeInto(input = '', output = new Uint8Array()) {
+ const Encoding = import.meta.importSync('_encodingNative');
// The TextEncoder specification only allows for UTF-8 encoding.
return Encoding.encodeInto(`${input}`, output);
}
diff --git a/modules/esm/_timers.js b/modules/esm/_timers.js
index 94da6f8f..ca20b71d 100644
--- a/modules/esm/_timers.js
+++ b/modules/esm/_timers.js
@@ -6,11 +6,6 @@
// Note: implicit coercion with + is used to perform the ToNumber algorithm from
// the timers specification
-import GLib from 'gi://GLib';
-import GObject from 'gi://GObject';
-
-const PromiseNative = import.meta.importSync('_promiseNative');
-
/**
* @param {number} delay a number value (in milliseconds)
*/
@@ -52,9 +47,9 @@ function checkThis(thisArg) {
* @returns {GLib.Source}
*/
function createTimeoutSource(timeout, handler) {
- const source = GLib.timeout_source_new(timeout);
- source.set_priority(GLib.PRIORITY_DEFAULT);
- GObject.source_set_closure(source, handler);
+ const source = imports.gi.GLib.timeout_source_new(timeout);
+ source.set_priority(imports.gi.GLib.PRIORITY_DEFAULT);
+ imports.gi.GObject.source_set_closure(source, handler);
return source;
}
@@ -72,13 +67,13 @@ function setTimeout(callback, delay = 0, ...args) {
const boundCallback = callback.bind(globalThis, ...args);
const source = createTimeoutSource(delay, () => {
if (!timeouts.has(source))
- return GLib.SOURCE_REMOVE;
+ return imports.gi.GLib.SOURCE_REMOVE;
boundCallback();
releaseSource(source);
- PromiseNative.drainMicrotaskQueue();
+ import.meta.importSync('_promiseNative').drainMicrotaskQueue();
- return GLib.SOURCE_REMOVE;
+ return imports.gi.GLib.SOURCE_REMOVE;
});
addSource(source);
@@ -98,12 +93,12 @@ function setInterval(callback, delay = 0, ...args) {
const boundCallback = callback.bind(globalThis, ...args);
const source = createTimeoutSource(delay, () => {
if (!timeouts.has(source))
- return GLib.SOURCE_REMOVE;
+ return imports.gi.GLib.SOURCE_REMOVE;
boundCallback();
- PromiseNative.drainMicrotaskQueue();
+ import.meta.importSync('_promiseNative').drainMicrotaskQueue();
- return GLib.SOURCE_CONTINUE;
+ return imports.gi.GLib.SOURCE_CONTINUE;
});
addSource(source);
diff --git a/modules/esm/console.js b/modules/esm/console.js
index 74a34666..1532624d 100644
--- a/modules/esm/console.js
+++ b/modules/esm/console.js
@@ -1,9 +1,6 @@
// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
// SPDX-FileCopyrightText: 2021 Evan Welsh <contact@evanwelsh.com>
-import GLib from 'gi://GLib';
-import GjsPrivate from 'gi://GjsPrivate';
-
const DEFAULT_LOG_DOMAIN = 'Gjs-Console';
// A line-by-line implementation of https://console.spec.whatwg.org/.
@@ -112,7 +109,7 @@ class Console {
*/
clear() {
this.#groupIndentation = '';
- GjsPrivate.clear_terminal();
+ imports.gi.GjsPrivate.clear_terminal();
}
/**
@@ -268,7 +265,7 @@ class Console {
* @returns {void}
*/
time(label) {
- this.#timeLabels[label] = GLib.get_monotonic_time();
+ this.#timeLabels[label] = imports.gi.GLib.get_monotonic_time();
}
/**
@@ -288,7 +285,7 @@ class Console {
`No time log found for label: '${label}'.`,
]);
} else {
- const durationMs = (GLib.get_monotonic_time() - startTime) / 1000;
+ const durationMs = (imports.gi.GLib.get_monotonic_time() - startTime) / 1000;
const concat = `${label}: ${durationMs.toFixed(3)} ms`;
data.unshift(concat);
@@ -314,7 +311,7 @@ class Console {
} else {
delete this.#timeLabels[label];
- const durationMs = (GLib.get_monotonic_time() - startTime) / 1000;
+ const durationMs = (imports.gi.GLib.get_monotonic_time() - startTime) / 1000;
const concat = `${label}: ${durationMs.toFixed(3)} ms`;
this.#printer('timeEnd', [concat]);
@@ -500,6 +497,7 @@ class Console {
* @returns {void}
*/
#printer(logLevel, args, options) {
+ const GLib = imports.gi.GLib;
let severity;
switch (logLevel) {