Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,26 @@ public final class TraceMapperV0_4 implements TraceMapper {
? new GenerationalUtf8Cache(Config.get().getTagValueUtf8CacheSize())
: null;

// Controls how often the UTF8 caches are recalibrated. The caches adapt to shifts in tag-value
// cardinality over a timescale much longer than a single span, so recalibrating periodically
// rather than per-span preserves their effectiveness without paying recalibrate()'s O(cacheSize)
// cost on every span. Must be a power of two (see the mask in shouldRecalibrate).
static final long RECALIBRATE_SPAN_INTERVAL = 512;

// True when at least one cache exists. static-final so the JIT can fold the whole recalibrate
// block away when both caches are off.
private static final boolean RECALIBRATE = (TAG_CACHE != null || VALUE_CACHE != null);

// Advanced by the single serializer thread. The value is a recalibration cadence, not an exact
// count, so a plain counter suffices -- no atomic/volatile needed; a benign race would at most
// nudge when recalibrate fires.
private static long spanCounter;

/** True once every {@link #RECALIBRATE_SPAN_INTERVAL} spans; advances the span counter. */
static boolean shouldRecalibrate() {
return RECALIBRATE && (++spanCounter & (RECALIBRATE_SPAN_INTERVAL - 1)) == 0;
}

private final int size;
private boolean firstSpanWritten;

Expand Down Expand Up @@ -68,8 +88,10 @@ MetaWriter forSpan(boolean firstInTrace, boolean lastInTrace, boolean firstInPay

@Override
public void accept(Metadata metadata) {
if (TAG_CACHE != null) TAG_CACHE.recalibrate();
if (VALUE_CACHE != null) VALUE_CACHE.recalibrate();
if (shouldRecalibrate()) {
if (TAG_CACHE != null) TAG_CACHE.recalibrate();
if (VALUE_CACHE != null) VALUE_CACHE.recalibrate();
}

TagMap tags = metadata.getTags();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package datadog.trace.common.writer.ddagent;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

class TraceMapperV0_4RecalibrateTest {

@Test
void recalibratesOncePerInterval() {
final long interval = TraceMapperV0_4.RECALIBRATE_SPAN_INTERVAL;

// shouldRecalibrate() advances a shared counter, so assert a property that holds regardless of
// the starting value: any window of 2*interval consecutive spans crosses exactly two interval
// boundaries.
int recalibrations = 0;
for (long i = 0; i < 2 * interval; i++) {
if (TraceMapperV0_4.shouldRecalibrate()) {
recalibrations++;
}
}
assertEquals(2, recalibrations);
}

@Test
void intervalIsAPowerOfTwo() {
// shouldRecalibrate uses a bit mask, which is only correct for a power-of-two interval.
final long interval = TraceMapperV0_4.RECALIBRATE_SPAN_INTERVAL;
assertEquals(0, interval & (interval - 1), "RECALIBRATE_SPAN_INTERVAL must be a power of two");
}
}