当前位置: 首页 > news >正文

网站开发的疑虑wordpress二次元网站

网站开发的疑虑,wordpress二次元网站,百度网站改版工具,宁波网站建设培训GC(Garbage Collector)垃圾回收机制及调优 简单理解GC机制 其实gc机制特别容易理解#xff0c;就是物理内存的自动清理工。我们可以把内存想象成一个房间#xff0c;程序运行时会在这个房间里存放各种东西#xff0c;但有时候我们会忘记把不再需要的东西拿出去#xff0c…GC(Garbage Collector)垃圾回收机制及调优 简单理解GC机制 其实gc机制特别容易理解就是物理内存的自动清理工。我们可以把内存想象成一个房间程序运行时会在这个房间里存放各种东西但有时候我们会忘记把不再需要的东西拿出去这就会导致房间变得杂乱不堪。甚至会出现房间的空间不够用的情况对应到计算机就是OOM(out of memory, 内存再多用一点就会爆炸)。 Go语言的GC机制会定期巡视这个房间找出那些被遗忘的东西并将它们清理出去释放内存。这样程序就能继续运行不会因为内存不足而崩溃。 那么我们为什么要看gc机制呢让gc自己在后台运行不好吗其实看gc机制的主要目的就是为了内存或CPU占用率的优化体现在两点 我需要知道房间里哪些东西最占地方看看是不能能在代码上有所优化我要想要更加频繁的清理房间(减小内存占用)或更少频次的清理房间(减少CPU开销) GC机制的原理 当然如果不想知道原理的话直接转到第三节就好。(咳咳其实我对细节也不是那么清楚知道怎么用的感觉已经很不容易了.) 什么时候需要用到GC 其实并不是所有内存都需要GC来清理的比如说有固定作用域的指针、地址等就无需gc等这些对象的生命周期结束后数据自动就会被销毁。换句人话说就是在栈上开辟的空间会随自动释放在堆上开辟的空间就需要gc机制来释放。如果学过C或C就会很好理解用make、new等操作创建的对象都需要手动free掉这些就是堆上开辟的内存空间。在Go语言中就不用手动free了这就是gc机制的作用定期free这些手动创建(堆上)的动态内存分配的对象。 当然专业点的话gc是一个专门识别和清理动态内存分配的系统。如果分不清的话可以看这个例子 package mainimport fmt// 一个简单的结构体类型 type Person struct {Name stringAge int }func main() {// 栈上的对象分配// 创建一个名为 Alice 年龄为 25 的 Person 对象分配在栈上alice : Person{Name: Alice, Age: 25}// 动态内存分配// 创建一个名为 Bob 年龄为 30 的 Person 对象使用 new 函数分配在堆上bob : new(Person)bob.Name Bobbob.Age 30// 输出栈上和堆上对象的信息fmt.Printf(Stack Object: Name: %s, Age: %d\n, alice.Name, alice.Age)fmt.Printf(Heap Object: Name: %s, Age: %d\n, bob.Name, bob.Age) }在程序运行结束后alice会因为生命周期结束自动free掉。但是bob仍然在堆上等待gc机制的回收。 对于Go语言的堆栈可以仿照C做一个简单的理解。实际上go语言的堆栈上的内存处理确实要比上述代码中描述的要复杂很多。go语言的逃逸分析就是专门负责堆栈上内存空间开辟的。有兴趣的话可以右转google一下。 回收内存的方法 gc机制通过标记-清除的方式回收内存。很好理解我想要free这块内存起码需要知道这块内存是不是没有用了。这就是标记的作用被标记的就是正在使用的(in-use)未被标记的都是要被free的。gc标记了一块地点 这个逻辑是不是很顺但有一个问题为什么不把标记清除放在一起呢我既然找到了需要free的内存为什么不直接清除掉还要分两个环节来做呢因为标记需要进行全局扫描当gc扫描到一个内存没有被使用时但是此时很有可能存在一个未被扫描到的指针指向了内存如果直接free掉就会造成“悬空指针”影响后续运行所以必须分为两个阶段先全局扫描进行标记然后陆续进行“清除” 稍微细扣一下 标记阶段 如何确定一个内存已经没有被使用呢gc好像有不同的方法举个例子引用计数(仿佛又回到了当年被八股的日子)。十分的简单有指针指向引用计数就加一如果扫描到引用计数为0房子就要没咯。这里边也涉及到一些比较专业点尔的词汇对象、指针、对象图。对象图是由对象和指向其他对象的指针一起构成的。遍历对象图的过程称为扫描。 为了识别实时内存GC 从程序的根部开始遍历对象图这些指针标识程序确实正在使用的对象。当然也不是时时刻刻都要扫描的毕竟它也不想996。这个就涉及到频率了后面会讲到。 还有一个很好玩的概念因为要对“对象图”进行扫描、标记gc会给它赋一个值叫做活动值。trace完成后GC 就会遍历堆中的所有内存并使所有未标记为可供分配的内存。 这个过程称为扫掠(sweeping)(文明六直呼内行从水下的从水下第一个生命的萌芽开始…)。 清除阶段 然后就需要扫掠了逐个free掉这个阶段没啥好说的之所以单独拎出来主要是为了标题的对称… 当然说的有些简单了大体上分为这两个阶段。如果细分的话还可以分SweepTermination、Mark、MarkTermination还有一些标记算法比如三色标记法等等感兴趣的可以自行查一查 gc调优的原理和开销 GOGC 决定了 GC CPU 和内存之间的权衡。所谓的优化也不过是在内存和CPU开销之间反复横跳看更需要哪种资源了。gc的一些官方文档上提到“GOGC 加倍会使堆内存开销加倍并使 GC CPU 成本减半”。现在用数学公式来看一下二者的tradeoff 内存开销 首先堆目标设置总堆大小的目标。超过堆目标或目标的百分比就要执行gc了。这就是确定gc执行的时间的方案。堆目标就两部分构成新开辟的内存和正在使用的内存(活动堆)。 # 这个是gc计算目标堆内存大小的公式不用太纠结它的物理含义超过这个值就需要进行gc了 Target heap memory Live heap (Live heap GC roots) * GOGC / 100Total heap memory Live heap New heap memory # 前两者推出 New heap memory (Live heap GC roots) * GOGC / 100Target heap memory目标堆内存这是垃圾回收器的目标它表示希望控制整个堆的大小。这个值由Go运行时系统设置并可以通过环境变量 GOGC 来调整。它主要影响新分配的堆内存的大小而不是已经存在的堆内存。 Live heap活动堆内存这是当前正在使用的堆内存的大小。这包括程序中正在使用的对象和数据结构。 GC roots垃圾回收根节点这表示垃圾回收器需要考虑的根节点的数量。主要分为三部分全局变量程序在编译期就能确定的那些存在于程序整个生命周期的变量。执行栈每个 goroutine 都包含自己的执行栈这些执行栈上包含栈上的变量及指向分配的堆内存区块的指针。寄存器寄存器的值可能表示一个指针参与计算的这些指针可能指向某些赋值器分配的堆内存区块。 GOGCGo语言的垃圾回收阈值GOGC 是一个环境变量表示垃圾回收器的触发阈值。当已分配的内存达到 Target heap memory 的一定百分比时垃圾回收将被触发默认值是100。也就是100%、 可能公式有一些绕大概意思就是我规定了一个目标堆内存大小的计算公式然后推出了新开辟的堆内存大小只要新开辟的堆内存大小达到了New heap memory就执行一次gc。这个新开辟的内存大小是受gc调控的。 CPU开销 来个简化版公式 Total GC CPU cost (Allocation rate) / (GOGC / 100) * (Cost per byte) * T详细公式可以看A Guide to the Go Garbage Collector 从这个简化版公式可以看出cpu的开销适合GOGC的大小成反比的 CPU vs 内存图例 依然是上面的网站有一个好玩的例子应用程序总共分配 200 MiB每次 1s分配20 MiB。它假设唯一要完成的相关 GC 工作来自活动堆并且不切实际地应用程序不使用额外的内存。 GC100(默认情况)时 GC50时 GC-1(关闭gc)时 GC调优 同第一节所说我们的目的有两个 需要知道什么东西最占内存修改gc机制的频次或阈值 查看内存手动调优 举个例子代码来自go pprof package mainimport (fmtnet/http_ net/http/pprofsynctime )func main() {// we need a webserver to get the pprof webservergo func() {http.ListenAndServe(localhost:6060, nil)}()fmt.Println(hello world)var wg sync.WaitGroupwg.Add(1)go leakyFunction(wg)wg.Wait() }func leakyFunction(wg sync.WaitGroup) {defer wg.Done()s : make([]string, 3)for i : 0; i 10000000; i {s append(s, magical pandas)if (i % 100000) 0 {time.Sleep(500 * time.Millisecond)}} }leakyFunction基本上这只是启动一个分配一堆内存的goroutine 然后最终退出。在程序运行期间通过以下命令查看内存的分配情况 go tool pprof http://localhost:6060/debug/pprof/heap然后使用top查看内存用量的前几名如下 # go tool pprof http://localhost:6060/debug/pprof/heap Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap Saved profile in /Users/yang/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz Type: inuse_space Time: Oct 28, 2023 at 11:31pm (CST) Entering interactive mode (type help for commands, o for options) (pprof) top Showing nodes accounting for 11715.14kB, 100% of 11715.14kB total Showing top 10 nodes out of 24flat flat% sum% cum cum%7104.01kB 60.64% 60.64% 7104.01kB 60.64% main.leakyFunction2562.81kB 21.88% 82.52% 2562.81kB 21.88% runtime.allocm1024.01kB 8.74% 91.26% 1024.01kB 8.74% runtime.doaddtimer512.20kB 4.37% 95.63% 512.20kB 4.37% runtime.malg512.11kB 4.37% 100% 512.11kB 4.37% net/http.ListenAndServe (inline)0 0% 100% 512.11kB 4.37% main.main.func10 0% 100% 1024.01kB 8.74% runtime.bgscavenge0 0% 100% 1025.12kB 8.75% runtime.mcall0 0% 100% 1024.01kB 8.74% runtime.modtimer0 0% 100% 1537.69kB 13.13% runtime.mstart (pprof) 当然也可以用图片比如这样不过需要Graphviz包没有的话会报错安装也很简单 apt install graphviz ## debian/ubuntu brew install graphviz ## mac ## 然后 go tool pprof -png http://localhost:6060/debug/pprof/heap out.png 然后就可以看到内存的分布图了 这样你就可以清晰的看到内存使用最多的函数leakyFunction。线越粗代表内存用量越大不过需要注意的是这里的信息只是你执行代码时采的点没有办法实时反应内存用量。 找到内存耗量最大的部分然后就可以手动对代码的做一些修改。这就极大的考验代码能力了。如果不想整可以移步下一小节修改gc参数自动搞定 当然除了看内存还可以看cpu开销等等(这些命令我忘记从哪里粘的了侵删)虽然官网上也有: https://pkg.go.dev/net/http/pprof。(但实在是懒就直接粘过来了) #所有过去内存分配的采样 go tool pprof http://127.0.0.1:6060/debug/pprof/allocs#对活动对象的内存分配进行采样 go tool pprof http://127.0.0.1:6060/debug/pprof/heap# 下载 cpu profile默认从当前开始收集 30s 的 cpu 使用情况需要等待 30s go tool pprof http://127.0.0.1:6060/debug/pprof/profile # wait 120s go tool pprof http://127.0.0.1:6060/debug/pprof/profile?seconds120 #导致同步原语阻塞的堆栈跟踪 go tool pprof http://127.0.0.1:8080/debug/pprof/block#所有当前goroutine的堆栈跟踪 go tool pprof http://127.0.0.1:8080/debug/pprof/goroutine#争用互斥锁持有者的堆栈跟踪 go tool pprof http://127.0.0.1:8080/debug/pprof/mutex#当前程序的执行轨迹。 go tool pprof http://127.0.0.1:8080/debug/pprof/trace当然本地开发的话这些都是有http窗口的但貌似对linux上开发帮助不大。感兴趣大家可以右拐google一下有很多帖子都是。 修改gc参数自动调优 gc值暴露了一个接口让我们修改gc的值那就是debug.SetGCPercent()需要import runtime/debug。 psgc真好哇知道我乱七八槽的不会用只给了我一个接口。 比如 package main import (runtime/debug )func main() {debug.SetGCPercent(30) //...... }还是上面的代码将gc改成30后我查看了前六次gc的日志和gc为默认值100情况下 # gc为30 # GODEBUGgctrace1 go run pprof.go gc 1 0.505s 0%: 0.0532.31.1 ms clock, 0.640/0.94/1.214 ms cpu, 3-4-2 MB, 4 MB goal, 12 P gc 2 0.509s 0%: 0.0343.60.002 ms clock, 0.410/1.3/2.70.033 ms cpu, 4-4-2 MB, 5 MB goal, 12 P gc 3 0.513s 0%: 0.0315.00.002 ms clock, 0.370.95/0.63/3.90.028 ms cpu, 3-3-2 MB, 4 MB goal, 12 P gc 4 0.519s 0%: 0.0573.20.002 ms clock, 0.680/4.1/0.720.027 ms cpu, 4-4-3 MB, 5 MB goal, 12 P gc 5 1.024s 0%: 0.0606.00.003 ms clock, 0.720/3.3/4.60.041 ms cpu, 5-5-4 MB, 6 MB goal, 12 P gc 6 1.031s 0%: 0.029110.074 ms clock, 0.350.87/6.6/0.420.88 ms cpu, 7-10-10 MB, 8 MB goal, 12 P# gc为100 # GODEBUGgctrace1 go run pprof.go gc 1 0.505s 0%: 0.0622.40.002 ms clock, 0.740/1.1/1.60.033 ms cpu, 4-4-1 MB, 5 MB goal, 12 P gc 2 0.510s 0%: 0.0276.00.002 ms clock, 0.330.18/3.9/0.550.032 ms cpu, 5-6-4 MB, 6 MB goal, 12 P gc 3 1.018s 0%: 0.12110.002 ms clock, 1.50/11/0.290.030 ms cpu, 9-9-7 MB, 10 MB goal, 12 P gc 4 1.534s 0%: 0.044120.002 ms clock, 0.530/13/2.40.030 ms cpu, 15-15-8 MB, 16 MB goal, 12 P gc 5 2.050s 0%: 0.046160.002 ms clock, 0.550/3.6/130.032 ms cpu, 20-20-7 MB, 21 MB goal, 12 P gc 6 2.567s 0%: 0.075160.002 ms clock, 0.900/6.2/150.034 ms cpu, 15-15-15 MB, 16 MB goal, 12 P 如何查看分析日志呢见下一小节。 其实可以明显的看出来gc为30时目标堆大小明显要比gc为100的时候要小得多。这样我们就省下来很多的内存可以存一些自己想要的学习资料好好好拿内存当存储是吧… 查看gc日志 查看gc日志信息(参考自GODEBUG-GC) # GODEBUGgctrace1 go run debug.go gc 1 0.049s 0%: 0.0160.260.015 ms clock, 0.190.13/0.33/0.180.19 ms cpu, 4-4-0 MB, 5 MB goal, 12 P gc 2 0.816s 0%: 0.110.390.003 ms clock, 1.30.19/0.65/0.620.037 ms cpu, 4-4-0 MB, 5 MB goal, 12 P gc 3 0.824s 0%: 0.150.330.002 ms clock, 1.80/0.39/0.510.024 ms cpu, 4-4-0 MB, 5 MB goal, 12 P含义如下 gc#GC 执行次数的编号每次叠加。#s自程序启动后到当前的具体秒数。#%自程序启动以来在 GC 中花费的时间百分比。#…#GC 的标记工作共使用的 CPU 时间占总 CPU 时间的百分比。#-#-# MB分别表示 GC 启动时, GC 结束时, GC 活动时的堆大小.#MB goal下一次触发 GC 的内存占用阈值。#P当前使用的处理器 P 的数量 debug的其他api 有点跑题了不过确实很有用关于gc参数调整goland只提供了一个接口但是对于debug中还有其他的一些api也很有用比如说 // 强制gc 将尽可能多的内存返回给操作系统 func FreeOSMemory() // 设置最大堆大小 func SetMaxStack(bytes int) int // 设置最大线程数 func SetMaxThreads(threads int) int和SetGCPercent的使用方法一样更多api详见https://pkg.go.dev/runtime/debug#FreeOSMemory 参考 A Guide to the Go Garbage Collector gc问题集 debug.api GODEBUG-GC go pprof gc机制和调优 ChatGPT[doge]
http://www.w-s-a.com/news/650772/

