Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ internal class PerfettoProfiler(
@Volatile
private var profilingAppStartInfo: String? = null

@Volatile
private var profilingSamplingRateHz: Int = PROFILING_SAMPLING_RATE_APP_LAUNCH

@Volatile
override var internalLogger: InternalLogger? = null
set(value) {
Expand Down Expand Up @@ -138,7 +141,7 @@ internal class PerfettoProfiler(
resultCallbackDelayMs = resultCallbackDelayMs,
stopReason = resolveStopReason(result.errorCode),
bufferSizeKb = BUFFER_SIZE_KB,
samplingFrequencyHz = PROFILING_SAMPLING_RATE
samplingFrequencyHz = profilingSamplingRateHz
)
)
}
Expand All @@ -148,18 +151,28 @@ internal class PerfettoProfiler(
startReason: ProfilingStartReason,
durationMs: Int
): ProfilingRequest {
val samplingRateHz = getSamplingRateHz(startReason)
profilingSamplingRateHz = samplingRateHz
return CancellationSignal().let {
this.stopSignal = it
StackSamplingRequestBuilder()
.setCancellationSignal(it)
.setTag(startReason.value)
.setSamplingFrequencyHz(PROFILING_SAMPLING_RATE)
.setSamplingFrequencyHz(samplingRateHz)
.setBufferSizeKb(BUFFER_SIZE_KB)
.setDurationMs(durationMs)
.build()
}
}

private fun getSamplingRateHz(startReason: ProfilingStartReason): Int {
return if (startReason == ProfilingStartReason.APPLICATION_LAUNCH) {
PROFILING_SAMPLING_RATE_APP_LAUNCH
} else {
PROFILING_SAMPLING_RATE_CONTINUOUS
}
}

private fun notifyCallbacks(dispatch: ProfilerCallback.() -> Unit) {
val running = runningInstances.get()
callbackMap.forEach { (key, callback) ->
Expand Down Expand Up @@ -291,9 +304,11 @@ internal class PerfettoProfiler(
// increased or configurable if needed.
private const val BUFFER_SIZE_KB = 5120 // 5MB

// Currently we give 201HZ frequency to balance the sampling accuracy and performance
// overhead also to avoid lockstep sampling, it can be updated or configurable if needed.
internal const val PROFILING_SAMPLING_RATE = 201 // 201Hz
// 201Hz for app launch: higher accuracy to capture startup behavior.
internal const val PROFILING_SAMPLING_RATE_APP_LAUNCH = 201

// 101Hz for continuous profiling: lower overhead for sustained background recording.
internal const val PROFILING_SAMPLING_RATE_CONTINUOUS = 101

// Re-exported from ProfilingTelemetry so external callers (e.g. content provider)
// keep using the same property key when passing app-start info as an additional attribute.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import com.datadog.android.profiling.forge.Configurator
import com.datadog.android.profiling.internal.anr.AnrTriggerRegistrar
import com.datadog.android.profiling.internal.perfetto.PerfettoProfiler
import com.datadog.android.profiling.internal.perfetto.PerfettoProfiler.Companion.APP_LAUNCH_PROFILING_MAX_DURATION_MS
import com.datadog.android.profiling.internal.perfetto.PerfettoProfiler.Companion.PROFILING_SAMPLING_RATE
import com.datadog.android.profiling.internal.perfetto.PerfettoProfiler.Companion.PROFILING_SAMPLING_RATE_APP_LAUNCH
import com.datadog.android.profiling.internal.perfetto.PerfettoProfiler.Companion.PROFILING_SAMPLING_RATE_CONTINUOUS
import com.datadog.android.profiling.internal.perfetto.PerfettoResult
import fr.xgouchet.elmyr.Forge
import fr.xgouchet.elmyr.annotation.Forgery
Expand Down Expand Up @@ -237,7 +238,7 @@ class PerfettoProfilerTest {
),
"profiling_config" to mapOf(
"buffer_size" to 5120,
"sampling_frequency" to PROFILING_SAMPLING_RATE
"sampling_frequency" to PROFILING_SAMPLING_RATE_APP_LAUNCH
)
)
verify(mockInternalLogger)
Expand Down Expand Up @@ -299,7 +300,7 @@ class PerfettoProfilerTest {
),
"profiling_config" to mapOf(
"buffer_size" to 5120,
"sampling_frequency" to PROFILING_SAMPLING_RATE
"sampling_frequency" to PROFILING_SAMPLING_RATE_APP_LAUNCH
)
)
verify(mockInternalLogger)
Expand Down Expand Up @@ -362,7 +363,7 @@ class PerfettoProfilerTest {
),
"profiling_config" to mapOf(
"buffer_size" to 5120,
"sampling_frequency" to PROFILING_SAMPLING_RATE
"sampling_frequency" to PROFILING_SAMPLING_RATE_APP_LAUNCH
)
)
verify(mockInternalLogger)
Expand Down Expand Up @@ -766,7 +767,7 @@ class PerfettoProfilerTest {
),
"profiling_config" to mapOf(
"buffer_size" to 5120,
"sampling_frequency" to PROFILING_SAMPLING_RATE
"sampling_frequency" to PROFILING_SAMPLING_RATE_APP_LAUNCH
)
)
verify(mockInternalLogger)
Expand Down Expand Up @@ -811,6 +812,11 @@ class PerfettoProfilerTest {
callbackCaptor.firstValue.accept(mockResult)

val messageCaptor = argumentCaptor<() -> String>()
val expectedSamplingRate = if (startReason == ProfilingStartReason.APPLICATION_LAUNCH) {
PROFILING_SAMPLING_RATE_APP_LAUNCH
} else {
PROFILING_SAMPLING_RATE_CONTINUOUS
}
val expectedProps = mapOf(
"metric_type" to "profiling session",
"profiling_session" to mapOf(
Expand All @@ -825,7 +831,7 @@ class PerfettoProfilerTest {
),
"profiling_config" to mapOf(
"buffer_size" to 5120,
"sampling_frequency" to PROFILING_SAMPLING_RATE
"sampling_frequency" to expectedSamplingRate
)
)
verify(mockInternalLogger)
Expand Down Expand Up @@ -892,7 +898,7 @@ class PerfettoProfilerTest {
),
"profiling_config" to mapOf(
"buffer_size" to 5120,
"sampling_frequency" to PROFILING_SAMPLING_RATE
"sampling_frequency" to PROFILING_SAMPLING_RATE_APP_LAUNCH
)
)
verify(mockInternalLogger)
Expand Down Expand Up @@ -985,7 +991,7 @@ class PerfettoProfilerTest {
),
"profiling_config" to mapOf(
"buffer_size" to 5120,
"sampling_frequency" to PROFILING_SAMPLING_RATE
"sampling_frequency" to PROFILING_SAMPLING_RATE_CONTINUOUS
)
)
verify(mockInternalLogger).logMetric(
Expand Down
Loading