常用调试golang的bug以及性能问题的实践方法

news2024/10/1 17:31:30

文章目录

  • 如何分析程序运行时间和CPU利用率情况
    • 1.shell内置time指令
    • /usr/bin/time指令
  • 如何分析golang程序的内存使用情况?
    • 1.内存占用情况查看
  • 如何分析golang程序的CPU性能情况
    • 1.性能分析注意事项
    • 2.CPU性能分析
      • A.Web界面查看
      • B.使用pprof工具查看

如何分析程序运行时间和CPU利用率情况

1.shell内置time指令

time是Unix/linux内置多命令,使用时一般不用传过多参数,直接跟上需要调试多程序即可。

$ time go run test2.go 
&{{0 0} 张三 0}

real	0m0.843s
user	0m0.216s
sys	0m0.389s

上面是使用time对 go run test2.go对执行程序坐了性能分析,得到3个指标。

● real:从程序开始到结束,实际度过的时间;
● user:程序在用户态度过的时间;
● sys:程序在内核态度过的时间。

一般情况下 real >= user + sys,因为系统还有其它进程(切换其他进程中间对于本进程会有空白期)

/usr/bin/time指令

这个指令比内置的time更加详细一些,使用的时候需要用绝对路径,而且要加上参数-v

$ /usr/bin/time -v go run test2.go  

	Command being timed: "go run test2.go"
	User time (seconds): 0.12
	System time (seconds): 0.06
	Percent of CPU this job got: 115%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.16
	Average shared text size (kbytes): 0
	Average unshared data size (kbytes): 0
	Average stack size (kbytes): 0
	Average total size (kbytes): 0
	Maximum resident set size (kbytes): 41172
	Average resident set size (kbytes): 0
	Major (requiring I/O) page faults: 1
	Minor (reclaiming a frame) page faults: 15880
	Voluntary context switches: 897
	Involuntary context switches: 183
	Swaps: 0
	File system inputs: 256
	File system outputs: 2664
	Socket messages sent: 0
	Socket messages received: 0
	Signals delivered: 0
	Page size (bytes): 4096
	Exit status: 0

可以看到这里的功能要强大多了,除了之前的信息外,还包括了:

● CPU占用率;
● 内存使用情况;
● Page Fault 情况;
● 进程切换情况;
● 文件系统IO;
● Socket 使用情况;
● ……

如何分析golang程序的内存使用情况?

1.内存占用情况查看

package main

import (
    "log"
    "runtime"
    "time"
)

func test() {
    //slice 会动态扩容,用slice来做堆内存申请
    container := make([]int, 8)

    log.Println(" ===> loop begin.")
    for i := 0; i < 32*1000*1000; i++ {
        container = append(container, i)
    }
    log.Println(" ===> loop end.")
}

func main() {
    log.Println("Start.")

    test()

    log.Println("force gc.")
    runtime.GC() //强制调用gc回收

    log.Println("Done.")

    time.Sleep(3600 * time.Second) //睡眠,保持程序不退出
}

编译

$go build -o snippet && ./snippet

然后在./snippet进程没有执行完,我们再开一个窗口,通过top命令查看进程的内存占用情况

$top -p $(pidof snippet_mem)

结果如下:
在这里插入图片描述
我们看出来,没有退出的snippet_mem进程有约830m的内存被占用。

直观上来说,这个程序在test()函数执行完后,切片contaner的内存应该被释放,不应该占用830M那么大。
结论:
1、在test()函数执行完后,demo程序中的切片容器所申请的堆空间都被垃圾回收器回收了。

2、如果此时在top指令查询内存的时候,如果依然是800+MB,说明垃圾回收器回收了应用层的内存后,(可能)并不会立即将内存归还给系统。

如何分析golang程序的CPU性能情况

1.性能分析注意事项

● 性能分析必须在一个
可重复的、稳定的环境中来进行。
○ 机器必须闲置
■ 不要在共享硬件上进行性能分析;
■ 不要在性能分析期间,在同一个机器上去浏览网页
○ 注意省电模式和过热保护,如果突然进入这些模式,会导致分析数据严重不准确
○ 不要使用虚拟机、共享的云主机,太多干扰因素,分析数据会很不一致;
○ 不要在 macOS 10.11 及以前的版本运行性能分析,有 bug,之后的版本修复了。

