Skip to content

Commit c8f560d

Browse files
committed
1 parent af52824 commit c8f560d

2 files changed

Lines changed: 51 additions & 6 deletions

File tree

sentry-android-core/src/main/java/io/sentry/android/core/internal/threaddump/ArtContextParser.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,33 @@ void parseLine(final @NotNull String text) {
108108
return null;
109109
}
110110

111+
/**
112+
* Parses ART's PrettyDuration output and converts to milliseconds. Handles "s", "ms", "us", "ns"
113+
* suffixes and the bare "0" special case.
114+
*
115+
* @see <a
116+
* href="https://cs.android.com/android/platform/superproject/+/android-latest-release:art/libartbase/base/time_utils.cc;l=95-133;drc=16e1409f339b1318fe1cdce8462f089b3b0475e8">ART
117+
* PrettyDuration / FormatDuration</a>
118+
*/
111119
private static @Nullable Double parseTimeMs(final @NotNull String timeString) {
112120
final String trimmed = timeString.trim();
113-
if (trimmed.endsWith("ms")) {
114-
try {
115-
// Double.parseDouble is locale-independent (always uses '.' as decimal separator),
116-
// which matches the ART runtime output format.
121+
try {
122+
if (trimmed.equals("0")) {
123+
return 0.0;
124+
}
125+
// Double.parseDouble is locale-independent (always uses '.' as decimal separator),
126+
// which matches the ART runtime output format.
127+
if (trimmed.endsWith("ms")) {
117128
return Double.parseDouble(trimmed.substring(0, trimmed.length() - 2));
118-
} catch (NumberFormatException e) {
119-
return null;
129+
} else if (trimmed.endsWith("ns")) {
130+
return Double.parseDouble(trimmed.substring(0, trimmed.length() - 2)) / 1_000_000.0;
131+
} else if (trimmed.endsWith("us")) {
132+
return Double.parseDouble(trimmed.substring(0, trimmed.length() - 2)) / 1_000.0;
133+
} else if (trimmed.endsWith("s")) {
134+
return Double.parseDouble(trimmed.substring(0, trimmed.length() - 1)) * 1_000.0;
120135
}
136+
} catch (NumberFormatException e) {
137+
return null;
121138
}
122139
return null;
123140
}

sentry-android-core/src/test/java/io/sentry/android/core/internal/threaddump/ArtContextParserTest.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,34 @@ class ArtContextParserTest {
5353
assertEquals(11.807, parser.artContext!!.gcTotalTime)
5454
}
5555

56+
@Test
57+
fun `parses time in seconds`() {
58+
val parser = ArtContextParser()
59+
parser.parseLine("Total GC time: 2.5s")
60+
assertEquals(2500.0, parser.artContext!!.gcTotalTime)
61+
}
62+
63+
@Test
64+
fun `parses time in microseconds`() {
65+
val parser = ArtContextParser()
66+
parser.parseLine("Total GC time: 500us")
67+
assertEquals(0.5, parser.artContext!!.gcTotalTime)
68+
}
69+
70+
@Test
71+
fun `parses time in nanoseconds`() {
72+
val parser = ArtContextParser()
73+
parser.parseLine("Total GC time: 1000000ns")
74+
assertEquals(1.0, parser.artContext!!.gcTotalTime)
75+
}
76+
77+
@Test
78+
fun `parses zero duration`() {
79+
val parser = ArtContextParser()
80+
parser.parseLine("Total GC time: 0")
81+
assertEquals(0.0, parser.artContext!!.gcTotalTime)
82+
}
83+
5684
@Test
5785
fun `parses all memory fields`() {
5886
val parser = ArtContextParser()

0 commit comments

Comments
 (0)