相关文章:

  • 中国空间站科幻作文1000字wordpress运行库
  • 徐州做网站的wordpress可视化编辑器排行
  • 官方网站英语上海公司注册核名查询
  • 东莞网站建设推广云南昆明最新消息
  • 上网站乱码网页设计与网站建设案例教程
  • 宣讲网站建设wordpress多媒体主题
  • 如何成立网站互联网开发是做什么的
  • 网站首页的尺寸做多大网页图片排版
  • 龙岩天宫山索道多少钱河南网站排名优化哪家好
  • 北京做网站设计程序员和网站开发
  • 个人 做自媒体 建网站图片制作成视频的手机软件
  • h5 建站网站 移动端重庆潼南网站建设价格
  • 商企在线营销型网站怎么做时光网站
  • 网站建设方案论文1500竞价托管哪家便宜
  • 使用cdn的网站宣武网站建设
  • 营销型网站怎么建设企业网站Wap在线生成
  • 网站建设服务费应该做到什么科目广州网页制作服务商
  • 网站显示500错误怎么解决方法店面设计模板
  • 网站备案icp文化传媒有限公司
  • 北京企业建站模板微信公众号商城怎么制作
  • 制作网站 公司简介大型做网站的公司
  • 北京网站开发建设南昌网站小程序开发
  • 网站如何做ip签名图片宁波互联网
  • 中山小榄网站建设长沙网络营销品牌排名
  • 推广优化厂商联系方式网站推广教程优化整站
  • 为外国企业做中文网站建设网站建设单位哪家好
  • 生物制药公司网站模板有没有专业做steam创客的网站
  • 福田做棋牌网站建设找哪家效益快弄一个微信小程序多少钱
  • 成都哪家做网站建设比较好做推广赚钱的网站
  • 常州专门做网站的公司有哪些网页模板下载网站10