如果承受得起,购买专用的性能测试分析的硬件设备,上架。

● 关闭电源管理、过热管理;
● 绝不要升级,以保证测试的一致性,以及具有可比性。

如果没有这样的环境,那就一定要在多个环境中,执行多次,以取得可参考的、具有相对一致性的测试结果

2.CPU性能分析

利用以下代码进行测试:

package main

import (
    "bytes"
    "math/rand"
    "time"
    "log"
    "net/http"
    _ "net/http/pprof"
)


func test() {

    log.Println(" ===> loop begin.")
    for i := 0; i < 1000; i++ {
        log.Println(genSomeBytes())
    }

    log.Println(" ===> loop end.")
}

//生成一个随机字符串
func genSomeBytes() *bytes.Buffer {

    var buff bytes.Buffer

    for i := 1; i < 20000; i++ {
        buff.Write([]byte{'0' + byte(rand.Intn(10))})
    }

    return &buff
}

func main() {

    go func() {
        for {
            test()
            time.Sleep(time.Second * 1)
        }
    }()

    //启动pprof
    http.ListenAndServe("0.0.0.0:10000", nil)

}

这里面还是启动了pprof的监听,有关pprof启动的代码如下:

import (
    "net/http"
    _ "net/http/pprof"
)

func main() {
	//...
  //...
  
  //启动pprof
  http.ListenAndServe("0.0.0.0:10000", nil)
}

main()里的流程很简单,启动一个goroutine去无限循环调用test()方法,休眠1s.

test()的流程是生成1000个20000个字符的随机字符串.并且打印.

我们将上面的代码编译成可执行的二进制文件 demo4(记住这个名字,稍后我们能用到)

$ go build demo4.go

接下来我们启动程序,程序会无限循环的打印字符串.

接下来我们通过几种方式来查看进程的cpu性能情况.

A.Web界面查看

浏览器访问http://127.0.0.1:10000/debug/pprof/

我们会看到如下画面
在这里插入图片描述
这里面能够通过pprof查看包括(阻塞信息、cpu信息、内存堆信息、锁信息、goroutine信息等等), 我们这里关心的cpu的性能的profile信息.

有关profile下面的英文解释大致如下:

“CPU配置文件。您可以在秒GET参数中指定持续时间。获取概要文件后,请使用go tool pprof命令调查概要文件。”

所以我们要是想得到cpu性能,就是要获取到当前进程的profile文件,这个文件默认是30s生成一个,所以你的程序要至少运行30s以上(这个参数也可以修改,稍后我们介绍)

我们可以直接点击网页的profile,浏览器会给我们下载一个profile文件. 记住这个文件的路径, 可以拷贝到与demo4所在的同一文件夹下.

B.使用pprof工具查看

pprof 的格式如下:

go tool pprof [binary] [profile]

binary: 必须指向生成这个性能分析数据的那个二进制可执行文件;

profile: 必须是该二进制可执行文件所生成的性能分析数据文件。

binary 和 profile 必须严格匹配。

我们来查看一下:

$ go tool pprof ./demo4 profile

File: demo4
Type: cpu
Time: Mar 3, 2020 at 11:18pm (CST)
Duration: 30.13s, Total samples = 6.27s (20.81%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof)

help可以查看一些指令,我么可以通过top来查看cpu的性能情况.

(pprof) top
Showing nodes accounting for 5090ms, 81.18% of 6270ms total
Dropped 80 nodes (cum <= 31.35ms)
Showing top 10 nodes out of 60
      flat  flat%   sum%        cum   cum%
    1060ms 16.91% 16.91%     2170ms 34.61%  math/rand.(*lockedSource).Int63
     850ms 13.56% 30.46%      850ms 13.56%  sync.(*Mutex).Unlock (inline)
     710ms 11.32% 41.79%     2950ms 47.05%  math/rand.(*Rand).Int31n
     570ms  9.09% 50.88%      990ms 15.79%  bytes.(*Buffer).Write
     530ms  8.45% 59.33%      540ms  8.61%  syscall.Syscall
     370ms  5.90% 65.23%      370ms  5.90%  runtime.procyield
     270ms  4.31% 69.54%     4490ms 71.61%  main.genSomeBytes
     250ms  3.99% 73.52%     3200ms 51.04%  math/rand.(*Rand).Intn
     250ms  3.99% 77.51%      250ms  3.99%  runtime.memmove
     230ms  3.67% 81.18%      690ms 11.00%  runtime.suspendG
