diff --git a/website/guide/performance.html b/website/guide/performance.html index 1200e80a..d3ba3e5c 100644 --- a/website/guide/performance.html +++ b/website/guide/performance.html @@ -144,6 +144,23 @@ slower.

them up from the global object or other objects +

Enumeration

+ +

When an object is enumerated, with either the for-in statement +or Object.keys(), Duktape first traverses the target object and its +prototype chain and forms an internal enumeration object, which contains all +the enumeration keys as strings. +In particular, all array indices (or character indices in case of +strings) are converted and interned into string values before enumeration and +they remain interned until the enumeration completes. This can be memory +intensive especially if large arrays or strings are enumerated.

+ +

Note, however, that iterating a string or an array with for-in +and expecting the array elements or string indices to be enumerated in an +ascending order is non-portable. Such behavior, while guaranteed by many +implementations including Duktape, is not guaranteed by the Ecmascript +standard.

+

Function features

Ecmascript has a lot of features which make function entry and execution @@ -273,6 +290,41 @@ for (var i = 0; i <= 1000; i++) { } +

Iterate arrays with explicit indices, not a "for-in"

+ +

Because the internal enumeration object contains all (used) array +indices converted to string values, avoid for-in enumeration +of at least large arrays. As a concrete example, consider:

+
+var a = [];
+for (var i = 0; i < 1000000; i++) {
+  a[i] = i;
+}
+for (var i in a) {
+  // Before this loop is first entered, a million strings ("0", "1",
+  // ..., "999999") will be interned.
+  print(i, a[i]);
+}
+// The million strings become garbage collectable only here.
+
+ +

The internal enumeration object created in this example would contain a +million interned string keys for "0", "1", ..., "999999". All of these keys +would remain reachable for the entire duration of the enumeration. The +following code would perform much better (and would be more portable, as it +makes no assumptions on enumeration order):

+ +
+var a = [];
+for (var i = 0; i < 1000000; i++) {
+  a[i] = i;
+}
+var n = a.length;
+for (var i = 0; i < n; i++) {
+  print(i, a[i]);
+}
+
+

Minimize top-level global/eval code

Identifier accesses in global and eval code always use slow path instructions