Go程序GC优化经验分享

Go语言性能优化:从GC调优到pprof分析 通过GC调优和pprof分析,可以有效地优化Go语言的性能。在实际项目中,建议结合使用这两种方法,定期进行性能测试和分析,找到性能瓶颈并进行针对性的优化。同时,保持代码的可读性和可维护性也是优化过程中需要注意的重要方面。希望本文的分享能够帮助大家更好地优化Go语言应用的性能。 阅读详情

作者:达达

来源:http://1234n.com/?post/yzsrwa

最近一段时间对《仙侠道》的服务端进行了一系列针对GC的调优,这里跟各位分享一下调优的经验。

游戏第一次上线的时候,大部分精力都投入在做cpuprof和memprof找性能瓶颈和内存泄漏上,没有关注过Go的GC运行情况。

有一次cpuprof里的scanblock调用所占的比例让我注意到Go的GC所带来的性能消耗,记得那份cpuprof里,scanblock调用占到49%。也就是说有一半的CPU时间浪费在了GC上。

于是我开始研究如何进行优化,过程中免不了要分析数据,经过一番搜索,我好到了GOGCTRACE这个环境变量。

用法类似这样:

GOGCTRACE=1 ./my_go_program 2> log_file

通过这个环境变量可以让Go程序在每次GC时都输出信息,信息是输出到标准错误的,所以需要用 2> 把输出重定向到文件里。

输出的内容像这样:

gc16(8): 34+6+5 ms, 367 -> 365 MB 817253 -> 782045 (18216892-17434847) objects, 64(2182) handoff, 72(22022) steal, 553/244/51 yields

其中gc16表示第16次进行GC,后面的(8)表示由8个线程执行,这个线程数对应GOMAXPROCS环境变量,34+6+5 ms分别代表一系列GC动作消耗的时间,这三个时间加起来45ms,就是这个程序在这次GC过程中暂停的时间。

后面接着的是内存、对象数量等,在GC前后的变化,其中最关键的是对象数量,这边可以看到GC后还有782045个对象存在。

我在实际游戏服和内网开发测试服都开启了GOGCTRACE,发现GC暂停时间相差甚大,当时(还未做第一次优化前)外网GC暂停达到400多ms,而内网才20ms。

显然跟内存中数据多少有关系,于是我推测跟内存中对象数量关系最大,原因很简单,假设我是GC开发者,不可能让一个对象占用100M内存跟一万个对象占用100M内存同样消耗性能,显然那一个占用100M内存的对象,当我发现它不需要回收的话,我就不需要做什么事情了,而那一万个对象,我需要逐个检查是否还有被引用,所以内存大小不是关键,对象数量才是关键。

于是我按这个推测进行了第一次性能优化,我把存储游戏内存数据的链表结构改为slice,当初设计成链表是因为数据有插入和删除,slice可以扩容但是要收缩就比较麻烦了,于是想到了链表,链表要删除单个节点的时候,只需要把节点从链表上断开,不需要复制数据,效率高于数组结构。这里直观的表示一下两种数据结构的区别:

    type MyData1 struct {
        next *MyData
        Id   int
        Name string
    }

    var mydata1 *MyData1

    type MyData2 struct {
        Id   int
        Name string
    }

    var mydata2 []MyData2

上面示例代码的mydata1用的是链表结构,每个节点都有一个指向下一个节点的指针,想像下存储1万个对象到mydata1,是不是需要创建1万个MyData1类型的对象。

示例中的mydata2用的是slice结构,一个slice就是一个对象,其中的元素都是这一块内存中的值,而不是对象,需要注意 []MyData2 和 []*MyData2 是不一样的,如果换用第二种写法,那么每个元素一样都是一个对象,因为这时候slice存的不是值而是指向对象的指针,而这些指针每一个都分别指到一个对象。

我做了一组不同数据结构跟对象数量关系的实验,可以直观的感受区别:github链接

经过这番改造,对象数量少了一个数量级,具体对少对象我已经记不得了,但是可以自己估计一下,一个mydata1这样的内存表,假设平均20条记录,假设有50个这样的表,就是1000个对象,换成mydata2这样的内存表,就只要50个对象。

