性能剖析相关概念

性能剖析是动态代码分析的一种形式。您可以在应用运行时捕获应用的特征,然后使用这些特征信息确定如何使应用更快、更高效。

过去,仅在应用开发期间执行性能剖析。此方法依赖于开发能够准确预测生产环境的负载测试和基准的能力。

持续性能剖析是指对在生产环境中执行的应用进行性能剖析。此方法可缓解为生产环境开发准确的预测负载测试和基准的需求。对持续性能剖析的研究表明,这种方法准确且经济实惠*

Cloud Profiler 是一种持续性能剖析工具,专为在 Google Cloud 上运行的应用而设计:

  • 它是一种统计或采样性能剖析器,开销极低,适合生产环境。

  • 它支持常用语言,可收集多种性能剖析类型。如需了解概要,请参阅可用的性能剖析类型

配置 Google Cloud 应用以生成性能剖析数据是一个简单的一次性过程:通过随附的性能剖析代理来关联或运行您的服务。部署应用后,性能剖析代理会定期运行以收集性能数据,然后将这些数据发送到您的 Google Cloud 项目。如需详细了解此过程,请参阅性能剖析文件收集

收集应用的性能剖析数据后,您可以使用 Profiler 界面分析数据。分析性能剖析数据通常是一个迭代过程,依赖于您对应用设计及其编程语言的了解。

*请参阅以下 Google 范围性能剖析:数据中心的持续性能剖析基础架构持续性能剖析:所有周期都去了哪里?

可用的性能剖析类型

下表汇总了支持的性能剖析类型:

性能剖析类型 Go Java Node.js Python
CPU 时间
分配的堆
争用
线程
实际用时

本部分的其余内容详细介绍了上述各种性能剖析类型。

时间测量

  • CPU 时间是 CPU 执行代码块所花费的时间。

    函数的 CPU 时间可告知您 CPU 忙于执行指令的时长,CPU 等待的时间或处理其他程序的指令的时间不包括在内。

  • 挂钟时间(也称为“实际用时”)是运行代码块所需的时间。

    函数的挂钟时间用于测量从进入到退出函数所经过的时间。挂钟时间包括所有等待时间,锁定和线程同步的时间都包括在内。代码块的实际用时永远不会短于 CPU 时间。

如果挂钟时间比 CPU 时间长很多,则表示代码花在等待上的时间非常多。这可能表示存在资源瓶颈。

如果 CPU 时间接近实际用时,则表示代码块属于 CPU 密集型;几乎所有运行时间都由 CPU 占用。长时间运行的 CPU 密集型代码块可能需要进行优化。

堆(内存)用量

  • 堆用量(也称为“堆”)是收集性能剖析文件时程序的堆中所分配的内存量。与其他收集一段时间间隔内的数据的性能剖析文件类型不同,此性能剖析文件类型收集单个时间点上的堆用量。

  • 堆分配量(也称为“分配的堆”)是在收集性能剖析文件的时间间隔内程序的堆中分配的总内存量。此值包括已被分配并释放后不再用到的内存。例如,假设某个作业重复以下序列:分配 1 MiB,等待 500 毫秒,释放 1 MiB,等待 500 毫秒。在收集分配的堆性能剖析文件的 10 秒内,有 10 次分配和 10 次释放。该配置文件将显示 10 MiB 分配的堆,因为不考虑释放的量。平均分配速率为 10 MiB/10 秒或 1 MiB/秒。

对堆用量进行性能剖析有助于您发现程序中潜在的低效和内存泄漏问题,对堆分配量进行性能剖析则有助于您了解哪些分配最大程度加重了“清洁工”的工作量。

线程信息

创建线程的应用可能会遭遇阻塞的线程(创建后从未实际运行的线程)以及线程泄露(创建的线程数量不断增加)。第一个问题是第二个问题的原因之一。

争用

在多线程程序中,序列化对共享资源的访问所花费的等待时间可能很长。了解争用行为可以指导代码的设计,还能提供优化性能方面的信息。

性能剖析文件收集

Profiler 代理的作用是从应用捕获性能剖析数据,并使用 Profiler API 将此数据传输到 Profiler 后端。每个性能剖析文件可供应用的单个实例使用,性能剖析文件中包含四个唯一标识其部署的字段:

  • GCP 项目
  • 应用名称
  • 应用地区
  • 应用版本

代理准备好捕获性能剖析文件后,会向 Profiler 后端发出 Profiler API 命令。后端收到此请求后会通过最简单的方案立即回复代理。回复中会指定要捕获的性能剖析类型。作为响应,代理会捕获相应性能剖析文件并将其传输到后端。最后,Profiler 后端会将性能剖析文件与您的 Google Cloud 项目相关联。然后,您便可以使用 Profiler 界面查看和分析该性能剖析文件。

实际的握手顺序比上一段落中描述的更复杂。例如,当 Profiler 收到已准备好收集性能剖析文件的代理发出的请求时,后端会检查其数据库,以确定之前是否收到过该代理发出的请求。 如果没收到过,后端会将代理信息添加到其数据库中。如果代理部署字段与任何其他所记录代理的字段不匹配,则会创建新部署。

对于每个部署和每种性能剖析类型,后端平均每分钟会选择一个代理,并指示其捕获一个性能剖析文件。 例如,如果部署的代理支持堆和实际用时性能剖析,则平均每分钟会捕获 2 个性能剖析文件:

  • 对于除堆用量和线程消耗量之外的所有性能剖析类型,一个性能剖析文件表示在 10 秒的时间内收集的数据。

  • 堆用量和线程性能剖析文件是即时收集的。

主要的观察结果是,代理通知 Profiler 后端它已准备好捕获数据后,将一直处于空闲状态,直到收到后端的回复(其中指定了要捕获的性能剖析类型)。 如果您在同一部署中运行了 10 个应用实例,则可以创建 10 个性能剖析代理。但是,这些代理大部分时间都处于空闲状态。 在 10 分钟时间内,您应该会捕获 10 个性能剖析文件;每个代理平均会收到一个针对各性能剖析类型的回复。 其中涉及一些随机内容,因此实际数量可能会有所不同。

Profiler 后端使用 Profiler API 配额和性能剖析文件部署字段来限制提取的性能剖析文件的数量。 如需了解如何查看和管理您的 Profiler 配额,请参阅配额和限制