Skip to content

Commit fcb1331

Browse files
Cache feature resolution at the namespace level instead of individual objects to avoid any O(n^2) scaling
1 parent db3c953 commit fcb1331

File tree

5 files changed

+27
-18
lines changed

5 files changed

+27
-18
lines changed

index.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,9 @@ export abstract class NamespaceBase extends ReflectionObject {
750750
/** Nested objects by name. */
751751
public nested?: { [k: string]: ReflectionObject };
752752

753+
/** Whether or not objects contained in this namespace need feature resolution. */
754+
protected _needsRecursiveFeatureResolution: boolean;
755+
753756
/** Nested objects of this namespace as an array for iteration. */
754757
public readonly nestedArray: ReflectionObject[];
755758

@@ -909,9 +912,6 @@ export abstract class ReflectionObject {
909912
/** Resolved Features. */
910913
public _features: object;
911914

912-
/** Whether or not features have been resolved. */
913-
public _featuresResolved: boolean;
914-
915915
/** Parent namespace. */
916916
public parent: (Namespace|null);
917917

src/namespace.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,23 @@ function Namespace(name, options) {
117117
* @private
118118
*/
119119
this._lookupCache = {};
120+
121+
/**
122+
* Whether or not objects contained in this namespace need feature resolution.
123+
* @type {boolean}
124+
* @protected
125+
*/
126+
this._needsRecursiveFeatureResolution = true;
120127
}
121128

122129
function clearCache(namespace) {
123130
namespace._nestedArray = null;
124131
namespace._lookupCache = {};
125132

126133
// Also clear parent caches, since they include nested lookups.
127-
var parent = namespace.parent;
128-
while(parent) {
134+
var parent = namespace;
135+
while(parent = parent.parent) {
129136
parent._lookupCache = {};
130-
parent = parent.parent;
131137
}
132138
return namespace;
133139
}
@@ -266,6 +272,14 @@ Namespace.prototype.add = function add(object) {
266272
}
267273
}
268274

275+
this._needsRecursiveFeatureResolution = true;
276+
277+
// Also clear parent caches, since they need to recurse down.
278+
var parent = this;
279+
while(parent = parent.parent) {
280+
parent._needsRecursiveFeatureResolution = true;
281+
}
282+
269283
object.onAdd(this);
270284
return clearCache(this);
271285
};
@@ -341,6 +355,9 @@ Namespace.prototype.resolveAll = function resolveAll() {
341355
* @override
342356
*/
343357
Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
358+
if (!this._needsRecursiveFeatureResolution) return this;
359+
this._needsRecursiveFeatureResolution = false;
360+
344361
edition = this._edition || edition;
345362

346363
ReflectionObject.prototype._resolveFeaturesRecursive.call(this, edition);

src/object.js

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,6 @@ function ReflectionObject(name, options) {
6767
*/
6868
this._features = {};
6969

70-
/**
71-
* Whether or not features have been resolved.
72-
* @type {boolean}
73-
*/
74-
this._featuresResolved = false;
75-
7670
/**
7771
* Parent namespace.
7872
* @type {Namespace|null}
@@ -198,10 +192,6 @@ ReflectionObject.prototype._resolveFeaturesRecursive = function _resolveFeatures
198192
* @returns {undefined}
199193
*/
200194
ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition) {
201-
if (this._featuresResolved) {
202-
return;
203-
}
204-
205195
var defaults = {};
206196

207197
/* istanbul ignore if */
@@ -225,7 +215,6 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition)
225215
throw new Error("Unknown edition: " + edition);
226216
}
227217
this._features = Object.assign(defaults, protoFeatures || {});
228-
this._featuresResolved = true;
229218
return;
230219
}
231220

@@ -247,7 +236,6 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition)
247236
// Sister fields should have the same features as their extensions.
248237
this.extensionField._features = this._features;
249238
}
250-
this._featuresResolved = true;
251239
};
252240

253241
/**

src/service.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ Service.prototype.resolveAll = function resolveAll() {
121121
* @override
122122
*/
123123
Service.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
124+
if (!this._needsRecursiveFeatureResolution) return this;
125+
124126
edition = this._edition || edition;
125127

126128
Namespace.prototype._resolveFeaturesRecursive.call(this, edition);

src/type.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ Type.prototype.resolveAll = function resolveAll() {
317317
* @override
318318
*/
319319
Type.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
320+
if (!this._needsRecursiveFeatureResolution) return this;
321+
320322
edition = this._edition || edition;
321323

322324
Namespace.prototype._resolveFeaturesRecursive.call(this, edition);

0 commit comments

Comments
 (0)