Skip to content
Draft
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- Reduce JSON serialization overhead by lowering the initial `JsonWriter` nesting stack size while preserving on-demand growth. ([#5591](https://github.com/getsentry/sentry-java/pull/5591))
- Reduce timestamp helper overhead by replacing unnecessary `Calendar` usage in `DateUtils` with direct `Date` creation. ([#5589](https://github.com/getsentry/sentry-java/pull/5589))
- Reduce Android startup overhead by using the default timezone directly on older devices or when no timezone info is available in the locale. ([#5587](https://github.com/getsentry/sentry-java/pull/5587))
- Reduce `SentryId` and `SpanId` allocation overhead by replacing their per-instance `LazyEvaluator` (and its lock) with a lightweight lazily-generated `String`. ([#5645](https://github.com/getsentry/sentry-java/pull/5645))

## 8.45.0

Expand Down
31 changes: 21 additions & 10 deletions sentry/src/main/java/io/sentry/SpanId.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,61 @@

import static io.sentry.util.StringUtils.PROPER_NIL_UUID;

import io.sentry.util.LazyEvaluator;
import java.io.IOException;
import java.util.Objects;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public final class SpanId implements JsonSerializable {
public static final SpanId EMPTY_ID =
new SpanId(PROPER_NIL_UUID.replace("-", "").substring(0, 16));

private final @NotNull LazyEvaluator<String> lazyValue;
private volatile @Nullable String value;

public SpanId(final @NotNull String value) {
Objects.requireNonNull(value, "value is required");
this.lazyValue = new LazyEvaluator<>(() -> value);
this.value = Objects.requireNonNull(value, "value is required");
}

public SpanId() {
this.lazyValue = new LazyEvaluator<>(SentryUUID::generateSpanId);
public SpanId() {}

private @NotNull String getValue() {
String result = value;
if (result == null) {
synchronized (this) {
result = value;
if (result == null) {
result = SentryUUID.generateSpanId();
value = result;
}
}
}
return result;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SpanId spanId = (SpanId) o;
return lazyValue.getValue().equals(spanId.lazyValue.getValue());
return getValue().equals(spanId.getValue());
}

@Override
public int hashCode() {
return lazyValue.getValue().hashCode();
return getValue().hashCode();
}

@Override
public String toString() {
return lazyValue.getValue();
return getValue();
}

// JsonElementSerializer

@Override
public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger)
throws IOException {
writer.value(lazyValue.getValue());
writer.value(getValue());
}

// JsonElementDeserializer
Expand Down
39 changes: 24 additions & 15 deletions sentry/src/main/java/io/sentry/protocol/SentryId.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import io.sentry.ObjectReader;
import io.sentry.ObjectWriter;
import io.sentry.SentryUUID;
import io.sentry.util.LazyEvaluator;
import io.sentry.util.StringUtils;
import io.sentry.util.UUIDStringUtils;
import java.io.IOException;
Expand All @@ -19,19 +18,15 @@ public final class SentryId implements JsonSerializable {
public static final SentryId EMPTY_ID =
new SentryId(StringUtils.PROPER_NIL_UUID.replace("-", ""));

private final @NotNull LazyEvaluator<String> lazyStringValue;
private volatile @Nullable String value;
private final @Nullable UUID uuid;

public SentryId() {
this((UUID) null);
}

public SentryId(@Nullable UUID uuid) {
if (uuid != null) {
this.lazyStringValue =
new LazyEvaluator<>(() -> normalize(UUIDStringUtils.toSentryIdString(uuid)));
} else {
this.lazyStringValue = new LazyEvaluator<>(SentryUUID::generateSentryId);
}
this.uuid = uuid;
}

public SentryId(final @NotNull String sentryIdString) {
Expand All @@ -42,29 +37,43 @@ public SentryId(final @NotNull String sentryIdString) {
+ "or 36 characters long (completed UUID). Received: "
+ sentryIdString);
}
if (normalized.length() == 36) {
this.lazyStringValue = new LazyEvaluator<>(() -> normalize(normalized));
} else {
this.lazyStringValue = new LazyEvaluator<>(() -> normalized);
this.uuid = null;
this.value = normalized.length() == 36 ? normalize(normalized) : normalized;
}

private @NotNull String getValue() {
String result = value;
if (result == null) {
synchronized (this) {
result = value;
if (result == null) {
result =
uuid != null
? normalize(UUIDStringUtils.toSentryIdString(uuid))
: SentryUUID.generateSentryId();
value = result;
}
}
}
return result;
}

@Override
public String toString() {
return lazyStringValue.getValue();
return getValue();
}

@Override
public boolean equals(final @Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SentryId sentryId = (SentryId) o;
return lazyStringValue.getValue().equals(sentryId.lazyStringValue.getValue());
return getValue().equals(sentryId.getValue());
}

@Override
public int hashCode() {
return lazyStringValue.getValue().hashCode();
return getValue().hashCode();
}

private @NotNull String normalize(@NotNull String uuidString) {
Expand Down
Loading