From 28687bca75d1e2a09458ddbb3b61cb6bcf67284a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 29 Jul 2014 20:33:43 -0700 Subject: [PATCH] Optimize CMap.prototype.forEach(). This change avoids the element stringification caused by for..in for the vast majority of CMaps. When loading the PDF from issue #4580, this change reduces peak RSS from ~650 to ~600 MiB, and improves overall speed by ~20%, from 902 ms to 713 ms. Other CMap-heavy documents will also see improvements. --- src/core/cmap.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/core/cmap.js b/src/core/cmap.js index 771f3ffd32596..446b11e42056b 100644 --- a/src/core/cmap.js +++ b/src/core/cmap.js @@ -242,9 +242,24 @@ var CMap = (function CMapClosure() { }, forEach: function(callback) { + // Most maps have fewer than 65536 entries, and for those we use normal + // array iteration. But really sparse tables are possible -- e.g. with + // indices in the *billions*. For such tables we use for..in, which isn't + // ideal because it stringifies the indices for all present elements, but + // it does avoid iterating over every undefined entry. var map = this._map; - for (var key in this._map) { - callback(key, map[key]); + var length = map.length; + var i; + if (length <= 0x10000) { + for (i = 0; i < length; i++) { + if (map[i] !== undefined) { + callback(i, map[i]); + } + } + } else { + for (i in this._map) { + callback(i, map[i]); + } } },