Skip to content

Commit 5fd3d03

Browse files
authored
Merge branch 'perf/sdk-overhead-reduction' into perf/sdk-overhead-reduction-breadcrumb-lazy-data
2 parents 3d2fab5 + 9766b74 commit 5fd3d03

7 files changed

Lines changed: 54 additions & 15 deletions

File tree

CHANGELOG.md

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

55
### Internal
66

7+
<<<<<<< perf/sdk-overhead-reduction-breadcrumb-lazy-data
78
- Reduce breadcrumb allocation overhead by creating the `Breadcrumb` data map only when data is added. ([#5598](https://github.com/getsentry/sentry-java/pull/5598))
9+
=======
10+
- 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))
11+
- Reduce timestamp helper overhead by replacing unnecessary `Calendar` usage in `DateUtils` with direct `Date` creation. ([#5589](https://github.com/getsentry/sentry-java/pull/5589))
12+
- 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))
13+
>>>>>>> perf/sdk-overhead-reduction
814

915
## 8.45.0
1016

sentry-android-core/src/main/java/io/sentry/android/core/DeviceInfoUtil.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,14 +257,19 @@ private void setDeviceIO(
257257
@SuppressWarnings("NewApi")
258258
@NotNull
259259
private TimeZone getTimeZone() {
260-
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.N) {
260+
// Only use the costly Calendar API on Android 13+ (API Level 33+) when the locale contains a
261+
// Unicode timezone extension (for example "en-US-u-tz-usnyc"), because Calendar honors that
262+
// extension. For all other cases, use the process default timezone directly for performance.
263+
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.TIRAMISU) {
261264
LocaleList locales = context.getResources().getConfiguration().getLocales();
262265
if (!locales.isEmpty()) {
263266
Locale locale = locales.get(0);
264-
return Calendar.getInstance(locale).getTimeZone();
267+
if (locale.getUnicodeLocaleType("tz") != null) {
268+
return Calendar.getInstance(locale).getTimeZone();
269+
}
265270
}
266271
}
267-
return Calendar.getInstance().getTimeZone();
272+
return TimeZone.getDefault();
268273
}
269274

270275
@SuppressWarnings("JdkObsolete")

sentry-android-core/src/test/java/io/sentry/android/core/DeviceInfoUtilTest.kt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,22 @@ package io.sentry.android.core
22

33
import android.content.Context
44
import android.content.Intent
5+
import android.content.res.Configuration
56
import android.os.BatteryManager
7+
import android.os.Build
8+
import android.os.LocaleList
69
import androidx.test.core.app.ApplicationProvider
710
import androidx.test.ext.junit.runners.AndroidJUnit4
811
import io.sentry.android.core.internal.util.CpuInfoUtils
12+
import java.util.Locale
13+
import java.util.TimeZone
914
import kotlin.test.BeforeTest
1015
import kotlin.test.Test
1116
import kotlin.test.assertEquals
1217
import kotlin.test.assertNotNull
1318
import kotlin.test.assertNull
1419
import org.junit.runner.RunWith
20+
import org.robolectric.annotation.Config
1521

