From bfd63ebd92fe87baaa78fe9ceb9d973597d02fa5 Mon Sep 17 00:00:00 2001 From: Daniel Hodges Date: Mon, 13 Sep 2021 21:39:45 -0400 Subject: [PATCH] lazily return errors in profiler initialization Signed-off-by: Daniel Hodges --- cache_profiler.go | 103 ++++++++++++++++++++++++++----------------- hardware_profiler.go | 53 +++++++++++++--------- software_profiler.go | 48 ++++++++++++-------- 3 files changed, 123 insertions(+), 81 deletions(-) diff --git a/cache_profiler.go b/cache_profiler.go index 1d2612e..35ae452 100644 --- a/cache_profiler.go +++ b/cache_profiler.go @@ -64,177 +64,198 @@ type cacheProfiler struct { // NewCacheProfiler returns a new cache profiler. func NewCacheProfiler(pid, cpu int, opts ...int) (CacheProfiler, error) { profilers := map[int]Profiler{} + var e error // L1 data op := unix.PERF_COUNT_HW_CACHE_OP_READ result := unix.PERF_COUNT_HW_CACHE_RESULT_ACCESS l1dataReadHit, err := NewL1DataProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[L1DataReadHit] = l1dataReadHit } - profilers[L1DataReadHit] = l1dataReadHit op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_MISS l1dataReadMiss, err := NewL1DataProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[L1DataReadMiss] = l1dataReadMiss } - profilers[L1DataReadMiss] = l1dataReadMiss op = unix.PERF_COUNT_HW_CACHE_OP_WRITE result = unix.PERF_COUNT_HW_CACHE_RESULT_ACCESS l1dataWriteHit, err := NewL1DataProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[L1DataWriteHit] = l1dataWriteHit } - profilers[L1DataWriteHit] = l1dataWriteHit // L1 instruction op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_MISS l1InstrReadMiss, err := NewL1InstrProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[L1InstrReadMiss] = l1InstrReadMiss } - profilers[L1InstrReadMiss] = l1InstrReadMiss // Last Level op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_ACCESS llReadHit, err := NewLLCacheProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[LLReadHit] = llReadHit } - profilers[LLReadHit] = llReadHit op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_MISS llReadMiss, err := NewLLCacheProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[LLReadMiss] = llReadMiss } - profilers[LLReadMiss] = llReadMiss op = unix.PERF_COUNT_HW_CACHE_OP_WRITE result = unix.PERF_COUNT_HW_CACHE_RESULT_ACCESS llWriteHit, err := NewLLCacheProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[LLWriteHit] = llWriteHit } - profilers[LLWriteHit] = llWriteHit op = unix.PERF_COUNT_HW_CACHE_OP_WRITE result = unix.PERF_COUNT_HW_CACHE_RESULT_MISS llWriteMiss, err := NewLLCacheProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[LLWriteMiss] = llWriteMiss } - profilers[LLWriteMiss] = llWriteMiss // dTLB op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_ACCESS dTLBReadHit, err := NewDataTLBProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[DataTLBReadHit] = dTLBReadHit } - profilers[DataTLBReadHit] = dTLBReadHit op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_MISS dTLBReadMiss, err := NewDataTLBProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[DataTLBReadMiss] = dTLBReadMiss } - profilers[DataTLBReadMiss] = dTLBReadMiss op = unix.PERF_COUNT_HW_CACHE_OP_WRITE result = unix.PERF_COUNT_HW_CACHE_RESULT_ACCESS dTLBWriteHit, err := NewDataTLBProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[DataTLBWriteHit] = dTLBWriteHit } - profilers[DataTLBWriteHit] = dTLBWriteHit op = unix.PERF_COUNT_HW_CACHE_OP_WRITE result = unix.PERF_COUNT_HW_CACHE_RESULT_MISS dTLBWriteMiss, err := NewDataTLBProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[DataTLBWriteMiss] = dTLBWriteMiss } - profilers[DataTLBWriteMiss] = dTLBWriteMiss // iTLB op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_ACCESS iTLBReadHit, err := NewInstrTLBProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[InstrTLBReadHit] = iTLBReadHit } - profilers[InstrTLBReadHit] = iTLBReadHit op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_MISS iTLBReadMiss, err := NewInstrTLBProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[InstrTLBReadMiss] = iTLBReadMiss } - profilers[InstrTLBReadMiss] = iTLBReadMiss // BPU op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_ACCESS bpuReadHit, err := NewBPUProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[BPUReadHit] = bpuReadHit } - profilers[BPUReadHit] = bpuReadHit op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_MISS bpuReadMiss, err := NewBPUProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[BPUReadMiss] = bpuReadMiss } - profilers[BPUReadMiss] = bpuReadMiss // Node op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_ACCESS nodeReadHit, err := NewNodeCacheProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[NodeCacheReadHit] = nodeReadHit } - profilers[NodeCacheReadHit] = nodeReadHit op = unix.PERF_COUNT_HW_CACHE_OP_READ result = unix.PERF_COUNT_HW_CACHE_RESULT_MISS nodeReadMiss, err := NewNodeCacheProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[NodeCacheReadMiss] = nodeReadMiss } - profilers[NodeCacheReadMiss] = nodeReadMiss op = unix.PERF_COUNT_HW_CACHE_OP_WRITE result = unix.PERF_COUNT_HW_CACHE_RESULT_ACCESS nodeWriteHit, err := NewNodeCacheProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[NodeCacheWriteHit] = nodeWriteHit } - profilers[NodeCacheWriteHit] = nodeWriteHit op = unix.PERF_COUNT_HW_CACHE_OP_WRITE result = unix.PERF_COUNT_HW_CACHE_RESULT_MISS nodeWriteMiss, err := NewNodeCacheProfiler(pid, cpu, op, result, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[NodeCacheWriteMiss] = nodeWriteMiss } - profilers[NodeCacheWriteMiss] = nodeWriteMiss return &cacheProfiler{ profilers: profilers, - }, nil + }, e } // Start is used to start the CacheProfiler, it will return an error if no diff --git a/hardware_profiler.go b/hardware_profiler.go index e3cb804..13e4cdf 100644 --- a/hardware_profiler.go +++ b/hardware_profiler.go @@ -15,71 +15,82 @@ type hardwareProfiler struct { // NewHardwareProfiler returns a new hardware profiler. func NewHardwareProfiler(pid, cpu int, opts ...int) (HardwareProfiler, error) { + var e error profilers := map[int]Profiler{} cpuCycleProfiler, err := NewCPUCycleProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_HW_CPU_CYCLES] = cpuCycleProfiler } - profilers[unix.PERF_COUNT_HW_CPU_CYCLES] = cpuCycleProfiler instrProfiler, err := NewInstrProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_HW_INSTRUCTIONS] = instrProfiler } - profilers[unix.PERF_COUNT_HW_INSTRUCTIONS] = instrProfiler cacheRefProfiler, err := NewCacheRefProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_HW_CACHE_REFERENCES] = cacheRefProfiler } - profilers[unix.PERF_COUNT_HW_CACHE_REFERENCES] = cacheRefProfiler cacheMissesProfiler, err := NewCacheMissesProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_HW_CACHE_MISSES] = cacheMissesProfiler } - profilers[unix.PERF_COUNT_HW_CACHE_MISSES] = cacheMissesProfiler branchInstrProfiler, err := NewBranchInstrProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = branchInstrProfiler } - profilers[unix.PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = branchInstrProfiler branchMissesProfiler, err := NewBranchMissesProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_HW_BRANCH_MISSES] = branchMissesProfiler } - profilers[unix.PERF_COUNT_HW_BRANCH_MISSES] = branchMissesProfiler busCyclesProfiler, err := NewBusCyclesProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_HW_BUS_CYCLES] = busCyclesProfiler } - profilers[unix.PERF_COUNT_HW_BUS_CYCLES] = busCyclesProfiler stalledCyclesFrontProfiler, err := NewStalledCyclesFrontProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = stalledCyclesFrontProfiler } - profilers[unix.PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = stalledCyclesFrontProfiler stalledCyclesBackProfiler, err := NewStalledCyclesBackProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = stalledCyclesBackProfiler } - profilers[unix.PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = stalledCyclesBackProfiler refCPUCyclesProfiler, err := NewRefCPUCyclesProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_HW_REF_CPU_CYCLES] = refCPUCyclesProfiler } - profilers[unix.PERF_COUNT_HW_REF_CPU_CYCLES] = refCPUCyclesProfiler return &hardwareProfiler{ profilers: profilers, - }, nil + }, e } // Start is used to start the HardwareProfiler. diff --git a/software_profiler.go b/software_profiler.go index a5f8e69..d90f8fa 100644 --- a/software_profiler.go +++ b/software_profiler.go @@ -15,65 +15,75 @@ type softwareProfiler struct { // NewSoftwareProfiler returns a new software profiler. func NewSoftwareProfiler(pid, cpu int, opts ...int) (SoftwareProfiler, error) { + var e error profilers := map[int]Profiler{} cpuClockProfiler, err := NewCPUClockProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_SW_CPU_CLOCK] = cpuClockProfiler } - profilers[unix.PERF_COUNT_SW_CPU_CLOCK] = cpuClockProfiler taskClockProfiler, err := NewTaskClockProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_SW_TASK_CLOCK] = taskClockProfiler } - profilers[unix.PERF_COUNT_SW_TASK_CLOCK] = taskClockProfiler pageFaultProfiler, err := NewPageFaultProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_SW_PAGE_FAULTS] = pageFaultProfiler } - profilers[unix.PERF_COUNT_SW_PAGE_FAULTS] = pageFaultProfiler ctxSwitchesProfiler, err := NewCtxSwitchesProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_SW_CONTEXT_SWITCHES] = ctxSwitchesProfiler } - profilers[unix.PERF_COUNT_SW_CONTEXT_SWITCHES] = ctxSwitchesProfiler cpuMigrationsProfiler, err := NewCPUMigrationsProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_SW_CPU_MIGRATIONS] = cpuMigrationsProfiler } - profilers[unix.PERF_COUNT_SW_CPU_MIGRATIONS] = cpuMigrationsProfiler minorFaultProfiler, err := NewMinorFaultsProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_SW_PAGE_FAULTS_MIN] = minorFaultProfiler } - profilers[unix.PERF_COUNT_SW_PAGE_FAULTS_MIN] = minorFaultProfiler majorFaultProfiler, err := NewMajorFaultsProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_SW_PAGE_FAULTS_MAJ] = majorFaultProfiler } - profilers[unix.PERF_COUNT_SW_PAGE_FAULTS_MAJ] = majorFaultProfiler alignFaultsFrontProfiler, err := NewAlignFaultsProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_SW_ALIGNMENT_FAULTS] = alignFaultsFrontProfiler } - profilers[unix.PERF_COUNT_SW_ALIGNMENT_FAULTS] = alignFaultsFrontProfiler emuFaultProfiler, err := NewEmulationFaultsProfiler(pid, cpu, opts...) if err != nil { - return nil, err + e = multierr.Append(e, err) + } else { + profilers[unix.PERF_COUNT_SW_EMULATION_FAULTS] = emuFaultProfiler } - profilers[unix.PERF_COUNT_SW_EMULATION_FAULTS] = emuFaultProfiler return &softwareProfiler{ profilers: profilers, - }, nil + }, e } // Start is used to start the SoftwareProfiler.