From a5bce0cf0fefe1e6334c2c7e993f5aa1cf11f71f Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Thu, 10 Oct 2019 16:24:41 +0200 Subject: [PATCH] Avoid using ConcurrentLinkedDeque.size It is a linear operation that can take a long time when many spans are involved. Using an atomic integer to track the size allows it to be a constant operation. --- .../java/datadog/opentracing/PendingTrace.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java b/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java index 619e6390d7f..eeb97718341 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java @@ -43,6 +43,9 @@ public class PendingTrace extends ConcurrentLinkedDeque { Collections.newSetFromMap(new ConcurrentHashMap, Boolean>()); private final AtomicInteger pendingReferenceCount = new AtomicInteger(0); + + // We must maintain a separate count because ConcurrentLinkedDeque.size() is a linear operation. + private final AtomicInteger completedSpanCount = new AtomicInteger(0); /** * During a trace there are cases where the root span must be accessed (e.g. priority sampling and * trace-search tags). @@ -209,6 +212,7 @@ private void expireReference() { final DDSpan span = it.next(); if (span != rootSpan) { partialTrace.add(span); + completedSpanCount.decrementAndGet(); it.remove(); } } @@ -254,6 +258,17 @@ public synchronized boolean clean() { return count > 0; } + @Override + public void addFirst(final DDSpan span) { + super.addFirst(span); + completedSpanCount.incrementAndGet(); + } + + @Override + public int size() { + return completedSpanCount.get(); + } + private void addPendingTrace() { final SpanCleaner cleaner = SPAN_CLEANER.get(); if (cleaner != null) {