99  ArrayPrototypePush, 
1010  ArrayPrototypeSlice, 
1111  ArrayPrototypeSort, 
12+   Error, 
1213  ObjectDefineProperties, 
1314  ObjectFreeze, 
1415  ObjectKeys, 
@@ -32,6 +33,7 @@ const {
3233const  { 
3334  InternalPerformanceEntry, 
3435  isPerformanceEntry, 
36+   kBufferNext, 
3537}  =  require ( 'internal/perf/performance_entry' ) ; 
3638
3739const  { 
@@ -83,12 +85,17 @@ const kSupportedEntryTypes = ObjectFreeze([
8385  'mark' , 
8486  'measure' , 
8587] ) ; 
86- const  kTimelineEntryTypes  =  ObjectFreeze ( [ 
87-   'mark' , 
88-   'measure' , 
89- ] ) ; 
9088
91- const  kPerformanceEntryBuffer  =  new  SafeMap ( ) ; 
89+ // Performance timeline entry Buffers 
90+ const  markEntryBuffer  =  createBuffer ( ) ; 
91+ const  measureEntryBuffer  =  createBuffer ( ) ; 
92+ const  kMaxPerformanceEntryBuffers  =  1e6 ; 
93+ const  kClearPerformanceEntryBuffers  =  ObjectFreeze ( { 
94+   'mark' : 'performance.clearMarks' , 
95+   'measure' : 'performance.clearMeasures' , 
96+ } ) ; 
97+ const  kWarnedEntryTypes  =  new  SafeMap ( ) ; 
98+ 
9299const  kObservers  =  new  SafeSet ( ) ; 
93100const  kPending  =  new  SafeSet ( ) ; 
94101let  isPending  =  false ; 
@@ -238,7 +245,7 @@ class PerformanceObserver {
238245      maybeIncrementObserverCount ( type ) ; 
239246      if  ( buffered )  { 
240247        const  entries  =  filterBufferMapByNameAndType ( undefined ,  type ) ; 
241-         this [ kBuffer ] . push ( ...entries ) ; 
248+         ArrayPrototypePush ( this [ kBuffer ] ,   ...entries ) ; 
242249        kPending . add ( this ) ; 
243250        if  ( kPending . size ) 
244251          queuePending ( ) ; 
@@ -307,50 +314,97 @@ function enqueue(entry) {
307314  } 
308315
309316  const  entryType  =  entry . entryType ; 
310-   if  ( ! kTimelineEntryTypes . includes ( entryType ) )  { 
317+   let  buffer ; 
318+   if  ( entryType  ===  'mark' )  { 
319+     buffer  =  markEntryBuffer ; 
320+   }  else  if  ( entryType  ===  'measure' )  { 
321+     buffer  =  measureEntryBuffer ; 
322+   }  else  { 
311323    return ; 
312324  } 
313-   const  buffer  =  getEntryBuffer ( entryType ) ; 
314-   buffer . push ( entry ) ; 
325+ 
326+   const  count  =  buffer . count  +  1 ; 
327+   buffer . count  =  count ; 
328+   if  ( count  ===  1 )  { 
329+     buffer . head  =  entry ; 
330+     buffer . tail  =  entry ; 
331+     return ; 
332+   } 
333+   buffer . tail [ kBufferNext ]  =  entry ; 
334+   buffer . tail  =  entry ; 
335+ 
336+   if  ( count  >  kMaxPerformanceEntryBuffers  && 
337+     ! kWarnedEntryTypes . has ( entryType ) )  { 
338+     kWarnedEntryTypes . set ( entryType ,  true ) ; 
339+     // No error code for this since it is a Warning 
340+     // eslint-disable-next-line no-restricted-syntax 
341+     const  w  =  new  Error ( 'Possible perf_hooks memory leak detected. '  + 
342+                         `${ count }   ${ entryType }   entries added to the global `  + 
343+                         'performance entry buffer. Use '  + 
344+                         `${ kClearPerformanceEntryBuffers [ entryType ] }   to `  + 
345+                         'clear the buffer.' ) ; 
346+     w . name  =  'MaxPerformanceEntryBufferExceededWarning' ; 
347+     w . entryType  =  entryType ; 
348+     w . count  =  count ; 
349+     process . emitWarning ( w ) ; 
350+   } 
315351} 
316352
317353function  clearEntriesFromBuffer ( type ,  name )  { 
354+   let  buffer ; 
355+   if  ( type  ===  'mark' )  { 
356+     buffer  =  markEntryBuffer ; 
357+   }  else  if  ( type  ===  'measure' )  { 
358+     buffer  =  measureEntryBuffer ; 
359+   }  else  { 
360+     return ; 
361+   } 
318362  if  ( name  ===  undefined )  { 
319-     kPerformanceEntryBuffer . delete ( type ) ; 
363+     resetBuffer ( buffer ) ; 
320364    return ; 
321365  } 
322-   let  buffer  =  getEntryBuffer ( type ) ; 
323-   buffer  =  ArrayPrototypeFilter ( 
324-     buffer , 
325-     ( entry )  =>  entry . name  !==  name ) ; 
326-   kPerformanceEntryBuffer . set ( type ,  buffer ) ; 
327- } 
328366
329- function  getEntryBuffer ( type )  { 
330-   let  buffer  =  kPerformanceEntryBuffer . get ( type ) ; 
331-   if  ( buffer  ===  undefined )  { 
332-     buffer  =  [ ] ; 
333-     kPerformanceEntryBuffer . set ( type ,  buffer ) ; 
367+   let  head  =  null ; 
368+   let  tail  =  null ; 
369+   for  ( let  entry  =  buffer . head ;  entry  !==  null ;  entry  =  entry [ kBufferNext ] )  { 
370+     if  ( entry . name  !==  name )  { 
371+       head  =  head  ??  entry ; 
372+       tail  =  entry ; 
373+       continue ; 
374+     } 
375+     if  ( tail  ===  null )  { 
376+       continue ; 
377+     } 
378+     tail [ kBufferNext ]  =  entry [ kBufferNext ] ; 
334379  } 
335-   return  buffer ; 
380+   buffer . head  =  head ; 
381+   buffer . tail  =  tail ; 
336382} 
337383
338384function  filterBufferMapByNameAndType ( name ,  type )  { 
339385  let  bufferList ; 
340-   if  ( type  !==  undefined )  { 
341-     bufferList  =  kPerformanceEntryBuffer . get ( type )  ??  [ ] ; 
386+   if  ( type  ===  'mark' )  { 
387+     bufferList  =  [ markEntryBuffer ] ; 
388+   }  else  if  ( type  ===  'measure' )  { 
389+     bufferList  =  [ measureEntryBuffer ] ; 
390+   }  else  if  ( type  !==  undefined )  { 
391+     // Unrecognized type; 
392+     return  [ ] ; 
342393  }  else  { 
343-     bufferList  =  ArrayFrom ( kPerformanceEntryBuffer . values ( ) ) ; 
394+     bufferList  =  [ markEntryBuffer ,   measureEntryBuffer ] ; 
344395  } 
345396  return  ArrayPrototypeFlatMap ( bufferList , 
346397                               ( buffer )  =>  filterBufferByName ( buffer ,  name ) ) ; 
347398} 
348399
349400function  filterBufferByName ( buffer ,  name )  { 
350-   if  ( name  ===  undefined )  { 
351-     return  buffer ; 
401+   const  arr  =  [ ] ; 
402+   for  ( let  entry  =  buffer . head ;  entry  !==  null ;  entry  =  entry [ kBufferNext ] )  { 
403+     if  ( name  ===  undefined  ||  entry . name  ===  name )  { 
404+       arr . push ( entry ) ; 
405+     } 
352406  } 
353-   return  ArrayPrototypeFilter ( buffer ,   ( it )   =>   it . name   ===   name ) ; 
407+   return  arr ; 
354408} 
355409
356410function  observerCallback ( name ,  type ,  startTime ,  duration ,  details )  { 
@@ -398,6 +452,20 @@ function hasObserver(type) {
398452  return  observerCounts [ observerType ]  >  0 ; 
399453} 
400454
455+ function  createBuffer ( )  { 
456+   return  { 
457+     head : null , 
458+     tail : null , 
459+     count : 0 , 
460+   } ; 
461+ } 
462+ 
463+ function  resetBuffer ( buffer )  { 
464+   buffer . head  =  null ; 
465+   buffer . tail  =  null ; 
466+   buffer . count  =  0 ; 
467+ } 
468+ 
401469module . exports  =  { 
402470  PerformanceObserver, 
403471  enqueue, 
0 commit comments