(pprof)

这里面有几列数据,需要说明一下.

● flat:当前函数占用CPU的耗时
● flat%::当前函数占用CPU的耗时百分比
● sum%:函数占用CPU的耗时累计百分比
● cum:当前函数加上调用当前函数的函数占用CPU的总耗时
● cum%:当前函数加上调用当前函数的函数占用CPU的总耗时百分比
● 最后一列:函数名称

通过结果我们可以看出, 该程序的大部分cpu性能消耗在 main.getSoneBytes()方法中,其中math/rand取随机数消耗比较大.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/348279.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PHP(12)文件上传

PHP&#xff08;12&#xff09;文件上传一、文件上传原理二、表单写法三、预定义变量 $_FILES四、移动临时文件五、多文件上传1. 同名表单2. 不同名表单六、多文件处理1. 同名文件2. 不同名文件七、封装文件上传函数一、文件上传原理 文件从客户机上传至服务器指定目录。 步骤…

Redhat7.6升级openssh(超详细)

一、准备工作 从官网下载新版的openssh-7.9p1.tar.gz 准备rhel-server-7.6-x86_64-dvd.iso用于使用yum安装依赖 二、具体升级步骤 1.查看系统版本 [rootredhat ~]# cat /etc/redhat-release Red Hat Enterprise Linux Server release 7.6 (Maipo) 2.查看openssh现有版本 …

金三银四面试必看,自动化测试如何解决日志问题

前言 前几天在员群里&#xff0c;有同学问了一个自动化测试实践中遇到的问题&#xff1a; 持续集成的自动化用例很多&#xff0c;测试环境日志level为debug&#xff0c;日志量大概40G/每天&#xff0c;定位问题时日志查询很慢&#xff0c;该怎么解决&#xff1f; 这个问题可…

pytorch基础入门教程

pytorch基础入门教程 Pytorch一小时入门教程 前言 机器学习的门槛并没有想象中那么高&#xff0c;我会陆续把我在学习过程中看过的一些文章和写过的代码以博客的形式分享给大家&#xff0c;和大家一起交流&#xff0c;这个是本系列的第一篇&#xff0c;pytoch入门教程&#x…

软件测试2-测试必须有策略和测试有哪些最高原则

什么是软件测试测试是为发现错误而执行程序的过程。软件测试一个破坏性的过程&#xff0c;甚至是一个施虐的过程&#xff0c;也就是第一天说的“找茬”游戏。 当一个输入框让我输入手机号码时&#xff0c;我偏不&#xff0c;我要输入非手机号码&#xff0c;甚至不填。 当界面提…

定时任务使用总结

定时任务表达式生成工具网站&#xff1a;https://cron.qqe2.com/定时任务选型&#xff1a;xxl-job 官方文档&#xff1a;https://www.xuxueli.com/xxl-job/安装定时任务调度中心 xxl-job-admin第一步、先导入xxl-job的数据库&#xff1a;地址&#xff1a;https://gitee.com/xux…

2.2 多区域集成IS-IS

2.2.2 实验二:多区域集成IS-IS 1. 实验目的  实现IS-IS协议DIS优先级修改 实现IS-IS协议网络类型修改 实现IS-IS协议外部路由引入 实现IS-IS接口cost修改 实现IS-IS路由渗透配置2. 实验拓扑 配置多区域集成IS-IS如图2-5所示: …

Java 万年历、周六日计算、节假日导出

目录 通过 Java 的基本语法来实现万年历 Java 获取一年中所有的周六和周日 Java 节假日导入导出 通过 Java 的基本语法来实现万年历 在 Java 的时间计算方面还有很多好用的工具类&#xff0c;Java 常用的工具类封装框架链接如下&#xff1a;HUTool 框架官网 package com.ta…

企业降本增效的催化剂:敏捷迭代

伴随着开源技术的大爆发&#xff0c;新一代的软件技术如雨后春笋般层出不穷。每家企业在硬件及软件开发上都有许多开源技术可选&#xff0c;目的还是在于提高效率&#xff0c;降低开发成本。 本篇文章&#xff0c;带大家了解下促进企业降本增效的重要理念&#xff1a;敏捷迭代…