当然这样一换,内存占用肯定就上去了,但是实际观测下来,内存占用在可接收范围,甚至还是远小于之前我用erlang开发的游戏,而GC扫描时间从300多ms降到几十ms,降了一个数量级。

本来优化到此我就打算告一段落了,但是随着游戏的持续运行,数据的持续增加,我发现slice自身占用的对象数量也还是值得动动脑筋消除掉的,线上GC暂停时间最高的服务器,达到了100ms,如果再涨上去,一样还是可能达到200ms设置300ms。

所以又继续懂了一些脑筋,比如把玩家数据压缩起来,等需要用的时候再解开来用,尝试过json序列化等等,目的都是把多个对象归并成一个。

但是这些方案都是牺牲数据访问的效率为代价的,需要访问数据时就要反序列化展开数据。

其实在第一次优化时,我大部分时间花在尝试cgo上面,而不是尝试slice上,我第一个思路是用cgo申请内存,伪造成go的对象,这些对象就不受Go的GC管理里,也就不会对GC有负担。但是尝试下来,总是遇到各种指针异常,我可以确信不是我的指针运算问题,但是为什么自己申请的内存会影响到Go的执行,我一直弄不明白,时间不等人,不可能一直研究下去,所以我才想了slice的这个方案,不是最优解但至少暂时解决问题。

而这一次,因为使用了slice,原先的内存数据库的数据结构就变得很单一,而优化的目的也明显,减少slice的内存消耗。正好那阵子我在尝试将SpiderMonkey嵌入到Go,接触到了cgo操作slice的一些技巧,比如将C的数组映射成Go的slice,或者利用reflect.SliceHeader取得slice所指向的内存块地址,然后用cgo复制数据。

于是我就想到用C来申请slice所需内存块,然后自己构造SliceHeader的办法。

这里需要说明下SliceHader和slice之间的关系。

Go提供了一个很有用的数据结构slice,slice比起C时代的数值有很明显的优势,有边界判断、可以反复切割、没有牺牲运行效率,如何做到的呢?官方这片文章有很清楚的说明:点击查看

简单说来,Go的slice其实是一个三个字段的结构体,三个字段分别存放着slice的当前长度、内存块的大小和实际内存块的地址,每次len(slice)的时候是不需要循环计算长度的,只是到结构体里去一下长度,而重新切割的过程,只是重新构造一个指向同一个内存块或块中某一位置的过程,所以不会有内存拷贝和循环等消耗性能的操作。

这个三个字段的结构体,在Go的反射包里面使用SliceHeader类型表示,这让我们的程序有机会构造自己的SliceHeader。

cgo的wiki文档里有这样一段示例代码,演示如何把C的数组包装成Go的slice:

import "C"
import "unsafe"
...
        var theCArray *TheCType := C.getTheArray()
        length := C.getTheArrayLength()
        var theGoSlice []TheCType
        sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&theGoSlice)))
        sliceHeader.Cap = length
        sliceHeader.Len = length
        sliceHeader.Data = uintptr(unsafe.Pointer(&theCArray[0]))
        // now theGoSlice is a normal Go slice backed by the C array

这边用到了unsafe.Pointer,通过Pointer类型,我们可以在Go的程序里实现指针运算,之前我有写过相关文章,这里就不重复介绍了:点击查看

于是我将内存数据库用到的slice类型全部换成自己用C伪造的slice,还好当初内存数据库用的是代码生成器,否则代码就要改死掉了 :)

全部替换完后,我拿外网同样数据对比,优化前的程序GC扫描时间100多ms,对象数量140万,优化后的程序GC扫描时间18ms,对象数量16万。

本来可以就这样打完收功了,但是生活总是充满戏剧性,内网测试的时候发现好友列表里面的名字全乱码了,肯定跟优化有关系,但为什么会乱码呢?

我的推测是go构造的字符串对象被C构造的对象引用,这样的引用导致go把字符串对象当成没人使用,于是就被回收利用了。

我只好把所有字符串字段也全部改为C伪造的对象,原理给伪造slice是一样的,不同的是字符串用StringHeader表示。

经过改造,字符串再也不会乱码了,不过需要很小心的释放内存。

优化过程中Go提供的pprof模块起到了很重要的作用,所有的优化都是以数据为依据的,如果不能看到数据就没有办法定位问题。