1622
@RunWith(AndroidJUnit4::class)
1723
class DeviceInfoUtilTest {
@@ -47,6 +53,32 @@ class DeviceInfoUtilTest {
4753
assertNotNull(deviceInfo.memorySize)
4854
}
4955

56+
@Test
57+
fun `sets default timezone`() {
58+
val deviceInfoUtil = DeviceInfoUtil.getInstance(context, SentryAndroidOptions())
59+
val deviceInfo = deviceInfoUtil.collectDeviceInformation(false, false)
60+
61+
assertEquals(TimeZone.getDefault(), deviceInfo.timezone)
62+
}
63+
64+
@Test
65+
@Config(sdk = [Build.VERSION_CODES.TIRAMISU])
66+
fun `preserves timezone from locale unicode extension`() {
67+
val defaultTimeZone = TimeZone.getDefault()
68+
try {
69+
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
70+
val configuration = Configuration(context.resources.configuration)
71+
configuration.setLocales(LocaleList(Locale.forLanguageTag("en-US-u-tz-usnyc")))
72+
val localizedContext = context.createConfigurationContext(configuration)
73+
val deviceInfoUtil = DeviceInfoUtil(localizedContext, SentryAndroidOptions())
74+
val deviceInfo = deviceInfoUtil.collectDeviceInformation(false, false)
75+
76+
assertEquals("America/New_York", deviceInfo.timezone?.id)
77+
} finally {
78+
TimeZone.setDefault(defaultTimeZone)
79+
}
80+
}
81+
5082
@Test
5183
fun `does include cpu data`() {
5284
CpuInfoUtils.getInstance().setCpuMaxFrequencies(listOf(1024))

sentry/src/main/java/io/sentry/Breadcrumb.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ public Breadcrumb(@Nullable String message) {
564564
if (timestamp != null) {
565565
return (Date) timestamp.clone();
566566
} else if (timestampMs != null) {
567-
// we memoize it here into timestamp to avoid instantiating Calendar again and again
567+
// we memoize it here into timestamp to avoid creating a Date again and again
568568
timestamp = DateUtils.getDateTime(timestampMs);
569569
return timestamp;
570570
}

sentry/src/main/java/io/sentry/DateUtils.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
package io.sentry;
22

3-
import static io.sentry.vendor.gson.internal.bind.util.ISO8601Utils.TIMEZONE_UTC;
4-
53
import io.sentry.vendor.gson.internal.bind.util.ISO8601Utils;
64
import java.math.BigDecimal;
75
import java.math.RoundingMode;
86
import java.text.ParseException;
97
import java.text.ParsePosition;
10-
import java.util.Calendar;
118
import java.util.Date;
129
import org.jetbrains.annotations.ApiStatus;
1310
import org.jetbrains.annotations.NotNull;
@@ -24,10 +21,9 @@ private DateUtils() {}
2421
*
2522
* @return the UTC Date
2623
*/
27-
@SuppressWarnings("JdkObsolete")
24+
@SuppressWarnings("JavaUtilDate")
2825
public static @NotNull Date getCurrentDateTime() {
29-
final Calendar calendar = Calendar.getInstance(TIMEZONE_UTC);
30-
return calendar.getTime();
26+
return new Date();
3127
}
3228

3329
/**
@@ -78,10 +74,9 @@ private DateUtils() {}
7874
* @param millis the UTC millis from the epoch
7975
* @return the UTC Date
8076
*/
77+
@SuppressWarnings("JavaUtilDate")
8178
public static @NotNull Date getDateTime(final long millis) {
82-
final Calendar calendar = Calendar.getInstance(TIMEZONE_UTC);
83-
calendar.setTimeInMillis(millis);
84-
return calendar.getTime();
79+
return new Date(millis);
8580
}
8681

8782
/**

sentry/src/main/java/io/sentry/vendor/gson/stream/JsonWriter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
// Source: https://github.com/google/gson
1818
// Tag: gson-parent-2.8.7
1919
// Commit Hash: 4520489c29e770c64b11ca35e0a0fdf17a1874ab
20-
// Changes: @ApiStatus.Internal, SuppressWarnings
20+
// Changes: @ApiStatus.Internal, SuppressWarnings, reduced stack size
2121

2222
package io.sentry.vendor.gson.stream;
2323

@@ -175,7 +175,7 @@ public class JsonWriter implements Closeable, Flushable {
175175
/** The output data, containing at most one top-level array or object. */
176176
private final Writer out;
177177

178-
private int[] stack = new int[32];
178+
private int[] stack = new int[8];
179179
private int stackSize = 0;
180180
{
181181
push(EMPTY_DOCUMENT);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class DateUtilsTest {
8686
val utcActual = convertDate(actual)
8787
val timestamp = utcActual.format(isoFormat)
8888

89+
assertEquals(millis, actual.time)
8990
assertEquals("2020-06-07T12:38:12.631Z", timestamp)
9091
}
9192

0 commit comments

Comments
 (0)