Skip to content

Commit 2053575

Browse files
adinauerclaude
andcommitted
perf(core): Remove redundant event map copies
Avoid creating temporary maps when applying scope and options tags or scope extras. The event setters already copy these maps, so this preserves snapshot semantics while reducing allocation overhead. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 8b5f3c4 commit 2053575

5 files changed

Lines changed: 59 additions & 7 deletions

File tree

sentry/src/main/java/io/sentry/MainEventProcessor.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import java.io.Closeable;
1212
import java.io.IOException;
1313
import java.util.ArrayList;
14-
import java.util.HashMap;
1514
import java.util.List;
1615
import java.util.Map;
1716
import org.jetbrains.annotations.ApiStatus;
@@ -191,7 +190,7 @@ private void setSdk(final @NotNull SentryBaseEvent event) {
191190

192191
private void setTags(final @NotNull SentryBaseEvent event) {
193192
if (event.getTags() == null) {
194-
event.setTags(new HashMap<>(options.getTags()));
193+
event.setTags(options.getTags());
195194
} else {
196195
for (Map.Entry<String, String> item : options.getTags().entrySet()) {
197196
if (!event.getTags().containsKey(item.getKey())) {

sentry/src/main/java/io/sentry/SentryClient.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.util.Collection;
2828
import java.util.Collections;
2929
import java.util.Comparator;
30-
import java.util.HashMap;
3130
import java.util.List;
3231
import java.util.Map;
3332
import org.jetbrains.annotations.ApiStatus;
@@ -1423,7 +1422,7 @@ public void captureBatchedMetricsEvents(final @NotNull SentryMetricsEvents metri
14231422
event.setUser(scope.getUser());
14241423
}
14251424
if (event.getTags() == null) {
1426-
event.setTags(new HashMap<>(scope.getTags()));
1425+
event.setTags(scope.getTags());
14271426
} else {
14281427
for (Map.Entry<String, String> item : scope.getTags().entrySet()) {
14291428
if (!event.getTags().containsKey(item.getKey())) {
@@ -1481,7 +1480,7 @@ public void captureBatchedMetricsEvents(final @NotNull SentryMetricsEvents metri
14811480
replayEvent.setUser(scope.getUser());
14821481
}
14831482
if (replayEvent.getTags() == null) {
1484-
replayEvent.setTags(new HashMap<>(scope.getTags()));
1483+
replayEvent.setTags(scope.getTags());
14851484
} else {
14861485
for (Map.Entry<String, String> item : scope.getTags().entrySet()) {
14871486
if (!replayEvent.getTags().containsKey(item.getKey())) {
@@ -1521,7 +1520,7 @@ public void captureBatchedMetricsEvents(final @NotNull SentryMetricsEvents metri
15211520
sentryBaseEvent.setUser(scope.getUser());
15221521
}
15231522
if (sentryBaseEvent.getTags() == null) {
1524-
sentryBaseEvent.setTags(new HashMap<>(scope.getTags()));
1523+
sentryBaseEvent.setTags(scope.getTags());
15251524
} else {
15261525
for (Map.Entry<String, String> item : scope.getTags().entrySet()) {
15271526
if (!sentryBaseEvent.getTags().containsKey(item.getKey())) {
@@ -1535,7 +1534,7 @@ public void captureBatchedMetricsEvents(final @NotNull SentryMetricsEvents metri
15351534
sortBreadcrumbsByDate(sentryBaseEvent, scope.getBreadcrumbs());
15361535
}
15371536
if (sentryBaseEvent.getExtras() == null) {
1538-
sentryBaseEvent.setExtras(new HashMap<>(scope.getExtras()));
1537+
sentryBaseEvent.setExtras(scope.getExtras());
15391538
} else {
15401539
for (Map.Entry<String, Object> item : scope.getExtras().entrySet()) {
15411540
if (!sentryBaseEvent.getExtras().containsKey(item.getKey())) {

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,19 @@ class MainEventProcessorTest {
358358
}
359359
}
360360

361+
@Test
362+
fun `options tags are copied when applied to event`() {
363+
val sut = fixture.getSut(tags = mapOf("tag1" to "value1"))
364+
val event = SentryEvent()
365+
366+
sut.process(event, Hint())
367+
val eventTags = event.tags!!
368+
369+
fixture.sentryOptions.setTag("tag2", "value2")
370+
371+
assertFalse(eventTags.containsKey("tag2"))
372+
}
373+
361374
@Test
362375
fun `when event has a tag set with the same name as SentryOptions tags, the tag value from the event is retained`() {
363376
val sut = fixture.getSut(tags = mapOf("tag1" to "value1", "tag2" to "value2"))

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,24 @@ class SentryClientTest {
534534
assertNotNull(event.request) { assertEquals("post", it.method) }
535535
}
536536

537+
@Test
538+
fun `when captureEvent applies scope tags and extras, event map containers are copied`() {
539+
val event = SentryEvent()
540+
val scope = createScope()
541+
542+
val sut = fixture.getSut()
543+
544+
sut.captureEvent(event, scope)
545+
val eventTags = event.tags!!
546+
val eventExtras = event.extras!!
547+
548+
scope.setTag("newTag", "newValue")
549+
scope.setExtra("newExtra", "newValue")
550+
551+
assertFalse(eventTags.containsKey("newTag"))
552+
assertFalse(eventExtras.containsKey("newExtra"))
553+
}
554+
537555
@Test
538556
fun `when breadcrumbs are not empty, sort them out by date`() {
539557
val b1 = Breadcrumb(DateUtils.getDateTime("2020-03-27T08:52:58.001Z"))

sentry/src/test/java/io/sentry/protocol/SentryBaseEventSerializationTest.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import io.sentry.SentryBaseEvent
99
import io.sentry.SentryIntegrationPackageStorage
1010
import io.sentry.vendor.gson.stream.JsonToken
1111
import kotlin.test.assertEquals
12+
import kotlin.test.assertFalse
1213
import org.junit.After
1314
import org.junit.Before
1415
import org.junit.Test
@@ -102,4 +103,26 @@ class SentryBaseEventSerializationTest {
102103

103104
assertEquals(expectedJson, actualJson)
104105
}
106+
107+
@Test
108+
fun `setTags copies source map`() {
109+
val source = mutableMapOf("a" to "1")
110+
val sut = Sut()
111+
112+
sut.tags = source
113+
source["b"] = "2"
114+
115+
assertFalse(sut.tags!!.containsKey("b"))
116+
}
117+
118+
@Test
119+
fun `setExtras copies source map`() {
120+
val source = mutableMapOf<String, Any>("a" to "1")
121+
val sut = Sut()
122+
123+
sut.setExtras(source)
124+
source["b"] = "2"
125+
126+
assertFalse(sut.extras!!.containsKey("b"))
127+
}
105128
}

0 commit comments

Comments
 (0)