From f934f9cb0fe907e527d6ac7193ffb6874d64809e Mon Sep 17 00:00:00 2001 From: mchtech Date: Wed, 7 Dec 2022 12:52:46 +0800 Subject: [PATCH] add options for perf profilers Signed-off-by: mchtech --- collector/perf_linux.go | 155 +++++++++++++++++++++++++++++++--------- 1 file changed, 122 insertions(+), 33 deletions(-) diff --git a/collector/perf_linux.go b/collector/perf_linux.go index 812dbaf8..e2405f12 100644 --- a/collector/perf_linux.go +++ b/collector/perf_linux.go @@ -37,12 +37,67 @@ const ( var ( perfCPUsFlag = kingpin.Flag("collector.perf.cpus", "List of CPUs from which perf metrics should be collected").Default("").String() perfTracepointFlag = kingpin.Flag("collector.perf.tracepoint", "perf tracepoint that should be collected").Strings() + perfNoHwProfiler = kingpin.Flag("collector.perf.disable-hardware-profilers", "disable perf hardware profilers").Default("false").Bool() + perfHwProfilerFlag = kingpin.Flag("collector.perf.hardware-profilers", "perf hardware profilers that should be collected").Strings() + perfNoSwProfiler = kingpin.Flag("collector.perf.disable-software-profilers", "disable perf software profilers").Default("false").Bool() + perfSwProfilerFlag = kingpin.Flag("collector.perf.software-profilers", "perf software profilers that should be collected").Strings() + perfNoCaProfiler = kingpin.Flag("collector.perf.disable-cache-profilers", "disable perf cache profilers").Default("false").Bool() + perfCaProfilerFlag = kingpin.Flag("collector.perf.cache-profilers", "perf cache profilers that should be collected").Strings() ) func init() { registerCollector(perfSubsystem, defaultDisabled, NewPerfCollector) } +var ( + perfHardwareProfilerMap = map[string]perf.HardwareProfilerType{ + "CpuCycles": perf.CpuCyclesProfiler, + "CpuInstr": perf.CpuInstrProfiler, + "CacheRef": perf.CacheRefProfiler, + "CacheMisses": perf.CacheMissesProfiler, + "BranchInstr": perf.BranchInstrProfiler, + "BranchMisses": perf.BranchMissesProfiler, + "StalledCyclesBackend": perf.StalledCyclesBackendProfiler, + "StalledCyclesFrontend": perf.StalledCyclesFrontendProfiler, + "RefCpuCycles": perf.RefCpuCyclesProfiler, + // "BusCycles": perf.BusCyclesProfiler, + } + perfSoftwareProfilerMap = map[string]perf.SoftwareProfilerType{ + "PageFault": perf.PageFaultProfiler, + "ContextSwitch": perf.ContextSwitchProfiler, + "CpuMigration": perf.CpuMigrationProfiler, + "MinorFault": perf.MinorFaultProfiler, + "MajorFault": perf.MajorFaultProfiler, + // "CpuClock": perf.CpuClockProfiler, + // "TaskClock": perf.TaskClockProfiler, + // "AlignFault": perf.AlignFaultProfiler, + // "EmuFault": perf.EmuFaultProfiler, + } + perfCacheProfilerMap = map[string]perf.CacheProfilerType{ + "L1DataReadHit": perf.L1DataReadHitProfiler, + "L1DataReadMiss": perf.L1DataReadMissProfiler, + "L1DataWriteHit": perf.L1DataWriteHitProfiler, + "L1InstrReadMiss": perf.L1InstrReadMissProfiler, + "LLReadHit": perf.LLReadHitProfiler, + "LLReadMiss": perf.LLReadMissProfiler, + "LLWriteHit": perf.LLWriteHitProfiler, + "LLWriteMiss": perf.LLWriteMissProfiler, + "InstrTLBReadHit": perf.InstrTLBReadHitProfiler, + "InstrTLBReadMiss": perf.InstrTLBReadMissProfiler, + "BPUReadHit": perf.BPUReadHitProfiler, + "BPUReadMiss": perf.BPUReadMissProfiler, + // "L1InstrReadHit": perf.L1InstrReadHitProfiler, + // "DataTLBReadHit": perf.DataTLBReadHitProfiler, + // "DataTLBReadMiss": perf.DataTLBReadMissProfiler, + // "DataTLBWriteHit": perf.DataTLBWriteHitProfiler, + // "DataTLBWriteMiss": perf.DataTLBWriteMissProfiler, + // "NodeCacheReadHit": perf.NodeCacheReadHitProfiler, + // "NodeCacheReadMiss": perf.NodeCacheReadMissProfiler, + // "NodeCacheWriteHit": perf.NodeCacheWriteHitProfiler, + // "NodeCacheWriteMiss": perf.NodeCacheWriteMissProfiler, + } +) + // perfTracepointFlagToTracepoints returns the set of configured tracepoints. func perfTracepointFlagToTracepoints(tracepointsFlag []string) ([]*perfTracepoint, error) { tracepoints := make([]*perfTracepoint, len(tracepointsFlag)) @@ -282,48 +337,82 @@ func NewPerfCollector(logger log.Logger) (Collector, error) { collector.tracepointCollector = tracepointCollector } + // Configure perf profilers + hardwareProfilers := perf.AllHardwareProfilers + if *perfHwProfilerFlag != nil && len(*perfHwProfilerFlag) > 0 { + // hardwareProfilers = 0 + for _, hf := range *perfHwProfilerFlag { + if v, ok := perfHardwareProfilerMap[hf]; ok { + hardwareProfilers |= v + } + } + } + softwareProfilers := perf.AllSoftwareProfilers + if *perfSwProfilerFlag != nil && len(*perfSwProfilerFlag) > 0 { + // softwareProfilers = 0 + for _, sf := range *perfSwProfilerFlag { + if v, ok := perfSoftwareProfilerMap[sf]; ok { + softwareProfilers |= v + } + } + } + cacheProfilers := perf.L1DataReadHitProfiler | perf.L1DataReadMissProfiler | perf.L1DataWriteHitProfiler | perf.L1InstrReadMissProfiler | perf.InstrTLBReadHitProfiler | perf.InstrTLBReadMissProfiler | perf.LLReadHitProfiler | perf.LLReadMissProfiler | perf.LLWriteHitProfiler | perf.LLWriteMissProfiler | perf.BPUReadHitProfiler | perf.BPUReadMissProfiler + if *perfCaProfilerFlag != nil && len(*perfCaProfilerFlag) > 0 { + cacheProfilers = 0 + for _, cf := range *perfCaProfilerFlag { + if v, ok := perfCacheProfilerMap[cf]; ok { + cacheProfilers |= v + } + } + } + // Configure all profilers for the specified CPUs. for _, cpu := range cpus { // Use -1 to profile all processes on the CPU, see: // man perf_event_open - hwProf, err := perf.NewHardwareProfiler( - -1, - cpu, - perf.AllHardwareProfilers, - ) - if err != nil && !hwProf.HasProfilers() { - return nil, err + if !*perfNoHwProfiler { + hwProf, err := perf.NewHardwareProfiler( + -1, + cpu, + hardwareProfilers, + ) + if err != nil && !hwProf.HasProfilers() { + return nil, err + } + if err := hwProf.Start(); err != nil { + return nil, err + } + collector.perfHwProfilers[cpu] = &hwProf + collector.hwProfilerCPUMap[&hwProf] = cpu } - if err := hwProf.Start(); err != nil { - return nil, err - } - collector.perfHwProfilers[cpu] = &hwProf - collector.hwProfilerCPUMap[&hwProf] = cpu - swProf, err := perf.NewSoftwareProfiler(-1, cpu, perf.AllSoftwareProfilers) - if err != nil && !swProf.HasProfilers() { - return nil, err + if !*perfNoSwProfiler { + swProf, err := perf.NewSoftwareProfiler(-1, cpu, softwareProfilers) + if err != nil && !swProf.HasProfilers() { + return nil, err + } + if err := swProf.Start(); err != nil { + return nil, err + } + collector.perfSwProfilers[cpu] = &swProf + collector.swProfilerCPUMap[&swProf] = cpu } - if err := swProf.Start(); err != nil { - return nil, err - } - collector.perfSwProfilers[cpu] = &swProf - collector.swProfilerCPUMap[&swProf] = cpu - cacheProfilers := perf.L1DataReadHitProfiler & perf.L1DataReadMissProfiler & perf.L1DataWriteHitProfiler & perf.L1InstrReadMissProfiler & perf.InstrTLBReadHitProfiler & perf.InstrTLBReadMissProfiler & perf.LLReadHitProfiler & perf.LLReadMissProfiler & perf.LLWriteHitProfiler & perf.LLWriteMissProfiler & perf.BPUReadHitProfiler & perf.BPUReadMissProfiler - cacheProf, err := perf.NewCacheProfiler( - -1, - cpu, - cacheProfilers, - ) - if err != nil && !cacheProf.HasProfilers() { - return nil, err + if !*perfNoCaProfiler { + cacheProf, err := perf.NewCacheProfiler( + -1, + cpu, + cacheProfilers, + ) + if err != nil && !cacheProf.HasProfilers() { + return nil, err + } + if err := cacheProf.Start(); err != nil { + return nil, err + } + collector.perfCacheProfilers[cpu] = &cacheProf + collector.cacheProfilerCPUMap[&cacheProf] = cpu } - if err := cacheProf.Start(); err != nil { - return nil, err - } - collector.perfCacheProfilers[cpu] = &cacheProf - collector.cacheProfilerCPUMap[&cacheProf] = cpu } collector.desc = map[string]*prometheus.Desc{