go语言程序cpu过高问题排查的方法详解

 更新时间:2023年04月15日 16:18:34   作者:zoudaohoutianI  
使用golang进行复杂的组合运算,导致CPU占用率非常高,下面这篇文章主要给大家介绍了关于go语言程序cpu过高问题排查的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

一、前言

Go程序像C/C++一样,如果开发编码考虑不当,会出现cpu负载过高的性能问题。如果程序是线上环境或者特定场景下出现负载过高,问题不好复现,则需要利用当前负载过高的进程进行调用栈分析。

C/C++中一般先通过top -d 1 -p $pid -H 命令查看负载过高的线程号(TID),然后使用gdb attach到该进程,通过thread info获取线程信息,然后切换到对应负载高的线程,输入bt查看调用栈。

结合对应代码中的函数,进一步分析。Go语言中方法也类似,我们将通过dlv来分析负载高的协程调用栈。

二、问题排查过程

2.1 通过top查看高cpu的进程pid

通过top -d 1,可以发现进程cava_smu(pid=11205)的cpu过高。

2.2 通过top查看高cpu的线程tid

通过上一步,我们确定了是pid=11205的cava_smu进程cpu过高,那么可以通过top -d 1 -p 11205 -H 来确认cpu过载的线程tid,如下图所示:

通过以上操作,可以确认tid=11208,11212,11213三个线程的cpu过高。

2.3 通过dlv附加到进程,分析线程/协程cpu过载的堆栈

首先,如果生产环境没有dlv,则可以拷贝对应的dlv到/usr/local/bin下。

接着 dlv attach 11205,确认tid=11208的goroutine 序号,如下图所示:

2.4 在dlv中切换到对应高cpu协程,并查看堆栈

如下图所示:

通过以上操作,可以确认业务底层的栈帧是第6→5帧,business.go:18行的disPatchTask ->business.go:168 行的dispatchIdleTeu方法相关,查看对应版本代码如下:

代码执行到下图中,dispatchIdleTeu返回了错误qferror.ErrNoTeu。

代码执行到下图中,189行dispatchIdleTeu返回了错误qferror.ErrNoTeu,所以189 if的执行语句192~212无法进入进行,而外层是一个for死循环,则会造成该协程一直占用cpu,导致cpu过载。

修复方法可以是在for 循环内增加sleep休眠,例如在214行处增加time.Sleep(200 * time.Millisecond),效果请自行验证。

总结

到此这篇关于go语言程序cpu过高问题排查的文章就介绍到这了,更多相关go程序cpu过高排查内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • GoLang使goroutine停止的五种方法实例

    GoLang使goroutine停止的五种方法实例

    goroutine是Go并行设计的核心,下面这篇文章主要给大家介绍了关于GoLang使goroutine停止的五种方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • Golang拾遗之实现一个不可复制类型详解

    Golang拾遗之实现一个不可复制类型详解

    在这篇文章中我们将实现一个无法被复制的类型,顺便加深对引用类型、值传递以及指针的理解。文中的示例代码讲解详细,感兴趣的可以了解一下
    2023-02-02
  • Golang实现短网址/短链服务的开发笔记分享

    Golang实现短网址/短链服务的开发笔记分享

    这篇文章主要为大家详细介绍了如何使用Golang实现短网址/短链服务,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-05-05
  • Go语言构建流数据pipeline的示例详解

    Go语言构建流数据pipeline的示例详解

    Go的并发原语可以轻松构建流数据管道,从而高效利用 I/O 和多个 CPU, 本文展示了此类pipelines的示例,强调了操作失败时出现的细微之处,并介绍了干净地处理失败的技术,希望对大家有所帮助
    2024-02-02
  • 一文带你使用golang手撸一个websocket中间件

    一文带你使用golang手撸一个websocket中间件

    这篇文章主要为大家详细介绍了如何使用golang手撸一个websocket中间件,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以参考一下
    2023-12-12
  • Go接口的用法详解

    Go接口的用法详解

    本文主要介绍了Go接口的用法详解,包括定义接口、实现接口、使用接口、空接口等,通过接口,可以实现多态性,即一个对象可以实现多个接口,从而实现不同接口的行为,感兴趣的可以了解一下
    2023-11-11
  • Go并发编程之goroutine使用正确方法

    Go并发编程之goroutine使用正确方法

    并发编程有一种常见方式就是许多工作子协程都是独立的,互不干扰,但他们又是“同一时间”处理。本文重大给大家介绍Go并发编程goroutine使用方法,一起看看吧
    2021-09-09
  • go语言实现LRU缓存的示例代码

    go语言实现LRU缓存的示例代码

    LRU是一种常见的缓存淘汰策略,用于管理缓存中的数据,本文主要介绍了go语言实现LRU缓存的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Goland 关闭自动移除未使用的包操作

    Goland 关闭自动移除未使用的包操作

    这篇文章主要介绍了Goland 关闭自动移除未使用的包操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • go语言中if语句用法实例

    go语言中if语句用法实例

    这篇文章主要介绍了go语言中if语句用法,以实例形式分析了if语句的定义及使用技巧,非常具有实用价值,需要的朋友可以参考下
    2015-02-02

最新评论