程序中可以用 pprof.Lookup("heap") 来获得堆信息,其中包含了对象数量和GC执行时间等有用的数据。

上次群里有人问 map[int]XXX 这样的数据结构是否会有GC问题,正好这个数据结构我之前也考虑过,也在上面的数据结构实验里体现了,map[int]XXX 和 map[int]XXX是一样的,一条数据就是一个对象,对GC是否有影响取决于对象的数量。

从上面的观测数值来看百来万的对象数量所造成的暂停应该还不足以影响程序,除非应用场景对实时性要求非常高。

但是对于游戏这样的常驻内存程序来说,对象的增长速度和对象数量上限也需要留意,比如刚开始对象数量只有几万,随着日子增长,玩家数据增多,对象数量达到百万千万,那时候可能就会有影响了。

之前第一次优化过后正好有人在知乎问Go的GC情况,我回了一帖,里面有比较详细的第一次优化的数据,大家可以参考一下:点击查看





Go 的垃圾回收机制在实践中有哪些需要注意的地方?



来源:http://www.zhihu.com/question/21615032/answer/18781477


不想看长篇大论的,这里先给个结论,go的gc还不完善但也不算不靠谱,关键看怎么用,尽量不要创建大量对象,也尽量不要频繁创建对象,这个道理其实在所有带gc的编程语言也都通用。

想知道如何提前预防和解决问题的,请耐心看下去。

先介绍下我的情况,我们团队的项目《仙侠道》在7月15号第一次接受玩家测试,这个项目的服务端完全用Go语言开发的,游戏数据都放在内存中由go 管理。

在上线测试后我对程序做了很多调优工作,最初是稳定性优先,所以先解决的是内存泄漏问题,主要靠memprof来定位问题,接着是进一步提高性能,主要靠cpuprof和自己做的一些统计信息来定位问题。

调优性能的过程中我从cpuprof的结果发现发现gc的scanblock调用占用的cpu竟然有40%多,于是我开始搞各种对象重用和尽量避免不必要的对象创建,效果显著,CPU占用降到了10%多。

但我还是挺不甘心的,想继续优化看看。网上找资料时看到GOGCTRACE这个环境变量可以开启gc调试信息的打印,于是我就在内网测试服开启了,每当go执行gc时就会打印一行信息,内容是gc执行时间和回收前后的对象数量变化。

我惊奇的发现一次gc要20多毫秒,我们服务器请求处理时间平均才33微秒,差了一个量级别呢。

于是我开始关心起gc执行时间这个数值,它到底是一个恒定值呢?还是更数据多少有关呢?

我带着疑问在外网玩家测试的服务器也开启了gc追踪,结果更让我冒冷汗了,gc执行时间竟然达到300多毫秒。go的gc是固定每两分钟执行一次,每次执行都是暂停整个程序的,300多毫秒应该足以导致可感受到的响应延迟。

所以缩短gc执行时间就变得非常必要。从哪里入手呢?首先,可以推断gc执行时间跟数据量是相关的,内网数据少外网数据多。其次,gc追踪信息把对象数量当成重点数据来输出,估计扫描是按对象扫描的,所以对象多扫描时间长,对象少扫描时间短。

于是我便开始着手降低对象数量,一开始我尝试用cgo来解决问题,由c申请和释放内存,这部分c创建的对象就不会被gc扫描了。

但是实践下来发现cgo会导致原有的内存数据操作出些诡异问题,例如一个对象明明初始化了,但还是读到非预期的数据。另外还会引起go运行时报申请内存死锁的错误,我反复读了go申请内存的代码,跟我直接用c的malloc完全都没关联,实在是很诡异。

我只好暂时放弃cgo的方案,另外想了个法子。一个玩家有很多数据,如果把非活跃玩家的数据序列化成一个字节数组,就等于把多个对象压缩成了一个,这样就可以大量减少对象数量。

我按这个思路用快速改了一版代码,放到外网实际测试,对象数量从几百万降至几十万,gc扫描时间降至二十几微秒。

效果不错,但是要用玩家数据时要反序列化,这个消耗太大,还需要再想办法。

于是我索性把内存数据都改为结构体和切片存放,之前用的是对象和单向链表,所以一条数据就会有一个对象对应,改为结构体和结构体切片,就等于把多个对象数据缩减下来。

