From 5e045bcdbabc79c1577dd97bb99448af4bc8b903 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sun, 26 May 2019 14:20:31 +0200 Subject: [PATCH] Ensure that the `Cmd`/`Name`/`Ref` caches are cleared when running other `cleanup` code The purpose of these caches is to reduce peak memory usage, by only ever having *a single* instance of a particular object. However, as-is these caches are never cleared and they will thus remain until the worker is destroyed. This could very well have a negative effect on total memory usage, particularly for large/long documents, hence it seems to make sense to clear out these caches together with various other ones. --- src/core/obj.js | 5 +++-- src/core/primitives.js | 29 ++++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/core/obj.js b/src/core/obj.js index 5784172aa..786e3eb56 100644 --- a/src/core/obj.js +++ b/src/core/obj.js @@ -20,8 +20,8 @@ import { warn } from '../shared/util'; import { - Dict, isCmd, isDict, isName, isRef, isRefsEqual, isStream, Ref, RefSet, - RefSetCache + clearPrimitiveCaches, Dict, isCmd, isDict, isName, isRef, isRefsEqual, + isStream, Ref, RefSet, RefSetCache } from './primitives'; import { Lexer, Parser } from './parser'; import { @@ -662,6 +662,7 @@ class Catalog { } cleanup() { + clearPrimitiveCaches(); this.pageKidsCountCache.clear(); const promises = []; diff --git a/src/core/primitives.js b/src/core/primitives.js index 7074676a8..59b256b88 100644 --- a/src/core/primitives.js +++ b/src/core/primitives.js @@ -19,36 +19,44 @@ import { assert } from '../shared/util'; var EOF = {}; var Name = (function NameClosure() { + let nameCache = Object.create(null); + function Name(name) { this.name = name; } Name.prototype = {}; - var nameCache = Object.create(null); - Name.get = function Name_get(name) { var nameValue = nameCache[name]; return (nameValue ? nameValue : (nameCache[name] = new Name(name))); }; + Name._clearCache = function() { + nameCache = Object.create(null); + }; + return Name; })(); var Cmd = (function CmdClosure() { + let cmdCache = Object.create(null); + function Cmd(cmd) { this.cmd = cmd; } Cmd.prototype = {}; - var cmdCache = Object.create(null); - Cmd.get = function Cmd_get(cmd) { var cmdValue = cmdCache[cmd]; return (cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd))); }; + Cmd._clearCache = function() { + cmdCache = Object.create(null); + }; + return Cmd; })(); @@ -178,7 +186,7 @@ var Dict = (function DictClosure() { })(); var Ref = (function RefClosure() { - const refCache = Object.create(null); + let refCache = Object.create(null); function Ref(num, gen) { this.num = num; @@ -202,6 +210,10 @@ var Ref = (function RefClosure() { return (refValue ? refValue : (refCache[key] = new Ref(num, gen))); }; + Ref._clearCache = function() { + refCache = Object.create(null); + }; + return Ref; })(); @@ -299,8 +311,15 @@ function isStream(v) { return typeof v === 'object' && v !== null && v.getBytes !== undefined; } +function clearPrimitiveCaches() { + Cmd._clearCache(); + Name._clearCache(); + Ref._clearCache(); +} + export { EOF, + clearPrimitiveCaches, Cmd, Dict, Name,