GoLand 2025.3 Help

CPU 分析器

GoLand 收集并可视化 CPU 分析、跟踪与堆分析数据。 为了收集所有必要的数据,GoLand 使用了 pprof 包。 GoLand 包含四种分析器,您可以通过用户界面运行它们:CPU、内存、阻塞(争用)和互斥锁。

分析结果可帮助您定位性能问题,但代码优化需手动实现。 如需了解详情,请参阅 go.dev 上的分析 以及 pkg.go.dev 上的 pprof 软件包说明

分析完成后,分析器会在报告中可视化结果。

在开始之前

在运行分析之前,请确保:

  • Go 已安装,您可通过 GOROOT 文章安装、升级或配置 Go。 欲了解更多信息,请参阅 GOROOT

  • GoLand 已在您的计算机上 安装

  • 您要分析的 Go 项目已在 IDE 中打开。

本主题中的所有示例均可在 GitHub 上的示例项目 中找到。

CPU 分析

CPU 分析器会测量每个函数在程序执行期间消耗的 CPU 时间。

示例程序

以下程序使用低效的冒泡排序算法对随机整数切片进行排序:

package main import ( "fmt" "math/rand" "time" ) func BubbleSort(nums []int) { for i := 0; i < len(nums); i++ { for j := 0; j < len(nums)-i-1; j++ { if nums[j] > nums[j+1] { nums[j], nums[j+1] = nums[j+1], nums[j] } } } } func main() { r := rand.New(rand.NewSource(time.Now().UnixNano())) nums := r.Perm(60000) BubbleSort(nums) fmt.Println("Sorted 60,000 numbers") }

您可以通过使用 go run main.go ,并在装订区域菜单中选择 运行 选项来运行此程序。

运行包含冒泡排序的程序

创建用于分析的测试

创建一个运行排序函数的单元测试:

package main import ( "math/rand" "testing" ) func TestBubbleSort(t *testing.T) { nums := rand.Perm(60000) BubbleSort(nums) }

运行 CPU 分析

  1. 打开 _test.go 文件。

  2. 点击测试函数旁边装订区域菜单中的 运行 选项。

  3. 请选择 使用 CPU 分析器进行分析

    运行 CPU 分析

分析 CPU 分析结果

GoLand 在三个视图中呈现 CPU 分析数据:

  • 火焰图 :可视化 CPU 时间如何分布在各个函数上。

    火焰图 选项卡显示函数调用以及每次调用所占的时间百分比。 每个块表示堆栈中的一个函数(一个堆栈框架)。 Y 轴显示调用堆栈深度(自底向上),而 X 轴表示按 CPU 使用量排序的函数,从资源消耗最多到最少的顺序排列。

    在阅读火焰图时,请关注最宽的块——它们表示的是最耗费 CPU 时间的函数。 将鼠标悬停在任意块上以查看详细信息。

    CPU 分析器中的火焰图
  • 调用树 :显示函数之间的调用关系以及每次调用所花费的时间。

    调用树 选项卡提供在分析过程中采样到的程序调用堆栈的详细信息,其中包括: 其中包括:

    • 方法名称

    • 总采样时间的百分比(可以切换为显示父调用时间)

    • 总采样计数

    • 过滤调用的数量

    CPU 分析器中的调用树视图
  • 方法列表 :以表格形式查看所有函数的累计执行时间和 CPU 总使用百分比。

    方法列表 选项卡列出分析数据中发现的所有方法,并按累计采样时间排序。每个方法项包括回溯树和合并被调用者树。 每个方法项包括一个回溯树和一个合并被调用者树。

    反向跟踪 选项卡显示调用者的层次结构,展示哪些方法调用了所选方法。 合并被调用者视图汇总了由所选函数调用的所有方法。

    合并的被调用者 选项卡显示从所选方法开始的调用轨迹。 被调用方列表 是汇总调用层次结构中所有方法的方法列表。

    CPU 分析器中的方法列表视图

在此示例中,大部分时间都花在了 BubbleSort 的嵌套循环中,这表明存在一个 O(n²) 瓶颈。

优化并比较结果

为提升性能,请将冒泡排序替换为快速排序,后者效率更高,平均时间复杂度为 O(n log n)。 在测试中,请将随机整数的数量增加到 1,000 万,以确保排序过程耗时可测量——否则,算法几乎会立即完成(大约 0.01 秒)。

func QuickSort(nums []int) { if len(nums) < 2 { return } quickSortHelper(nums, 0, len(nums)-1) } func quickSortHelper(nums []int, low, high int) { if low < high { pivotIndex := partition(nums, low, high) quickSortHelper(nums, low, pivotIndex-1) quickSortHelper(nums, pivotIndex+1, high) } } func partition(nums []int, low, high int) int { pivot := nums[high] i := low - 1 for j := low; j < high; j++ { if nums[j] <= pivot { i++ nums[i], nums[j] = nums[j], nums[i] } } nums[i+1], nums[high] = nums[high], nums[i+1] return i + 1 }

当您重新运行 CPU 分析器时,程序将大幅加快完成速度,并显著减少 CPU 时间的消耗——这清晰表明性能有所提升。

quicksort-example

为优化后的代码进行基准测试

为确认性能提升,请对两个实现进行基准测试:

func BenchmarkBubbleSort(b *testing.B) { for i := 0; i < b.N; i++ { nums := rand.Perm(1000) BubbleSort(nums) } } func BenchmarkQuicksort(b *testing.B) { for i := 0; i < b.N; i++ { nums := rand.Perm(1000) QuickSort(nums) } }

基准测试结果表明,相较于 BubbleSort()Quicksort() 的完成耗时大大缩短。

BenchmarkQuicksort 和 BubbleSort
最后修改日期: 2025年 12月 5日