summaryrefslogtreecommitdiff
path: root/lib/perf_hooks.js
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2018-01-10 09:42:10 -0800
committerJames M Snell <jasnell@gmail.com>2018-01-31 15:24:58 -0800
commit6bcd31f2f4a518f70646a72e7a6e42aa6ca90469 (patch)
tree39e2cb0645a6fd8b907a87a37c555fd86bdda26b /lib/perf_hooks.js
parent6e312c5cc7300e8c5d23301c970a1ac978950ff5 (diff)
downloadandroid-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/perf_hooks.js')
-rw-r--r--lib/perf_hooks.js49
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;
}