From 037aa9786d9a980834857bda14d17e0b2132b323 Mon Sep 17 00:00:00 2001 From: Zaid Abdulla Date: Sat, 8 Sep 2018 18:46:10 -0700 Subject: [PATCH] Optimize PathSet Performance has not been tested but generally avoiding sparse arrays should result in better performance. --- lib/path-set.js | 68 ++++++++++++++++++++++++------------------------- lib/session.js | 14 +++++----- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/lib/path-set.js b/lib/path-set.js index 7525e95..aa773be 100644 --- a/lib/path-set.js +++ b/lib/path-set.js @@ -33,22 +33,28 @@ class PathSet { if (p) return p; - if (!this.lengthIndex[path.length]) - this.lengthIndex[path.length] = new Set(); + while (this.lengthIndex.length <= path.length) { + this.lengthIndex.push(new Set()); + this.fragmentIndex.push(new Map()); + } - this.lengthIndex[path.length].add(path); + const lengthIndex = this.lengthIndex[path.length]; + lengthIndex.add(path); let wildcard = 0; for (let i = 0; i < path.length; ++i) { const fragment = path[i]; if (fragment === "*") wildcard = wildcard | (1 << i); - if (!this.fragmentIndex[i]) this.fragmentIndex[i] = {}; + const fragmentIndex = this.fragmentIndex[i]; - if (!this.fragmentIndex[i][fragment]) - this.fragmentIndex[i][fragment] = new Set(); + let fragmentIndexSet = fragmentIndex.get(fragment); + if (!fragmentIndexSet) { + fragmentIndexSet = new Set(); + fragmentIndex.set(fragment, fragmentIndexSet); + } - this.fragmentIndex[i][fragment].add(path); + fragmentIndexSet.add(path); } if (path.wildcard == null) { @@ -60,27 +66,26 @@ class PathSet { } get(pattern) { - if (!this.lengthIndex[pattern.length]) return null; + const lengthIndex = this.lengthIndex[pattern.length]; + if (!lengthIndex || !lengthIndex.size) return null; - if (this.lengthIndex[pattern.length].has(pattern)) return pattern; + if (lengthIndex.has(pattern)) return pattern; - const sets = []; - - sets.push(this.lengthIndex[pattern.length]); + const sets = [lengthIndex]; for (let i = 0; i < pattern.length; ++i) { - if (!this.fragmentIndex[i]) return null; + const fragmentIndex = this.fragmentIndex[i]; + if (!fragmentIndex || !fragmentIndex.size) return null; const fragment = pattern[i]; - if (!this.fragmentIndex[i][fragment]) return null; + const fragmentIndexSet = fragmentIndex.get(fragment); + if (!fragmentIndexSet) return null; - sets.push(this.fragmentIndex[i][fragment]); + sets.push(fragmentIndexSet); } - sets.sort((a, b) => { - return a.size - b.size; - }); + sets.sort((a, b) => a.size - b.size); const smallestSet = sets.shift(); for (let path of smallestSet) { @@ -107,7 +112,8 @@ class PathSet { if (!groups[0].length) return res; for (let i = 0; i < pattern.length; ++i) { - if (!this.fragmentIndex[i]) return res; + const fragmentIndex = this.fragmentIndex[i]; + if (!fragmentIndex) return res; const fragment = pattern[i]; @@ -115,27 +121,22 @@ class PathSet { const g = []; - if (this.fragmentIndex[i][fragment]) - g.push(this.fragmentIndex[i][fragment]); + const s = fragmentIndex.get(fragment); + if (s) g.push(s); - if (fragment !== "*" && superset && this.fragmentIndex[i]["*"]) - g.push(this.fragmentIndex[i]["*"]); + if (fragment !== "*" && superset && fragmentIndex.has("*")) + g.push(fragmentIndex.get("*")); if (!g.length) return res; groups.push(g); } - groups.sort((a, b) => { - return ( - a.reduce((prev, cur) => { - return prev + cur.size; - }, 0) - - b.reduce((prev, cur) => { - return prev + cur.size; - }, 0) - ); - }); + groups.sort( + (a, b) => + a.reduce((prev, cur) => prev + cur.size, 0) - + b.reduce((prev, cur) => prev + cur.size, 0) + ); const smallestGroup = groups.shift(); for (const set of smallestGroup) { @@ -157,7 +158,6 @@ class PathSet { if (path) res.push(path); } } - return res; } } diff --git a/lib/session.js b/lib/session.js index 1484968..a67c48a 100644 --- a/lib/session.js +++ b/lib/session.js @@ -1808,12 +1808,11 @@ function processDeclarations( const syncState = sessionContext.syncState; const root = sessionContext.deviceData.paths.add([]); - const paths = sessionContext.deviceData.paths.find([], false, true, 99); - paths.sort((a, b) => { - if (a.wildcard === b.wildcard) return a.length - b.length; - - return a.wildcard - b.wildcard; - }); + const paths = deviceData.paths.find([], false, true, 99); + paths.sort( + (a, b) => + a.wildcard === b.wildcard ? a.length - b.length : a.wildcard - b.wildcard + ); const virtualParameterDeclarations = []; @@ -1885,7 +1884,8 @@ function processDeclarations( leafIsObject = currentAttributes.object ? currentAttributes.object[1] : null; - if (leafIsObject === 0) + // Possible V8 bug causes null === 0 + if (leafIsObject != null && leafIsObject === 0) leafTimestamp = Math.max(leafTimestamp, currentAttributes.object[0]); } else { leafTimestamp = Math.max(leafTimestamp, currentTimestamp);