MemoryCountersQuery.kt
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.benchmark.macro.perfetto
import androidx.benchmark.perfetto.PerfettoTraceProcessor
import androidx.benchmark.perfetto.processNameLikePkg
import org.intellij.lang.annotations.Language
internal object MemoryCountersQuery {
// https://perfetto.dev/docs/data-sources/memory-counters
@Language("sql")
internal fun getQuery(targetPackageName: String) = """
SELECT
track.name as counter_name,
SUM(value)
FROM counter
LEFT JOIN process_counter_track as track on counter.track_id = track.id
LEFT JOIN process using (upid)
WHERE
${processNameLikePkg(targetPackageName)} AND
track.name LIKE 'mem.%.count'
GROUP BY counter_name
""".trimIndent()
private const val MINOR_PAGE_FAULTS_COUNT = "mem.mm.min_flt.count"
private const val MAJOR_PAGE_FAULTS_COUNT = "mem.mm.maj_flt.count"
private const val PAGE_FAULTS_BACKED_BY_SWAP_CACHE_COUNT = "mem.mm.swp_flt.count"
private const val PAGE_FAULTS_BACKED_BY_READ_IO_COUNT = "mem.mm.read_io.count"
private const val MEMORY_COMPACTION_EVENTS_COUNT = "mem.mm.compaction.count"
private const val MEMORY_RECLAIM_EVENTS_COUNT = "mem.mm.reclaim.count"
data class SubMetrics(
// Minor Page Faults
val minorPageFaults: Double,
// Major Page Faults
val majorPageFaults: Double,
// Page Faults Served by Swap Cache
val pageFaultsBackedBySwapCache: Double,
// Read Page Faults backed by I/O
val pageFaultsBackedByReadIO: Double,
// Memory Compaction Events
val memoryCompactionEvents: Double,
// Memory Reclaim Events
val memoryReclaimEvents: Double
)
fun getMemoryCounters(
session: PerfettoTraceProcessor.Session,
targetPackageName: String
): SubMetrics? {
val queryResultIterator = session.query(
query = getQuery(targetPackageName = targetPackageName)
)
val rows = queryResultIterator.toList()
return if (rows.isEmpty()) {
null
} else {
val summations: Map<String, Double> = rows.associate {
it.string("counter_name") to it.double("SUM(value)")
}
SubMetrics(
minorPageFaults = summations[MINOR_PAGE_FAULTS_COUNT] ?: 0.0,
majorPageFaults = summations[MAJOR_PAGE_FAULTS_COUNT] ?: 0.0,
pageFaultsBackedBySwapCache = summations[PAGE_FAULTS_BACKED_BY_SWAP_CACHE_COUNT]
?: 0.0,
pageFaultsBackedByReadIO = summations[PAGE_FAULTS_BACKED_BY_READ_IO_COUNT] ?: 0.0,
memoryCompactionEvents = summations[MEMORY_COMPACTION_EVENTS_COUNT] ?: 0.0,
memoryReclaimEvents = summations[MEMORY_RECLAIM_EVENTS_COUNT] ?: 0.0
)
}
}
}