blob: cb779530a198c2ffc53f04fcb8cecdea7dc24f12 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package benchmarking
import (
"fmt"
)
const OneSecInMicroSeconds float64 = 1000000
// Extract the list of average cpu percentage usages from the trace model
// under system_metrics category, and write it into testResultsFile.
func ReportCpuMetrics(model Model, testSuite string, testResultsFile *TestResultsFile) {
fmt.Printf("=== CPU ===\n")
duration := model.getTotalTraceDurationInMicroseconds()
if duration < 1.1*OneSecInMicroSeconds {
fmt.Printf("Trace duration %.4f microseconds is too short to provide CPU information.\n", duration)
return
}
cpuPercentages := extractCounterValues(
model, "system_metrics", "cpu_usage", []string{"average_cpu_percentage"})["average_cpu_percentage"]
fmt.Printf("Average CPU Load: %.4f\n", computeAverage(cpuPercentages))
testResultsFile.Add(&TestCaseResults{
Label: "CPU Load",
TestSuite: testSuite,
Unit: Unit(Percent),
Values: cpuPercentages,
})
}
// Extract used memory, VMO memory, MMU Overhead memory and IPC memory
// from the trace model under memory_monitor category, and write it into testResultsFile.
func ReportMemoryMetrics(model Model, testSuite string, testResultsFile *TestResultsFile) {
fmt.Printf("=== Memory ===\n")
duration := model.getTotalTraceDurationInMicroseconds()
if duration < 1.1*OneSecInMicroSeconds {
fmt.Printf("Trace duration %.4f microseconds is too short to provide memory information.\n", duration)
return
}
allocatedMemoryValues := extractCounterValues(
model, "memory_monitor", "allocated", []string{"vmo", "mmu_overhead", "ipc"})
totalMemory := extractCounterValues(
model, "memory_monitor", "fixed", []string{"total"})["total"][0]
freeMemoryValues := extractCounterValues(
model, "memory_monitor", "free", []string{"free"})["free"]
usedMemoryValues := make([]float64, 0)
for _, freeMemory := range freeMemoryValues {
usedMemoryValues = append(usedMemoryValues, totalMemory-freeMemory)
}
type SystemMetric struct {
Name string
Values []float64
}
systemMetrics := []SystemMetric{
{"Total System Memory", usedMemoryValues},
{"VMO Memory", allocatedMemoryValues["vmo"]},
{"MMU Overhead Memory", allocatedMemoryValues["mmu_overhead"]},
{"IPC Memory", allocatedMemoryValues["ipc"]},
}
for _, metric := range systemMetrics {
fmt.Printf("Average %s in bytes: %.2f\n", metric.Name, computeAverage(metric.Values))
testResultsFile.Add(&TestCaseResults{
Label: metric.Name,
TestSuite: testSuite,
Unit: Unit(Bytes),
Values: metric.Values,
})
}
}
// Extract the list of device temperature readings in Celsius from the trace model
// under system_metrics category, and write it into testResultsFile.
func ReportTemperatureMetrics(model Model, testSuite string, testResultsFile *TestResultsFile) {
fmt.Printf("=== Temperature ===\n")
duration := model.getTotalTraceDurationInMicroseconds()
if duration < 10.1*OneSecInMicroSeconds {
fmt.Printf("Trace duration %.4f microseconds is too short to provide temperature information.\n", duration)
return
}
temperatureReadings := extractCounterValues(
model, "system_metrics", "temperature", []string{"temperature"})["temperature"]
fmt.Printf("Average temperature reading: %.2f degrees Celsius\n", computeAverage(temperatureReadings))
testResultsFile.Add(&TestCaseResults{
Label: "Device temperature",
TestSuite: testSuite,
Unit: Unit(Count),
Values: temperatureReadings,
})
}
// Helper function to extract int or float64 values for a particular category,
// name and a list of args from the trace model.
// Returns a map from each arg to the corresponding list of values found.
// All values are cast to float64.
func extractCounterValues(model Model, cat string, name string, args []string) map[string][]float64 {
events := model.FindEvents(EventsFilter{Name: &name, Cat: &cat})
if len(events) == 0 {
panic(fmt.Sprintf("Found 0 events with category=%s and name=%s", cat, name))
}
argToValues := map[string][]float64{}
var value float64
for _, event := range events {
for _, arg := range args {
switch event.Args[arg].(type) {
case int:
value = float64(event.Args[arg].(int))
case float64:
value = event.Args[arg].(float64)
}
argToValues[arg] = append(argToValues[arg], value)
}
}
return argToValues
}
// Compute the average of an array of float64 values.
func computeAverage(array []float64) float64 {
result := 0.0
for _, item := range array {
result += item
}
return result / float64(len(array))
}