结果如预期的一样,内存多消耗了一些,但是对象数量少了一个量级。

其实项目之初我就担心过这样的情况,那时候到处问人,对象多了会不会增加gc负担,导致gc时间过长,结果没得到答案。

现在我填过这个坑了,可以确定的说,会。大家就不要再往这个坑跳了。

如果go的gc聪明一点,把老对象和新对象区别处理,至少在我这个应用场景可以减少不必要的扫描,如果gc可以异步进行不暂停程序,我才不在乎那几百毫秒的执行时间呢。

但是也不能完全怪go不完善,如果一开始我早点知道用GOGCTRACE来观测,就可以比较早点发现问题从而比较根本的解决问题。但是既然用了,项目也上了,没办法大改,只能见招拆招了。

总结以下几点给打算用go开发项目或已经在用go开发项目的朋友:
1、尽早的用memprof、cpuprof、GCTRACE来观察程序。
2、关注请求处理时间,特别是开发新功能的时候,有助于发现设计上的问题。
3、尽量避免频繁创建对象(&abc{}、new(abc{})、make()),在频繁调用的地方可以做对象重用。
4、尽量不要用go管理大量对象,内存数据库可以完全用c实现好通过cgo来调用。

手机回复打字好累,先写到这里,后面再来补充案例的数据。

数据补充:

图1,7月22日的一次cpuprof观测,采样3000多次调用,数据显示scanblock吃了43.3%的cpu。

图2,7月23日,对修改后的程序做cpuprof,采样1万多次调用,数据显示cpu占用降至9.8%

数据1,外网服务器的第一次gc trace结果,数据显示gc执行时间有400多ms,回收后对象数量1659922个:

gc13(1): 308+92+1 ms , 156 -> 107 MB 3339834 -> 1659922 (12850245-11190323) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields

数据2,程序做了优化后的外网服务器gc trace结果,数据显示gc执行时间30多ms,回收后对象数量126097个:
gc14(6): 16+15+1 ms, 75 -> 37 MB 1409074 -> 126097 (10335326-10209229) objects, 45(1913) handoff, 34(4823) steal, 455/283/52 yields


示例1,数据结构的重构过程:

最初的数据结构类似这样
// 玩家数据表的集合
type tables struct {
        tableA *tableA
        tableB *tableB
        tableC *tableC
        // ...... 此处省略一大堆表
}

// 每个玩家只会有一条tableA记录
type tableA struct {
        fieldA int
        fieldB string
}

// 每个玩家有多条tableB记录
type tableB struct {
        xxoo int
        ooxx int
        next *tableB  // 指向下一条记录
}

// 每个玩家只有一条tableC记录
type tableC struct {
        id int
        value int64
}

最初的设计会导致每个玩家有一个tables对象,每个tables对象里面有一堆类似tableA和tableC这样的一对一的数据,也有一堆类似tableB这样的一对多的数据。

假设有1万个玩家,每个玩家都有一条tableA和一条tableC的数据,又各有10条tableB的数据,那么将总的产生1w (tables) + 1w (tableA) + 1w (tableC) + 10w (tableB)的对象。

而实际项目中,表数量会有大几十,一对多和一对一的表参半,对象数量随玩家数量的增长倍数显而易见。

为什么一开始这样设计?

1、因为有的表可能没有记录,用对象的形式可以用 == nil 来判断是否有记录
2、一对多的表可以动态增加和删除记录,所以设计成链表
3、省内存,没数据就是没数据,有数据才有对象

改造后的设计:

// 玩家数据表的集合
type tables struct {
        tableA tableA
        tableB []tableB
        tableC tableC
        // ...... 此处省略一大堆表
}

// 每个玩家只会有一条tableA记录
type tableA struct {
        _is_nil bool
        fieldA int
        fieldB string
}

// 每个玩家有多条tableB记录
type tableB struct {
        _is_nil bool
        xxoo int
        ooxx int
}

// 每个玩家只有一条tableC记录
type tableC struct {
        _is_nil bool
        id int
        value int64
} 

一对一表用结构体,一对多表用slice,每个表都加一个_is_nil的字段,用来表示当前的数据是否是有用的数据。

这样修改的结果就是,一万个玩家,产生的对象总量是 1w (tables) + 1w ([]tablesB),跟之前的设计差别很明显。

