您的位置:

深入探究Perfetto

一、Perfetto概述

Perfetto是一款基于Linux平台下开发的系统跟踪工具,旨在提供类似Android Studio的profiler工具的功能,但更轻量级和可定制。Perfetto提供了低开销的内核探测器,将跟踪数据缓存到内存中,并通过插件式的API,让开发者可以更灵活地进行配置和使用。

下面是一个使用Perfetto进行内存分析的示例:

trace_config {
  buffers {
    size_kb: 102400
  }
  duration_ms: 30000
  buffer_size_trigger: { threshold_kb: 1024 left_percent: 20 }
  triggers {
    perfetto_config {
      name: "global"
      duration_ms: 5000
    }
    perfetto_config {
      name: "my_process"
      duration_ms: 1000
      filter: "upid == $my_upid"
    }
  }
}

data_sources {
  config {
    name: "linux.ftrace"
    target_buffer: "kernel"
    ftrace_config {
      ftrace_events: "sched_switch,sched_wakeup"
      include_overhead: true
      buffer_size_kb: 2048
      drain_period_ms: 5000
    }
  }
  config {
    name: "linux.process_stats"
    target_buffer: "user"
    process_stats_config {
      scan_all_processes_on_start: true
      scan_interval_ms: 1000
    }
  }
  config {
    name: "android.heapprofd"
    target_buffer: "user"
    heapprofd_config {
      sampling_interval_bytes: 4096
      continuous_dump_config {
        dump_interval_ms: 100
        dump_phase_ms: 100
      }
    }
  }
}

二、Perfetto插件系统

Perfetto提供了一套插件API,使开发者可以利用Perfetto的核心功能在自己的代码中进行定制。插件可以包括数据源、后处理器、实时监测器和可视化插件。下面是一个使用Perfetto数据源插件的示例:

int MyDataSource::Setup(DataSourceConfig config) {
  if (config.name() != "my_data_source") {
    PERFETTO_ELOG("MyDataSource received wrong name");
    return 0;
  }
  PERFETTO_ILOG("MyDataSource setup");

  // Start the async work.
  async_task_.reset(new base::TaskRunnerThread("my_data_source"));
  async_task_->PostTask([this, options = config.my_data_source_config() {
    SetupWorkerThread(options);
  }]);
  return 1;
}

三、Perfetto的性能优化

Perfetto通过多种方式进行性能优化,例如采用Ring Buffer、避免频繁分配内存和避免加锁等。下面是一个避免加锁操作的示例:

struct TlsMetadata {
  uint64_t start_ts = 0;
  uint64_t end_ts = 0;
};

void SampleProfiler::Record(uintptr_t tid, uint64_t ts) {
  static thread_local std::unordered_map tls_metadata_;
  TlsMetadata& tls_md = tls_metadata_[perfetto::base::GetTid()];

  // Try to expedite the common case.
  if (PERFETTO_UNLIKELY(ts < tls_md.end_ts)) {
    tls_md.end_ts = ts + 1;
    return;
  }

  std::lock_guard
    lock(metadata_mutex_);
  if (metadata_.size() >= kMaxMetadataSize)
    return;

  metadata_.push_back(Metadata{tid, std::array
    (), ts});
  tls_md.start_ts = tls_md.end_ts = ts;
}
    
   
  

四、Perfetto在实际应用中的使用场景

Perfetto可以被用于诊断各种性能瓶颈,例如内存泄漏、UI卡顿和高CPU使用率等。下面是一个使用Perfetto诊断因UI更新频繁而导致的卡顿问题的示例:

chrome://tracing

async function trackFrames() {
  const {trace} = await perfettoTrace();
  const frames = perfetto_frames(trace);
  const frametimes = frames.map(f => f.duration * 1000);
  updateUI(frametimes);
}

五、结束语

通过本文的介绍,我们可以看出Perfetto在系统跟踪方面具有强大的能力和广泛的应用场景。Perfetto的轻量级和灵活性可以让开发者在优化性能方面具有更多的操作空间。因此,在性能调优过程中,我们可以考虑使用Perfetto来帮助我们更好地解决问题。