Leverage a private object monitor lock instead of synchronizing on "this". (#612)

* Leverage a ReentrantReadWriteLock instead of synchronizing on this.

* remove lazy init of events

* just use a basic synchronized block

* appease checkstyle

* small tweaks, post-rebase

* fix synchronized after rebase
This commit is contained in:
Jason Plumb 2019-10-28 10:52:14 -07:00 committed by Bogdan Drutu
parent db0812c50b
commit 8aeada6b54
1 changed files with 46 additions and 58 deletions

View File

@ -47,14 +47,13 @@ import javax.annotation.concurrent.ThreadSafe;
/** Implementation for the {@link Span} class that records trace events. */ /** Implementation for the {@link Span} class that records trace events. */
@ThreadSafe @ThreadSafe
final class RecordEventsReadableSpan implements ReadableSpan, Span { final class RecordEventsReadableSpan implements ReadableSpan, Span {
private static final Logger logger = Logger.getLogger(Tracer.class.getName()); private static final Logger logger = Logger.getLogger(Tracer.class.getName());
// Contains the identifiers associated with this Span. // Contains the identifiers associated with this Span.
private final SpanContext context; private final SpanContext context;
// The parent SpanId of this span. Invalid if this is a root span. // The parent SpanId of this span. Invalid if this is a root span.
private final SpanId parentSpanId; private final SpanId parentSpanId;
// Active trace configs when the Span was created.
private final TraceConfig traceConfig;
// Handler called when the span starts and ends. // Handler called when the span starts and ends.
private final SpanProcessor spanProcessor; private final SpanProcessor spanProcessor;
// The displayed name of the span. // The displayed name of the span.
@ -63,7 +62,10 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
// Number of links recorded. // Number of links recorded.
private final int totalRecordedLinks; private final int totalRecordedLinks;
@GuardedBy("this") // Lock used to internally guard the mutable state of this instance
private final Object lock = new Object();
@GuardedBy("lock")
private String name; private String name;
// The kind of the span. // The kind of the span.
private final Kind kind; private final Kind kind;
@ -77,28 +79,26 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
// The start time of the span. // The start time of the span.
private final long startNanoTime; private final long startNanoTime;
// Set of recorded attributes. DO NOT CALL any other method that changes the ordering of events. // Set of recorded attributes. DO NOT CALL any other method that changes the ordering of events.
@GuardedBy("this") @GuardedBy("lock")
@Nullable private final AttributesWithCapacity attributes;
private AttributesWithCapacity attributes;
// List of recorded events. // List of recorded events.
@GuardedBy("this") @GuardedBy("lock")
@Nullable private final EvictingQueue<TimedEvent> events;
private EvictingQueue<TimedEvent> events;
// Number of events recorded. // Number of events recorded.
@GuardedBy("this") @GuardedBy("lock")
private int totalRecordedEvents = 0; private int totalRecordedEvents = 0;
// The number of children. // The number of children.
@GuardedBy("this") @GuardedBy("lock")
private int numberOfChildren; private int numberOfChildren;
// The status of the span. // The status of the span.
@GuardedBy("this") @GuardedBy("lock")
@Nullable @Nullable
private Status status; private Status status;
// The end time of the span. // The end time of the span.
@GuardedBy("this") @GuardedBy("lock")
private long endNanoTime; private long endNanoTime;
// True if the span is ended. // True if the span is ended.
@GuardedBy("this") @GuardedBy("lock")
private boolean hasBeenEnded; private boolean hasBeenEnded;
/** /**
@ -202,7 +202,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
*/ */
@Override @Override
public String getName() { public String getName() {
synchronized (this) { synchronized (lock) {
return name; return name;
} }
} }
@ -214,7 +214,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
* @return the end nano time. * @return the end nano time.
*/ */
private long getEndNanoTime() { private long getEndNanoTime() {
synchronized (this) { synchronized (lock) {
return getEndNanoTimeInternal(); return getEndNanoTimeInternal();
} }
} }
@ -226,7 +226,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
*/ */
@VisibleForTesting @VisibleForTesting
Status getStatus() { Status getStatus() {
synchronized (this) { synchronized (lock) {
return getStatusWithDefault(); return getStatusWithDefault();
} }
} }
@ -237,8 +237,8 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
* @return The TimedEvents for this span. * @return The TimedEvents for this span.
*/ */
private List<TimedEvent> getTimedEvents() { private List<TimedEvent> getTimedEvents() {
synchronized (this) { synchronized (lock) {
return events == null ? Collections.<TimedEvent>emptyList() : new ArrayList<>(events); return new ArrayList<>(events);
} }
} }
@ -249,7 +249,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
*/ */
@VisibleForTesting @VisibleForTesting
List<Link> getLinks() { List<Link> getLinks() {
synchronized (this) { synchronized (lock) {
if (links == null) { if (links == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -274,8 +274,8 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
*/ */
@VisibleForTesting @VisibleForTesting
Map<String, AttributeValue> getAttributes() { Map<String, AttributeValue> getAttributes() {
synchronized (this) { synchronized (lock) {
return Collections.unmodifiableMap(getInitializedAttributes()); return Collections.unmodifiableMap(attributes);
} }
} }
@ -286,16 +286,18 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
* @return the latency of the {@code Span} in nanos. * @return the latency of the {@code Span} in nanos.
*/ */
long getLatencyNs() { long getLatencyNs() {
synchronized (this) { synchronized (lock) {
return getEndNanoTimeInternal() - startNanoTime; return getEndNanoTimeInternal() - startNanoTime;
} }
} }
// Use getEndNanoTimeInternal to avoid over-locking. // Use getEndNanoTimeInternal to avoid over-locking.
@GuardedBy("this") @GuardedBy("lock")
private long getEndNanoTimeInternal() { private long getEndNanoTimeInternal() {
synchronized (lock) {
return hasBeenEnded ? endNanoTime : clock.nanoTime(); return hasBeenEnded ? endNanoTime : clock.nanoTime();
} }
}
/** /**
* Returns the kind of this {@code Span}. * Returns the kind of this {@code Span}.
@ -351,12 +353,12 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
public void setAttribute(String key, AttributeValue value) { public void setAttribute(String key, AttributeValue value) {
Preconditions.checkNotNull(key, "key"); Preconditions.checkNotNull(key, "key");
Preconditions.checkNotNull(value, "value"); Preconditions.checkNotNull(value, "value");
synchronized (this) { synchronized (lock) {
if (hasBeenEnded) { if (hasBeenEnded) {
logger.log(Level.FINE, "Calling setAttribute() on an ended Span."); logger.log(Level.FINE, "Calling setAttribute() on an ended Span.");
return; return;
} }
getInitializedAttributes().putAttribute(key, value); attributes.putAttribute(key, value);
} }
} }
@ -391,12 +393,12 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
} }
private void addTimedEvent(TimedEvent timedEvent) { private void addTimedEvent(TimedEvent timedEvent) {
synchronized (this) { synchronized (lock) {
if (hasBeenEnded) { if (hasBeenEnded) {
logger.log(Level.FINE, "Calling addEvent() on an ended Span."); logger.log(Level.FINE, "Calling addEvent() on an ended Span.");
return; return;
} }
getInitializedEvents().add(timedEvent); events.add(timedEvent);
totalRecordedEvents++; totalRecordedEvents++;
} }
} }
@ -404,7 +406,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
@Override @Override
public void setStatus(Status status) { public void setStatus(Status status) {
Preconditions.checkNotNull(status, "status"); Preconditions.checkNotNull(status, "status");
synchronized (this) { synchronized (lock) {
if (hasBeenEnded) { if (hasBeenEnded) {
logger.log(Level.FINE, "Calling setStatus() on an ended Span."); logger.log(Level.FINE, "Calling setStatus() on an ended Span.");
return; return;
@ -416,7 +418,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
@Override @Override
public void updateName(String name) { public void updateName(String name) {
Preconditions.checkNotNull(name, "name"); Preconditions.checkNotNull(name, "name");
synchronized (this) { synchronized (lock) {
if (hasBeenEnded) { if (hasBeenEnded) {
logger.log(Level.FINE, "Calling updateName() on an ended Span."); logger.log(Level.FINE, "Calling updateName() on an ended Span.");
return; return;
@ -438,7 +440,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
} }
private void endInternal() { private void endInternal() {
synchronized (this) { synchronized (lock) {
if (hasBeenEnded) { if (hasBeenEnded) {
logger.log(Level.FINE, "Calling end() on an ended Span."); logger.log(Level.FINE, "Calling end() on an ended Span.");
return; return;
@ -460,7 +462,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
} }
void addChild() { void addChild() {
synchronized (this) { synchronized (lock) {
if (hasBeenEnded) { if (hasBeenEnded) {
logger.log(Level.FINE, "Calling end() on an ended Span."); logger.log(Level.FINE, "Calling end() on an ended Span.");
return; return;
@ -469,30 +471,17 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
} }
} }
@GuardedBy("this") @GuardedBy("lock")
private AttributesWithCapacity getInitializedAttributes() {
if (attributes == null) {
attributes = new AttributesWithCapacity(traceConfig.getMaxNumberOfAttributes());
}
return attributes;
}
@GuardedBy("this")
private EvictingQueue<TimedEvent> getInitializedEvents() {
if (events == null) {
events = EvictingQueue.create(traceConfig.getMaxNumberOfEvents());
}
return events;
}
@GuardedBy("this")
private Status getStatusWithDefault() { private Status getStatusWithDefault() {
synchronized (lock) {
return status == null ? Status.OK : status; return status == null ? Status.OK : status;
} }
}
// A map implementation with a fixed capacity that drops events when the map gets full. Eviction // A map implementation with a fixed capacity that drops events when the map gets full. Eviction
// is based on the access order. // is based on the access order.
static final class AttributesWithCapacity extends LinkedHashMap<String, AttributeValue> { static final class AttributesWithCapacity extends LinkedHashMap<String, AttributeValue> {
private final long capacity; private final long capacity;
private int totalRecordedAttributes = 0; private int totalRecordedAttributes = 0;
// Here because -Werror complains about this: [serial] serializable class AttributesWithCapacity // Here because -Werror complains about this: [serial] serializable class AttributesWithCapacity
@ -545,7 +534,6 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
this.totalRecordedLinks = totalRecordedLinks; this.totalRecordedLinks = totalRecordedLinks;
this.name = name; this.name = name;
this.kind = kind; this.kind = kind;
this.traceConfig = traceConfig;
this.spanProcessor = spanProcessor; this.spanProcessor = spanProcessor;
this.clock = clock; this.clock = clock;
this.resource = resource; this.resource = resource;
@ -554,15 +542,15 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
this.timestampConverter = this.timestampConverter =
timestampConverter != null ? timestampConverter : TimestampConverter.now(clock); timestampConverter != null ? timestampConverter : TimestampConverter.now(clock);
startNanoTime = clock.nanoTime(); startNanoTime = clock.nanoTime();
if (!attributes.isEmpty()) { this.attributes = new AttributesWithCapacity(traceConfig.getMaxNumberOfAttributes());
getInitializedAttributes().putAll(attributes); this.attributes.putAll(attributes);
} this.events = EvictingQueue.create(traceConfig.getMaxNumberOfEvents());
} }
@SuppressWarnings("NoFinalizer") @SuppressWarnings("NoFinalizer")
@Override @Override
protected void finalize() throws Throwable { protected void finalize() throws Throwable {
synchronized (this) { synchronized (lock) {
if (!hasBeenEnded) { if (!hasBeenEnded) {
logger.log(Level.SEVERE, "Span " + name + " is GC'ed without being ended."); logger.log(Level.SEVERE, "Span " + name + " is GC'ed without being ended.");
} }
@ -582,14 +570,14 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
@VisibleForTesting @VisibleForTesting
int getNumberOfChildren() { int getNumberOfChildren() {
synchronized (this) { synchronized (lock) {
return numberOfChildren; return numberOfChildren;
} }
} }
@VisibleForTesting @VisibleForTesting
int getTotalRecordedEvents() { int getTotalRecordedEvents() {
synchronized (this) { synchronized (lock) {
return totalRecordedEvents; return totalRecordedEvents;
} }
} }