但是slice不会收缩,而结构体则是一开始就占了内存,所以修改后会导致内存消耗增大。

参考链接:

go的gc代码,scanblock等函数都在里面:
http://golang.org/src/pkg/runtime/mgc0.c

go的runtime包文档有对GOGCTRACE等关键的几个环境变量做说明:
golang.org/pkg/runtime/

如何使用cpuprof和memprof,请看《Profiling Go Programs》:
blog.golang.org/profili

我做的一些小试验代码,优化都是基于这些试验的数据的,可以参考下:
github.com/realint/labs
Golang 性能优化实战 作者:trumanyan,腾讯 CSIG 后台开发工程师项目背景网关服务作为统一接入服务,是大部分服务的统一入口。为了避免成功瓶颈,需要对其进行尽可能地优化。因此,特别总结一下 gola... 阅读详情

相关推荐

超详细neo4j安装教程

一、neo4j简介 最近开始学习知识图谱,所以首先想先学习一下neo4j的使用。 Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。由于知识图谱中存在大量的关系型信息(实体—关系—实体), 使用结构化数据库进行存储将产生大量的冗余存储信息, 因此将图数据库作为知识图谱的存储容器成为流行的选择。当前较为常用的图数据库主要有 Neo4j 等。 二、neo4j的安装 功能快捷键 撤销:Ctrl/Command + Z 重做:Ctrl/Command + Y 加粗:Ctrl/Co

qq_38335648的博客 9万+

性能优化 | Go Ballast 让内存控制更加丝滑

关于 Go GC 优化的手段你知道的有哪些?比较常见的是通过调整 GC 的步调,以调整 GC 的触发频率。设置 GOGC设置 debug.SetGCPercent()这两种方式的原理和效果都是一样的,GOGC 默认值是 100,也就是下次 GC 触发的 heap 的大小是这次 GC 之后的 heap 的一倍。我们都知道 GO 的 GC 是标记-清除方式,当 GC 会触发时全量遍历变量进行标记,当标记结束后执行清除,把标记为白色的对象执行垃圾回收。值得注意的是,这里的回收仅仅是标记内存可以返回给操作系统,并不

haohongfan的博客 1013

OpenCv案例(七): 基于OpenCvSharp计算图像的清晰度(自动对焦)

自动对焦,其实是对相机成像的清晰值得计算,若对焦不清晰,成像的清晰度低,视觉效果模糊。若是在工业检测行业,对焦不准确,可能会造成严重后果;对焦准确的图像,其清晰度高,对比度鲜明,层次明显。

qq_37835727的博客 7113

如何优化golang gc

通常,当使用堆管理器来管理内存时,垃圾回收时需要在堆中移动和调整不同的内存块,这会导致大量的内存拷贝。可以适当调整runtime.GOGC的值来减少GC的频率,根据应用程序的工作负载和内存使用模式,应适当调整该变量。GO语言采用的是三色标记法垃圾回收算法,这种算法采用的是并发标记,扫描完成后再进行清除工作,这意味着性能上可能会付出一些代价。虽然这不是最激进的解决方案,但它可以有效地减少GC的延迟。到目前为止,gc的标记工作(包括两次mark阶段的STW和并发标记)所用的CPU时间占总CPU的百分比。

王安的博客 1937

华硕ROG玩家国度安装Ubuntu双系统避坑指南:安全启动密钥那些事儿

本文详细解析了在华硕ROG玩家国度设备上安装Ubuntu双系统时,如何正确处理BIOS中的安全启动(Secure Boot)与密钥管理,避免常见的引导失败和Windows系统无法启动问题。指南提供了从数据备份、启动盘制作到BIOS精细设置(如将OS Type改为Other OS而非简单关闭Secure Boot)以及分区规划的完整流程,确保两个系统都能稳定共存。

weixin_29219189的博客 752

比亚迪 10C 闪充技术全解析:超高速离子通道与双电子流设计如何颠覆电动车补能格局?

性能碾压主流方案参数宁德时代6C比亚迪10C优势幅度最大电流700A1000A+43%内阻降幅30%50%+67%5分钟补能240公里400公里+67%

百态·数智思维 | 聚焦大数据、量化与未来AI 1119

[转]Go程序GC优化经验分享

