diff options
author | James M Snell <jasnell@gmail.com> | 2018-01-10 09:42:10 -0800 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2018-01-31 15:24:58 -0800 |
commit | 6bcd31f2f4a518f70646a72e7a6e42aa6ca90469 (patch) | |
tree | 39e2cb0645a6fd8b907a87a37c555fd86bdda26b /lib | |
parent | 6e312c5cc7300e8c5d23301c970a1ac978950ff5 (diff) | |
download | android-node-v8-6bcd31f2f4a518f70646a72e7a6e42aa6ca90469.tar.gz android-node-v8-6bcd31f2f4a518f70646a72e7a6e42aa6ca90469.tar.bz2 android-node-v8-6bcd31f2f4a518f70646a72e7a6e42aa6ca90469.zip |
perf_hooks: add warning when too many entries in the timeline
PR-URL: https://github.com/nodejs/node/pull/18087
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/perf_hooks.js | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/lib/perf_hooks.js b/lib/perf_hooks.js index 15256a63c0..6fd6e4a6b7 100644 --- a/lib/perf_hooks.js +++ b/lib/perf_hooks.js @@ -53,6 +53,9 @@ const kClearEntry = Symbol('clear-entry'); const kGetEntries = Symbol('get-entries'); const kIndex = Symbol('index'); const kMarks = Symbol('marks'); +const kCount = Symbol('count'); +const kMaxCount = Symbol('max-count'); +const kDefaultMaxCount = 150; observerCounts[NODE_PERFORMANCE_ENTRY_TYPE_MARK] = 1; observerCounts[NODE_PERFORMANCE_ENTRY_TYPE_MEASURE] = 1; @@ -250,10 +253,17 @@ const nodeTiming = new PerformanceNodeTiming(); // Maintains a list of entries as a linked list stored in insertion order. class PerformanceObserverEntryList { constructor() { - Object.defineProperty(this, kEntries, { - writable: true, - enumerable: false, - value: {} + Object.defineProperties(this, { + [kEntries]: { + writable: true, + enumerable: false, + value: {} + }, + [kCount]: { + writable: true, + enumerable: false, + value: 0 + } }); L.init(this[kEntries]); } @@ -261,9 +271,14 @@ class PerformanceObserverEntryList { [kInsertEntry](entry) { const item = { entry }; L.append(this[kEntries], item); + this[kCount]++; this[kIndexEntry](item); } + get length() { + return this[kCount]; + } + [kIndexEntry](entry) { // Default implementation does nothing } @@ -384,9 +399,22 @@ class Performance extends PerformanceObserverEntryList { this[kIndex] = { [kMarks]: new Set() }; + this[kMaxCount] = kDefaultMaxCount; this[kInsertEntry](nodeTiming); } + set maxEntries(val) { + if (typeof val !== 'number' || val >>> 0 !== val) { + const errors = lazyErrors(); + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'val', 'number'); + } + this[kMaxCount] = Math.max(1, val >>> 0); + } + + get maxEntries() { + return this[kMaxCount]; + } + [kIndexEntry](item) { const index = this[kIndex]; const type = item.entry.entryType; @@ -397,6 +425,17 @@ class Performance extends PerformanceObserverEntryList { } const entry = item.entry; L.append(items, { entry, item }); + const count = this[kCount]; + if (count > this[kMaxCount]) { + const text = count === 1 ? 'is 1 entry' : `are ${count} entries`; + process.emitWarning('Possible perf_hooks memory leak detected. ' + + `There ${text} in the ` + + 'Performance Timeline. Use the clear methods ' + + 'to remove entries that are no longer needed or ' + + 'set performance.maxEntries equal to a higher ' + + 'value (currently the maxEntries is ' + + `${this[kMaxCount]}).`); + } } [kClearEntry](type, name) { @@ -411,10 +450,12 @@ class Performance extends PerformanceObserverEntryList { if (entry.name === `${name}`) { L.remove(item); // remove from the index L.remove(item.item); // remove from the master + this[kCount]--; } } else { L.remove(item); // remove from the index L.remove(item.item); // remove from the master + this[kCount]--; } item = next; } |