前端错误/性能监控(vue)

配置目录结构 错误监听&#xff1a;可以提前发现前端的错误&#xff0c;并且找到对应的位置进行修改。因为等等环境因素可能导致不同的问题&#xff0c;这些问题难以发现&#xff0c;影响用户体验。 性能监听&#xff1a;可以及时发现问题&#xff0c;比如下载的js文件、image时…

Stream流源码分析及技巧(含大量案例)

Stream流源码分析及技巧&#xff08;含大量案例&#xff09; 目录 Stream流源码分析及技巧&#xff08;含大量案例&#xff09; 更新说明 简介&#xff08;这部分摘了部分官方文档&#xff09; 特性 Stream接口关系图 Stream流接口方法 Stream流之间的转换 与Stream流相…

华为OD面试经验分享,尤其注意机试题部分

文章目录招聘流程和背景介绍面试准备机试题目类型和解答技巧在算法部分在操作系统部分面试官提问和答题技巧面试总结和建议推荐一些华为 od 常见的机试题题目&#xff1a;两数之和题目&#xff1a;二叉树的遍历题目&#xff1a;链表反转题目&#xff1a;最大子序和招聘流程和背…

解决QML debugging is enabled.Only use this in a safe environment.警告

系列文章目录 文章目录系列文章目录前言一、警告原因二、解决办法参考前言 我试图运行一个非常简单的程序&#xff0c;当单击退出按钮时关闭窗口&#xff0c;但获取以下输出&#xff0c;前提是包含按钮的应用程序窗口不显示&#xff1a; 您已启用QML调试(实际上它默认启用)&…

CleanMyMac4.12.5最新版Mac系统清理优化工具

CleanMyMac X可以优化Mac系统。mac系统用久了&#xff0c;用CleanMyMac清理一下效果还不错。可用来清理系统的缓存、日志、语言和垃圾文件&#xff0c;还能卸载应用程序。小编给您带来cleanmymac中文版&#xff0c;CleanMyMac是一款Mac系统清理优化工具&#xff0c;使用只需两个…

Java中Synchronized关键字的基本使用方法

Java中Synchronized关键字的基本使用方法 1.简介 Synchronized是java的关键字&#xff0c;synchronized可以保证在同一个时刻&#xff0c;只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作)&#xff0c;synchronized可保证一个线程的变…

动态规划【Day01】| 669 · 换硬币、114 · 不同的路径、116 · 跳跃游戏

秘诀&#xff1a;确定状态转移方程初始条件和边界情况计算顺序 669 换硬币 669 换硬币 题目描述&#xff1a; 给出不同面额的硬币以及一个总金额. 写一个方法来计算给出的总金额可以换取的最少的硬币数量. 如果已有硬币的任意组合均无法与总金额面额相等, 那么返回 -1。 样…

元宇宙将如何彻底改变 K-12 和高等教育

欢迎来到Hubbleverse &#x1f30d; 关注我们 关注宇宙新鲜事 &#x1f4cc; 预计阅读时长&#xff1a;9分钟 本文仅代表作者个人观点&#xff0c;不代表平台意见&#xff0c;不构成投资建议。 想象一下&#xff0c;你将作为一个微小的细胞去参观人类的循环系统。这只是元宇…

基于django搭建简单的个人博客

文章目录第一步、在Ubuntu中安装虚拟环境并进入第二步、安装blog所需要的包&#xff0c;在requirements.txt中安装mysqlclient可能会报错&#xff0c;输入下列命令后在安装即可成功第三步、创建好数据库&#xff0c;把测试数据导入第四步、修改DjangoBlog包中 settings中数据库…

企业如何做好EHS环境健康安全管理?

目前随着传统制造业企业安全管理制度的落实&#xff0c;工人的安全意识得到很大的提升&#xff0c;但企业内部的安全管理制度并不能完全避免意外发生。如受限空间人员闯入、特种设备伤人、人员作业不规范、危化品泄露、仓储车间发生火情、有毒有害气体超标等一系列安全隐患。对…

leaflet 修改popup的样式,个性化弹窗(069)

第069个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中修改popup组件的样式,个性化弹窗。主要方法是更改css, 中增加custom-popup类名,style的样式要做穿透处理 >>>.具体方法请参考源代码。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实…