作者:达达来源:http://1234n.com/?post/yzsrwa最近一段时间对《仙侠道》的服务端进行了一系列针对GC的调优,这里跟各位分享一下调优的经验。游戏第一次上线的时候,大部分精力都投入在做cpuprof和memprof找性能瓶颈和内存泄漏上,没有关注过Go的GC运行情况。有一次cpuprof里的scanblock调用所占的比例让我注意到Go的GC所带来的性能消耗,记得那份cpup

heiyeluren的blog(黑夜路人的开源世界) 1万+

解决TexStudio编写LaTeX论文引用文献问题:正文引用处出现[?],参考文献也不显现

当我们利用LaTeX编写论文时,可能会出现引用参考文献时正文引用处出现?号,肯能的原因及解决方案如下: 问题一 忘记在\end{document}前面放\bibliographystyle{样式}和\bibliography{参考文献bib文件名}: \bibliographystyle{plain} \bibliography{sample} 其中, LaTeX 标准选项及其样式共有以下8种: plain,按字母的顺序排列,比较次序为作者、年度和标题. unsrt,样式同plain,只是按照引用的先后

左手の明天的博客 9527

go的gc机制,内存泄漏和内存逃逸,怎样才能最大减少gc的负担?

gc也就是垃圾回收。最近写的项目,pprof查看性能,发现在gc的消耗非常大,因此想着深入调研一下go的gc模式,了解在写程序时保持哪些好的代码习惯,才能最大的减少程序的gc调用。 gc是什么 了解的同学可以直接跳过。 GC Garbage Collection。直译过来就是垃圾回收。想要进行程序调优,是肯定避不开这个环节的,gc管理不好,很容易造成程序的内存无限增长,然后被系统杀掉,上线的项目发生内存泄漏,肯定是p0级别的问题了。 一般写的程序中会用到两种内存,堆内存和栈内存。堆内存就是堆状数据结

Aiky哇 4097

C#实现低通和高通滤波算法

低通滤波器允许通过低于某个截止频率的信号成分,并且抑制高于该频率的成分。而高通滤波器则允许通过高于某个截止频率的信号成分,并抑制低于该频率的成分。巴特沃斯滤波器是一种对称的滤波器,具有平坦的幅度响应和最小的群延迟。低通和高通滤波是数字信号处理中常用的滤波技术,用于滤除或增强信号中的特定频率成分。在本篇文章中,我们将使用C#编程语言来实现低通和高通滤波算法。以上就是使用C#实现低通和高通滤波算法的示例代码。你可以根据自己的需求调整截止频率和采样率,将这些代码应用于你的项目中。是滤波器的截止频率,

XisVisual_Basic的博客 1273

高频注入是否需要对齐和强拖操作?

高频注入技术显著优化了传统FOC启动流程,但仍需部分对齐操作。传统启动必须包含位置检测、对齐和强拖等步骤,而高频注入可实现零速闭环,简化或跳过部分环节。高频注入下的对齐主要用于验证有效性、初始化观测器和建立初始磁链,形式可大幅简化。虽然高频注入基本消除了传统强拖需求,但在重载、弱凸极等特殊情况下仍需辅助。实际应用中可采用自适应混合策略,根据负载和电机类型选择最优启动方案。高频注入使对齐和强拖从"必须"变为"可选优化项",是无传感器控制的重要进步。

汽车软件开发 204

40分钟学 Go 语言高并发:GC原理与优化

减少分配避免不必要的内存分配重用对象预分配内存控制GC合理设置GOGC监控GC指标及时调优代码优化使用正确的数据结构避免内存泄露保持代码简洁。

weixin_40780178的博客 1418

64、5G 侧链通信技术详解

本文详细解析了5G侧链通信的关键技术,包括资源感知与选择、UE间协调、混合ARQ、功率控制、信道探测与CSI报告以及侧链同步。资源感知与选择通过周期性或随机方式实现资源分配,UE间协调通过主动或被动方式避免资源冲突。混合ARQ机制确保数据传输可靠性,功率控制和信道探测优化传输质量并减少干扰。侧链同步则通过多种方式确保设备间时间一致性。这些技术相互配合,构建了高效稳定的5G侧链通信体系,适用于智能交通、物联网、应急通信等多个领域,为未来无线通信发展提供强大支撑。

