Skip to content

Commit 69edcfa

Browse files
authored
Merge pull request #5601 from getsentry/perf/sdk-overhead-reduction-reflection-serializer
perf(core): [SDK Overhead Reduction 10] Lazily create reflection JSON serializer
2 parents 307853f + 6a7e061 commit 69edcfa

4 files changed

Lines changed: 36 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Internal
66

7+
- Reduce JSON serialization overhead by creating the reflection serializer only when unknown-object fallback serialization is needed. ([#5601](https://github.com/getsentry/sentry-java/pull/5601))
78
- Reduce JSON serialization overhead by allocating reflection cycle-tracking state only when reflection serialization is used. ([#5600](https://github.com/getsentry/sentry-java/pull/5600))
89
- Reduce context serialization overhead by sorting key snapshots with arrays instead of temporary lists. ([#5599](https://github.com/getsentry/sentry-java/pull/5599))
910
- Reduce breadcrumb allocation overhead by creating the `Breadcrumb` data map only when data is added. ([#5598](https://github.com/getsentry/sentry-java/pull/5598))

sentry/api/sentry.api

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,6 @@ public final class io/sentry/JsonObjectReader : io/sentry/ObjectReader {
13121312

13131313
public final class io/sentry/JsonObjectSerializer {
13141314
public static final field OBJECT_PLACEHOLDER Ljava/lang/String;
1315-
public final field jsonReflectionObjectSerializer Lio/sentry/JsonReflectionObjectSerializer;
13161315
public fun <init> (I)V
13171316
public fun serialize (Lio/sentry/ObjectWriter;Lio/sentry/ILogger;Ljava/lang/Object;)V
13181317
}

sentry/src/main/java/io/sentry/JsonObjectSerializer.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ public final class JsonObjectSerializer {
2828

2929
public static final String OBJECT_PLACEHOLDER = "[OBJECT]";
3030

31-
public final JsonReflectionObjectSerializer jsonReflectionObjectSerializer;
31+
private final int maxDepth;
32+
private @Nullable JsonReflectionObjectSerializer jsonReflectionObjectSerializer;
3233

3334
public JsonObjectSerializer(int maxDepth) {
34-
jsonReflectionObjectSerializer = new JsonReflectionObjectSerializer(maxDepth);
35+
this.maxDepth = maxDepth;
3536
}
3637

3738
public void serialize(
@@ -127,7 +128,7 @@ public void serialize(
127128
writer.value(object.toString());
128129
} else {
129130
try {
130-
Object serializableObject = jsonReflectionObjectSerializer.serialize(object, logger);
131+
Object serializableObject = getJsonReflectionObjectSerializer().serialize(object, logger);
131132
serialize(writer, logger, serializableObject);
132133
} catch (Exception exception) {
133134
logger.log(SentryLevel.ERROR, "Failed serializing unknown object.", exception);
@@ -138,6 +139,13 @@ public void serialize(
138139

139140
// Helper
140141

142+
private @NotNull JsonReflectionObjectSerializer getJsonReflectionObjectSerializer() {
143+
if (jsonReflectionObjectSerializer == null) {
144+
jsonReflectionObjectSerializer = new JsonReflectionObjectSerializer(maxDepth);
145+
}
146+
return jsonReflectionObjectSerializer;
147+
}
148+
141149
private void serializeDate(
142150
@NotNull ObjectWriter writer, @NotNull ILogger logger, @NotNull Date date)
143151
throws IOException {

sentry/src/test/java/io/sentry/JsonObjectSerializerTest.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import java.util.Locale
77
import java.util.TimeZone
88
import java.util.concurrent.atomic.AtomicBoolean
99
import java.util.concurrent.atomic.AtomicIntegerArray
10+
import kotlin.test.assertNotNull
11+
import kotlin.test.assertNull
1012
import org.junit.Test
1113
import org.mockito.kotlin.inOrder
1214
import org.mockito.kotlin.mock
@@ -192,6 +194,21 @@ internal class JsonObjectSerializerTest {
192194
verify(jsonSerializable).serialize(fixture.writer, fixture.logger)
193195
}
194196

197+
@Test
198+
fun `serialize json serializable does not create reflection serializer`() {
199+
val serializer = fixture.getSUT()
200+
val jsonSerializable: JsonSerializable = mock()
201+
serializer.serialize(fixture.writer, fixture.logger, jsonSerializable)
202+
assertNull(serializer.reflectionObjectSerializer)
203+
}
204+
205+
@Test
206+
fun `serialize unknown object creates reflection serializer`() {
207+
val serializer = fixture.getSUT()
208+
serializer.serialize(fixture.writer, fixture.logger, object {})
209+
assertNotNull(serializer.reflectionObjectSerializer)
210+
}
211+
195212
@Test
196213
fun `serialize unknown object without data`() {
197214
val value = object {}
@@ -355,3 +372,10 @@ internal class JsonObjectSerializerTest {
355372
data class ClassWithEnumProperty(val enumProperty: DataCategory)
356373

357374
data class ClassWithLocaleProperty(val localeProperty: Locale)
375+
376+
private val JsonObjectSerializer.reflectionObjectSerializer: JsonReflectionObjectSerializer?
377+
get() {
378+
val field = JsonObjectSerializer::class.java.getDeclaredField("jsonReflectionObjectSerializer")
379+
field.isAccessible = true
380+
return field.get(this) as JsonReflectionObjectSerializer?
381+
}

0 commit comments

Comments
 (0)