@@ -234,7 +234,7 @@ PublishState onPublish(final DDSpan span) {
234234 if (span == rootSpan ) {
235235 tracer .onRootSpanPublished (rootSpan );
236236 }
237- return decrementRefAndMaybeWrite (span == rootSpan );
237+ return decrementRefAndMaybeWrite (span == rootSpan , true );
238238 }
239239
240240 @ Override
@@ -265,10 +265,10 @@ public void registerContinuation(final AgentScope.Continuation continuation) {
265265
266266 @ Override
267267 public void removeContinuation (final AgentScope .Continuation continuation ) {
268- decrementRefAndMaybeWrite (false );
268+ decrementRefAndMaybeWrite (false , false );
269269 }
270270
271- private PublishState decrementRefAndMaybeWrite (boolean isRootSpan ) {
271+ private PublishState decrementRefAndMaybeWrite (boolean isRootSpan , boolean addedSpan ) {
272272 final int count = PENDING_REFERENCE_COUNT .decrementAndGet (this );
273273 if (strictTraceWrites && count < 0 ) {
274274 throw new IllegalStateException ("Pending reference count " + count + " is negative" );
@@ -283,8 +283,19 @@ private PublishState decrementRefAndMaybeWrite(boolean isRootSpan) {
283283 // Finished root with pending work ... delay write
284284 pendingTraceBuffer .enqueue (this );
285285 return PublishState .ROOT_BUFFERED ;
286- } else if (partialFlushMinSpans > 0 && size () >= partialFlushMinSpans ) {
286+ } else if (addedSpan && partialFlushMinSpans > 0 && size () >= partialFlushMinSpans ) {
287287 // Trace is getting too big, write anything completed.
288+
289+ // DQH - We only trigger a partial flush, when a span has just been added
290+ // This prevents a bunch of threads which are only performing scope/context operations
291+ // from all fighting to perform the partialFlush after the threshold is crossed.
292+
293+ // This is an important optimization for virtual threads where a continuation might
294+ // be created even though no span is created. In that situation, virtual threads
295+ // can end up fighting to perform the partialFlush. And even trying to perform a
296+ // partialFlush requires taking the PendingTrace lock which can lead to unmounting
297+ // the virtual thread from its carrier thread.
298+
288299 partialFlush ();
289300 return PublishState .PARTIAL_FLUSH ;
290301 } else if (rootSpanWritten ) {
0 commit comments