oil88的博客 99

转 Go程序GC优化经验分享

转 Go程序GC优化经验分享

gfyufffb的博客 302

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Go程序内存占用分析与监控方法

通过本文的学习,我们已经掌握了Go程序内存分析与监控的基本方法和实践技巧。这些知识和技能将帮助你构建更加高效和稳定的Go应用。

sinat_27016095的博客 1304

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Go语言 GC优化经验分享

不想看长篇大论的,这里先给个结论,go的gc还不完善但也不算不靠谱,关键看怎么用,尽量不要创建大量对象,也尽量不要频繁创建对象,这个道理其实在所有带gc的编程语言也都通用。 想知道如何提前预防和解决问题的,请耐心看下去。 我们项目的服务端完全用Go语言开发的,游戏数据都放在内存中由go 管理。 在上线测试后我对程序做了很多调优工作,最初是稳定性优先,所以先解决的是内存泄漏问题,主要靠me...

mojolang 1422

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

golang GC相关调试参数

1. pprof生成CPU和memory profile 前段时间项目中遇到golang程序的性能上不去,想要找到程序的性能瓶颈所在,使用golang自带的pprof输出cpu和mem的profile文件进行分析。 具体如何生成profile文件参考如下: https://golang.org/pkg/runtime/pprof/ https://blog.golang.org/profiling...

辰若寒的博客 1万+

full gc什么时候触发_浅尝Go语言GC

大家好,我是小栈君,因为个人和工作的缘故,所以拖更了一点时间,但是关于拖更的内容小栈君会在后续的时间中补回来,还希望大家继续支持和关注小栈君。当然,在国内疫情稍微减缓的情况下,小栈君在这里也多说两句,在非常时刻,我们应当保持警惕,清洗手,多通风,避免人群聚集,希望大家平安健康,闲话不多说,我们直接进入正题,今天给大家分享的事关于Go语言中的GC,本期的分享并没有多少代码可言,都是一些理论知识,希望...

weixin_39629631的博客 482

golang 内存优化_Go系统的内存优化

golang 内存优化介绍(Introduction) Despite its growing popularity as a systems language, Go programs are susceptible to severe performance regressions at large scale. In systems with high memory usage, garba...

weixin_26716079的博客 1724

golang 关闭gc 并手动gc_go语言的垃圾回收(GC)概述

垃圾回收是高级语言的一个进步,其算法目前有几种经典的算法,说go的GC之前先说一下所有的GC的算法:引用计算法:每一个对象都有一个计数器,当这个对象被引用一次时,计数器加一,减少一次引用时,计数器减一,这样当对象的计数器为0时,我们就可以进行回收了。PHP、Object等在使用。优点:回收快,算法简单,不需要STW(Stop The World,挂起程序)缺点:相互引用时无法回收,计数器增加消耗。...

weixin_42504279的博客 941

浅尝Go语言GC

大家好,我是小栈君,因为个人和工作的缘故,所以拖更了一点时间,但是关于拖更的内容小栈君会在后续的时间中补回来,还希望大家继续支持和关注小栈君。当然,在国内疫情稍微减缓的情况下,小栈君在这里也多说两句,在非常时刻,我们应当保持警惕,清洗手,多通风,避免人群聚集,希望大家平安健康, 闲话不多说,我们直接进入正题,今天给大家分享的事关于Go语言中的GC,本期的分享并没有多少代码可言,都是一些理论知识,希...

Tkq_Carry的博客 1045

【Golang】GC探秘/写屏障是什么?

之前写了 一篇,有了很多的阅读量,那么我就接着分享一下Golang的GC相关的学习。由于Golang的GC机制一直在持续迭代,本文叙述的主要是Go1.9版本及以后的GC机制,该版本中Golang引入了 混合写屏障大幅度地优化了STW的时间。

qq_24428851的博客 889

案例:来自Uber的Go语言GC优化实践

Uber是世界领先的生活出行服务提供商,也是Go 语言的早期 adopter,根据Uber 工程博客的内容,大致可以判断出 Go 语言在 Uber 内部扮演了十分重要的角色。Uber...

架构师小秘圈 1155
上一篇: golang pprof 使用
下一篇: 记一次grub丢失后的修复记录
lvanneo
博客等级 码龄16年 13粉丝 11原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值