From c7f02d2c8ee1d1c7cbb26c9600c910ab3b33603f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 21 Jul 2014 22:19:31 -0700 Subject: [PATCH] Minimize memory usage of font-related arrays. This patch replaces some vanilla arrays with typed arrays, and avoids some array copying. It reduces the peak RSS when viewing http://www.dynacw.co.jp/Portals/3/fontsamplepdf/sample_4942546800828.pdf from ~940 MiB to ~750 MiB, and reduces its load time from 83 to 76 ms. --- src/core/fonts.js | 46 ++++++++++++++++++++++++++++++++++------------ src/shared/util.js | 2 +- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/core/fonts.js b/src/core/fonts.js index daf6257d4..c274841c3 100644 --- a/src/core/fonts.js +++ b/src/core/fonts.js @@ -2433,17 +2433,43 @@ var Font = (function FontClosure() { // length var length = data.length; - // Per spec tables must be 4-bytes align so add padding as needed - while (data.length & 3) { - data.push(0x00); + // Per spec tables must be 4-bytes align so add padding as needed. + var paddedLength = length; + while (paddedLength & 3) { + paddedLength++; } + var i; + var padding = paddedLength - length; + if (padding !== 0) { + // Padding is required. |data| can be an Array, Uint8Array, or + // Uint16Array. In the latter two cases we need to create slightly larger + // typed arrays and copy the old contents in. Fortunately that's not a + // common case. + var data2; + if (data instanceof Array) { + for (i = 0; i < padding; i++) { + data.push(0); + } + } else if (data instanceof Uint8Array) { + data2 = new Uint8Array(paddedLength); + data2.set(data); + data = data2; + } else if (data instanceof Uint16Array) { + data2 = new Uint16Array(paddedLength); + data2.set(data); + data = data2; + } else { + error('bad array kind in createTableEntry'); + } + } + while (file.virtualOffset & 3) { file.virtualOffset++; } // checksum var checksum = 0, n = data.length; - for (var i = 0; i < n; i += 4) { + for (i = 0; i < n; i += 4) { checksum = (checksum + int32(data[i], data[i + 1], data[i + 2], data[i + 3])) | 0; } @@ -2452,6 +2478,8 @@ var Font = (function FontClosure() { string32(offset) + string32(length)); file.file += tableEntry; file.virtualOffset += data.length; + + return data; } function isTrueTypeFile(file) { @@ -4066,13 +4094,7 @@ var Font = (function FontClosure() { // rewrite the tables but tweak offsets for (i = 0; i < numTables; i++) { table = tables[tablesNames[i]]; - var data = []; - - tableData = table.data; - for (var j = 0, jj = tableData.length; j < jj; j++) { - data.push(tableData[j]); - } - createTableEntry(ttf, table.tag, data); + table.data = createTableEntry(ttf, table.tag, table.data); } // Add the table datas @@ -4254,7 +4276,7 @@ var Font = (function FontClosure() { var field; for (field in fields) { - createTableEntry(otf, field, fields[field]); + fields[field] = createTableEntry(otf, field, fields[field]); } for (field in fields) { var table = fields[field]; diff --git a/src/shared/util.js b/src/shared/util.js index 78e4f59f2..2684485fa 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -436,7 +436,7 @@ function bytesToString(bytes) { function stringToArray(str) { var length = str.length; - var array = []; + var array = new Uint16Array(length); for (var i = 0; i < length; ++i) { array[i] = str.charCodeAt(i); }