@@ -53,6 +53,9 @@ const kClearEntry = Symbol('clear-entry');
5353const kGetEntries = Symbol ( 'get-entries' ) ;
5454const kIndex = Symbol ( 'index' ) ;
5555const kMarks = Symbol ( 'marks' ) ;
56+ const kCount = Symbol ( 'count' ) ;
57+ const kMaxCount = Symbol ( 'max-count' ) ;
58+ const kDefaultMaxCount = 150 ;
5659
5760observerCounts [ NODE_PERFORMANCE_ENTRY_TYPE_MARK ] = 1 ;
5861observerCounts [ NODE_PERFORMANCE_ENTRY_TYPE_MEASURE ] = 1 ;
@@ -250,20 +253,32 @@ const nodeTiming = new PerformanceNodeTiming();
250253// Maintains a list of entries as a linked list stored in insertion order.
251254class PerformanceObserverEntryList {
252255 constructor ( ) {
253- Object . defineProperty ( this , kEntries , {
254- writable : true ,
255- enumerable : false ,
256- value : { }
256+ Object . defineProperties ( this , {
257+ [ kEntries ] : {
258+ writable : true ,
259+ enumerable : false ,
260+ value : { }
261+ } ,
262+ [ kCount ] : {
263+ writable : true ,
264+ enumerable : false ,
265+ value : 0
266+ }
257267 } ) ;
258268 L . init ( this [ kEntries ] ) ;
259269 }
260270
261271 [ kInsertEntry ] ( entry ) {
262272 const item = { entry } ;
263273 L . append ( this [ kEntries ] , item ) ;
274+ this [ kCount ] ++ ;
264275 this [ kIndexEntry ] ( item ) ;
265276 }
266277
278+ get length ( ) {
279+ return this [ kCount ] ;
280+ }
281+
267282 [ kIndexEntry ] ( entry ) {
268283 // Default implementation does nothing
269284 }
@@ -384,9 +399,22 @@ class Performance extends PerformanceObserverEntryList {
384399 this [ kIndex ] = {
385400 [ kMarks ] : new Set ( )
386401 } ;
402+ this [ kMaxCount ] = kDefaultMaxCount ;
387403 this [ kInsertEntry ] ( nodeTiming ) ;
388404 }
389405
406+ set maxEntries ( val ) {
407+ if ( typeof val !== 'number' || val >>> 0 !== val ) {
408+ const errors = lazyErrors ( ) ;
409+ throw new errors . TypeError ( 'ERR_INVALID_ARG_TYPE' , 'val' , 'number' ) ;
410+ }
411+ this [ kMaxCount ] = Math . max ( 1 , val >>> 0 ) ;
412+ }
413+
414+ get maxEntries ( ) {
415+ return this [ kMaxCount ] ;
416+ }
417+
390418 [ kIndexEntry ] ( item ) {
391419 const index = this [ kIndex ] ;
392420 const type = item . entry . entryType ;
@@ -397,6 +425,17 @@ class Performance extends PerformanceObserverEntryList {
397425 }
398426 const entry = item . entry ;
399427 L . append ( items , { entry, item } ) ;
428+ const count = this [ kCount ] ;
429+ if ( count > this [ kMaxCount ] ) {
430+ const text = count === 1 ? 'is 1 entry' : `are ${ count } entries` ;
431+ process . emitWarning ( 'Possible perf_hooks memory leak detected. ' +
432+ `There ${ text } in the ` +
433+ 'Performance Timeline. Use the clear methods ' +
434+ 'to remove entries that are no longer needed or ' +
435+ 'set performance.maxEntries equal to a higher ' +
436+ 'value (currently the maxEntries is ' +
437+ `${ this [ kMaxCount ] } ).` ) ;
438+ }
400439 }
401440
402441 [ kClearEntry ] ( type , name ) {
@@ -411,10 +450,12 @@ class Performance extends PerformanceObserverEntryList {
411450 if ( entry . name === `${ name } ` ) {
412451 L . remove ( item ) ; // remove from the index
413452 L . remove ( item . item ) ; // remove from the master
453+ this [ kCount ] -- ;
414454 }
415455 } else {
416456 L . remove ( item ) ; // remove from the index
417457 L . remove ( item . item ) ; // remove from the master
458+ this [ kCount ] -- ;
418459 }
419460 item = next ;
420461 }
0 commit comments