@@ -8,6 +8,7 @@ const send = require('./send')
88const { getStackFromCallFrames } = require ( './state' )
99const { ackEmitting, ackError } = require ( './status' )
1010const { parentThreadId } = require ( './config' )
11+ const { MAX_SNAPSHOTS_PER_SECOND_GLOBALLY } = require ( './defaults' )
1112const log = require ( '../../log' )
1213const { version } = require ( '../../../../../package.json' )
1314
@@ -24,11 +25,14 @@ const expression = `
2425const threadId = parentThreadId === 0 ? `pid:${ process . pid } ` : `pid:${ process . pid } ;tid:${ parentThreadId } `
2526const threadName = parentThreadId === 0 ? 'MainThread' : `WorkerThread:${ parentThreadId } `
2627
28+ const oneSecondNs = BigInt ( 1_000_000_000 )
29+ let globalSnapshotSamplingRateWindowStart = BigInt ( 0 )
30+ let snapshotsSampledWithinTheLastSecond = 0
31+
2732// WARNING: The code above the line `await session.post('Debugger.resume')` is highly optimized. Please edit with care!
2833session . on ( 'Debugger.paused' , async ( { params } ) => {
2934 const start = process . hrtime . bigint ( )
3035
31- let captureSnapshotForProbe = null
3236 let maxReferenceDepth , maxCollectionSize , maxFieldCount , maxLength
3337
3438 // V8 doesn't allow seting more than one breakpoint at a specific location, however, it's possible to set two
@@ -38,6 +42,9 @@ session.on('Debugger.paused', async ({ params }) => {
3842 let sampled = false
3943 const length = params . hitBreakpoints . length
4044 let probes = new Array ( length )
45+ // TODO: Consider reusing this array between pauses and only recreating it if it needs to grow
46+ const snapshotProbeIndex = new Uint8Array ( length ) // TODO: Is a limit of 256 probes ever going to be a problem?
47+ let numberOfProbesWithSnapshots = 0
4148 for ( let i = 0 ; i < length ; i ++ ) {
4249 const id = params . hitBreakpoints [ i ]
4350 const probe = breakpoints . get ( id )
@@ -46,17 +53,28 @@ session.on('Debugger.paused', async ({ params }) => {
4653 continue
4754 }
4855
49- sampled = true
50- probe . lastCaptureNs = start
51-
5256 if ( probe . captureSnapshot === true ) {
53- captureSnapshotForProbe = probe
57+ // This algorithm to calculate number of sampled snapshots within the last second is not perfect, as it's not a
58+ // sliding window. But it's quick and easy :)
59+ if ( i === 0 && start - globalSnapshotSamplingRateWindowStart > oneSecondNs ) {
60+ snapshotsSampledWithinTheLastSecond = 1
61+ globalSnapshotSamplingRateWindowStart = start
62+ } else if ( snapshotsSampledWithinTheLastSecond >= MAX_SNAPSHOTS_PER_SECOND_GLOBALLY ) {
63+ continue
64+ } else {
65+ snapshotsSampledWithinTheLastSecond ++
66+ }
67+
68+ snapshotProbeIndex [ numberOfProbesWithSnapshots ++ ] = i
5469 maxReferenceDepth = highestOrUndefined ( probe . capture . maxReferenceDepth , maxReferenceDepth )
5570 maxCollectionSize = highestOrUndefined ( probe . capture . maxCollectionSize , maxCollectionSize )
5671 maxFieldCount = highestOrUndefined ( probe . capture . maxFieldCount , maxFieldCount )
5772 maxLength = highestOrUndefined ( probe . capture . maxLength , maxLength )
5873 }
5974
75+ sampled = true
76+ probe . lastCaptureNs = start
77+
6078 probes [ i ] = probe
6179 }
6280
@@ -68,17 +86,17 @@ session.on('Debugger.paused', async ({ params }) => {
6886 const dd = await getDD ( params . callFrames [ 0 ] . callFrameId )
6987
7088 let processLocalState
71- if ( captureSnapshotForProbe !== null ) {
89+ if ( numberOfProbesWithSnapshots !== 0 ) {
7290 try {
7391 // TODO: Create unique states for each affected probe based on that probes unique `capture` settings (DEBUG-2863)
7492 processLocalState = await getLocalStateForCallFrame (
7593 params . callFrames [ 0 ] ,
7694 { maxReferenceDepth, maxCollectionSize, maxFieldCount, maxLength }
7795 )
7896 } catch ( err ) {
79- // TODO: This error is not tied to a specific probe, but to all probes with `captureSnapshot: true`.
80- // However, in 99,99% of cases, there will be just a single probe, so I guess this simplification is ok ?
81- ackError ( err , captureSnapshotForProbe ) // TODO: Ok to continue after sending ackError?
97+ for ( let i = 0 ; i < numberOfProbesWithSnapshots ; i ++ ) {
98+ ackError ( err , probes [ snapshotProbeIndex [ i ] ] ) // TODO: Ok to continue after sending ackError ?
99+ }
82100 }
83101 }
84102
0 commit comments