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

2021年免费的网站有哪些做网站所用的工具

2021年免费的网站有哪些,做网站所用的工具,wordpress link,安阳网站如何做优化Go提供了自动化的内存管理机制#xff0c;但在某些情况下需要更精细的微调从而避免发生OOM错误。本文介绍了如何通过微调GOGC和GOMEMLIMIT在性能和内存效率之间取得平衡#xff0c;并尽量避免OOM的产生。原文: Memory Optimization and Garbage Collector Management in Go 本… Go提供了自动化的内存管理机制但在某些情况下需要更精细的微调从而避免发生OOM错误。本文介绍了如何通过微调GOGC和GOMEMLIMIT在性能和内存效率之间取得平衡并尽量避免OOM的产生。原文: Memory Optimization and Garbage Collector Management in Go 本文将讨论Go的垃圾收集器、应用程序内存优化以及如何防止OOM(Out-Of-Memory)错误。 Go中的堆(Heap)栈(Stack) 我不会详细介绍垃圾收集器如何工作已经有很多关于这个主题的文章和官方文档(比如A Guide to the Go Garbage Collector[1]和源码[2])。但是我会提到一些有助于理解本文主题的基本概念。 你可能已经知道Go的数据可以存储在两个主要的内存存储中: 栈(stack)和堆(heap)。 通常栈存储的数据的大小和使用时间可以由Go编译器预测包括函数局部变量、函数参数、返回值等。 栈是自动管理的遵循后进先出(LIFO)原则。当调用函数时所有相关数据都放在栈的顶部函数结束时这些数据将从栈中删除。栈不需要复杂的垃圾收集机制其内存管理开销最小在栈中检索和存储数据的过程非常快。 然而并不是所有数据都可以存储在栈中。在执行过程中动态更改的数据或需要在函数范围之外访问的数据不能放在栈上因为编译器无法预测其使用情况这种数据应该存储在堆中。 与栈不同从堆中检索数据并对其进行管理的成本更高。 栈里放什么堆里放什么? 正如前面提到的栈用于具有可预测大小和寿命的值例如: 在函数内部声明的局部变量例如基本数据类型变量(例如数字和布尔值)。 函数参数。 函数返回后不再被引用的返回值。 Go编译器在决定将数据放在栈中还是堆中时会考虑各种细微差别。 例如预分配大小为64 KB的数据将存储在栈中而大于64 KB的数据将存储在堆中。这同样适用于数组如果数组超过10 MB将存储在堆中。 可以使用逃逸分析(escape analysis)来确定特定变量的存储位置。 例如可以通过命令行编译参数-gcflags-m来分析应用程序: go build -gcflags-m main.go 如果使用-gcflags-m参数编译下面的main.go: package mainfunc main() {  var arrayBefore10Mb [1310720]int  arrayBefore10Mb[0]  1  var arrayAfter10Mb [1310721]int  arrayAfter10Mb[0]  1  sliceBefore64 : make([]int, 8192)  sliceOver64 : make([]int, 8193)  sliceOver64[0]  sliceBefore64[0]} 结果是: # command-line-arguments./main.go:3:6: can inline main./main.go:7:6: moved to heap: arrayAfter10Mb./main.go:10:23: make([]int, 8192) does not escape./main.go:11:21: make([]int, 8193) escapes to heap 可以看到arrayAfter10Mb数组被移动到堆中因为大小超过了10MB而arrayBefore10Mb仍然留在栈中(对于int变量10MB等于10 * 1024 * 1024 / 8 1310720个元素)。 此外sliceBefore64没有存储在堆中因为它的大小小于64KB而sliceOver64被存储在堆中(对于int变量64KB等于64 * 1024 / 8 8192个元素)。 要了解更多关于在堆中分配的位置和内容可以参考malloc.go源码[3]。 因此使用堆的一种方法是尽量避免用它但是如果数据已经落在堆中了呢 与栈不同堆的大小是无限的并且不断增长。堆存储动态创建的对象如结构体、分片和映射以及由于其限制而无法放入栈中的大内存块。 在堆中重用内存并防止其完全阻塞的唯一工具是垃圾收集器。 浅谈垃圾收集器的工作原理 垃圾收集器(GC)是一种专门用于识别和释放动态分配内存的系统。 Go使用基于跟踪和标记和扫描算法的垃圾收集算法。在标记阶段垃圾收集器将应用程序正在使用的数据标记为活跃堆。然后在清理阶段GC遍历所有未标记为活跃的内存并复用。 垃圾收集器不是免费工作的需要消耗两个重要的系统资源: CPU时间和物理内存。 垃圾收集器中的内存由以下部分组成: 活跃堆内存(在前一个垃圾收集周期中标记为活跃的内存) 新的堆内存(尚未被垃圾收集器分析的堆内存) 存储元数据的内存与前两个实体相比这些元数据通常微不足道。 垃圾收集器所消耗的CPU时间与其工作细节有关。有一种称为stop-the-world的垃圾收集器实现它在垃圾收集期间完全停止程序执行导致CPU时间被花在非生产性工作上。 在Go里垃圾收集器并不是完全stop-the-world而是与应用程序并行执行其大部分工作(例如标记堆)。 但是垃圾收集器的操作仍然有一些限制并且会在一个周期内多次完全停止工作代码的执行想要了解更多可以阅读源码[4]。 如何管理垃圾收集器 在Go中可以通过某些参数管理垃圾收集器: GOGC环境变量或runtime/debug包中的等效函数SetGCPercent。 GOGC参数确定将触发垃圾收集的新未分配堆内存相对于活跃内存的百分比。 GOGC的默认值是100意味着当新内存达到活跃堆内存的100%时将触发垃圾收集。 当新堆占用活跃堆的100%时将运行垃圾收集器。 我们以示例程序为例通过go tool trace跟踪堆大小的变化我们用Go 1.20.1版本来运行程序。 在本例中performMemoryIntensiveTask函数使用了在堆中分配的大量内存。这个函数启动一个队列大小为NumWorker的工作池任务数量等于NumTasks。 package mainimport ( fmt os runtime/debug runtime/trace sync)const ( NumWorkers     4     // Number of workers. NumTasks       500   // Number of tasks. MemoryIntense  10000 // Size of memory-intensive task (number of elements).)func main() { // Write to the trace file. f, _ : os.Create(trace.out) trace.Start(f) defer trace.Stop() // Set the target percentage for the garbage collector. Default is 100%. debug.SetGCPercent(100) // Task queue and result queue. taskQueue : make(chan int, NumTasks) resultQueue : make(chan int, NumTasks) // Start workers. var wg sync.WaitGroup wg.Add(NumWorkers) for i : 0; i  NumWorkers; i {  go worker(taskQueue, resultQueue, wg) } // Send tasks to the queue. for i : 0; i  NumTasks; i {  taskQueue - i } close(taskQueue) // Retrieve results from the queue. go func() {  wg.Wait()  close(resultQueue) }() // Process the results. for result : range resultQueue {  fmt.Println(Result:, result) } fmt.Println(Done!)}// Worker function.func worker(tasks -chan int, results chan- int, wg *sync.WaitGroup) { defer wg.Done() for task : range tasks {  result : performMemoryIntensiveTask(task)  results - result }}// performMemoryIntensiveTask is a memory-intensive function.func performMemoryIntensiveTask(task int) int { // Create a large-sized slice. data : make([]int, MemoryIntense) for i : 0; i  MemoryIntense; i {  data[i]  i  task } // Latency imitation. time.Sleep(10 * time.Millisecond) // Calculate the result. result : 0 for _, value : range data {  result  value } return result} 跟踪程序执行的结果被写入文件trace.out: // Writing to the trace file.f, _ : os.Create(trace.out)trace.Start(f)defer trace.Stop() 通过go tool trace可以观察堆大小的变化并分析程序中垃圾收集器的行为。 请注意go tool trace的精确细节和功能可能因go版本不同而有所差异因此建议参考官方文档以获取有关其在特定go版本中使用的详细信息。 GOGC的默认值 GOGC参数可以使用runtime/debug包中的debug.SetGCPercent进行设置GOGC默认设置为100%。 用下面命令运行程序: go run main.go 程序执行后将会创建trace.out文件可以使用go tool工具对其进行分析。要做到这一点执行命令: go tool trace trace.out 然后可以通过打开web浏览器并访问http://127.0.0.1:54784/trace来查看基于web的跟踪查看器。 GOGC 100 在STATS选项卡中可以看到Heap字段显示了在应用程序执行期间堆大小的变化情况图中红色区域表示堆占用的内存。 在PROCS选项卡中GC(垃圾收集器)字段显示的蓝色列表示触发垃圾收集器的时刻。 一旦新堆的大小达到活动堆大小的100%就会触发垃圾收集。例如如果活跃堆大小为10 MB则当当前堆大小达到10 MB时将触发垃圾收集。 跟踪所有垃圾收集调用使我们能够确定垃圾收集器处于活动状态的总时间。 GOGC100时的GC调用次数 示例中当GOGC值为100时将调用垃圾收集器16次总执行时间为14 ms。 更频繁的调用GC 如果我们将debug.SetGCPercent(10)设置为10%后运行代码将观察到垃圾收集器调用的频率更高。现在如果当前堆大小达到活跃堆大小的10%时将触发垃圾收集。 换句话说如果活跃堆大小为10 MB则当前堆大小达到1 MB时就将触发垃圾收集。 GOGC 10 在本例中垃圾收集器被调用了38次总垃圾收集时间为28 ms。 GOGC10时的GC调用次数 可以观察到将GOGC设置为低于100%的值可以增加垃圾收集的频率可能导致CPU使用率增加并降低程序性能。 更少的调用GC 如果运行相同程序但将debug.SetGCPercent(1000)设置为1000%我们将得到以下结果: GOGC 1000 可以看到当前堆的大小一直在增长直到达到活跃堆大小的1000%。换句话说如果活跃堆大小为10 MB则当前堆大小达到100 MB时将触发垃圾收集。 GOGC1000时的GC调用次数 在当前情况下垃圾收集器被调用一次并执行2毫秒。 关闭GC 还可以通过设置GOGCoff或调用debug.SetGCPercent(-1)来禁用垃圾收集。 下面是禁用垃圾收集器而不设置GOMEMLIMIT时堆的行为: 当GCoff时堆大小不断增长。 可以看到在关闭GC后应用程序的堆大小一直在增长直到程序执行为止。 堆占用多少内存? 在活跃堆的实际内存分配中通常不像我们在trace中看到的那样定期和可预测的工作。 活跃堆随着每个垃圾收集周期动态变化并且在某些条件下其绝对值可能出现峰值。 例如如果由于多个并行任务的重叠活跃堆的大小可以增长到800 MB那么只有在当前堆大小达到1.6 GB时才会触发垃圾收集。 现代开发通常在具有内存使用限制的容器中运行应用。因此如果容器将内存限制设置为1 GB并且总堆大小增加到1.6 GB则容器将失效并出现OOM(out of memory)错误。 让我们模拟一下这种情况。例如我们在内存限制为10 MB的容器中运行程序(仅用于测试目的)。Dockerfile: FROM golang:latest as builderWORKDIR /srcCOPY . .RUN go env -w GO111MODULEonRUN go mod vendorRUN CGO_ENABLED0 GOOSlinux go build -modvendor -a -installsuffix cgo -o app ./cmd/FROM golang:latestWORKDIR /root/COPY --frombuilder /src/app .EXPOSE 8080CMD [./app] Docker-compose描述: version: 3services: my-app:   build:     context: .     dockerfile: Dockerfile   ports:     - 8080:8080   deploy:     resources:       limits:         memory: 10M 让我们使用前面设置GOGC1000%的代码启动容器。 可以使用以下命令运行容器: docker-compose builddocker-compose up 几秒钟后容器将崩溃并产生与OOM相对应的错误。 exited with code 137 这种情况非常令人不快: GOGC只控制新堆的相对值而容器有绝对限制。 如何避免OOM? 从1.19版本开始在GOMEMLIMIT选项的帮助下Golang引入了一个名为软内存管理的特性runtime/debug包中名为SetMemoryLimit的类似函数(可以阅读48409-soft-memory-limit.md了解有关此选项的一些有趣的设计细节)提供了相同的功能。 GOMEMLIMIT环境变量设置Go运行时可以使用的总体内存限制例如: GOMEMLIMIT 8MiB。要设置内存值需要使用大小后缀在本例中为8 MB。 让我们启动将GOMEMLIMIT境变量设置为8MiB的容器。为此我们将环境变量添加到docker-compose文件中: version: 3services: my-app:    environment:      GOMEMLIMIT: 8MiB   build:     context: .     dockerfile: Dockerfile   ports:     - 8080:8080   deploy:     resources:       limits:         memory: 10M 现在当启动容器时程序运行没有任何错误。该机制是专门为解决OOM问题而设计的。 这是因为启用GOMEMLIMIT8MiB后会定期调用垃圾收集器并将堆大小保持在一定限制内结果就是会频繁调用垃圾收集器以避免内存过载。 运行垃圾收集器以使堆大小保持在一定的限制内。 成本是什么? GOMEMLIMIT是强有力的工具但也可能适得其反。 在上面的堆跟踪图中可以看到这种场景的一个示例。 当总内存大小由于活跃堆或持久程序泄漏的增长而接近GOMEMLIMIT时将开始根据该限制不断调用垃圾收集器。 由于频繁调用垃圾收集器应用程序的运行时可能会无限增加从而消耗应用程序的CPU时间。 这种行为被称为死亡螺旋[5]可能导致应用程序性能下降与OOM错误不同这种问题很难检测和修复。 这正是GOMEMLIMIT机制作为软限制起作用的原因。 Go不能100%保证GOMEMLIMIT指定的内存限制会被严格执行而是会允许使用超出限制的内存并防止频繁调用垃圾收集器的情况。 为了实现这一点需要对CPU使用设置限制。目前这个限制被设置为所有处理器时间的50%CPU窗口为2 * GOMAXPROCS秒。 这就是为什么我们不能完全避免OOM错误而是会将其推迟到很久以后发生。 在哪里应用GOMEMLIMIT和GOGC 如果默认垃圾收集器设置在大多数情况下是足够的那么带有GOMEMLIMIT的软内存管理机制可以使我们避免不愉快的情况。 使用GOMEMLIMIT内存限制可能有用的例子: 在内存有限的容器中运行应用程序时最好将 GOMEMLIMIT设置为保留5-10%的可用内存。 在运行资源密集型库或代码时对 GOMEMLIMIT进行实时管理是有好处的。 当在容器中以脚本形式运行应用程序时(意味着应用程序在一段时间内执行某些任务然后终止)禁用垃圾收集器但设置 GOMEMLIMIT可以提高性能并防止超出容器的资源限制。 避免使用GOMEMLIMIT的情况: 当程序已经接近其环境的内存限制时不要设置内存限制。 在无法控制的执行环境中部署时不要使用内存限制特别是在程序的内存使用与其输入数据成正比的情况下例如CLI工具或桌面应用程序。 如上所述通过深思熟虑的方法我们可以管理程序中的微调设置例如垃圾收集器和GOMEMLIMIT。然而仔细考虑应用这些设置的策略无疑非常重要。 你好我是俞凡在Motorola做过研发现在在Mavenir做技术工作对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣平时喜欢阅读、思考相信持续学习、终身成长欢迎一起交流学习。为了方便大家以后能第一时间看到文章请朋友们关注公众号DeepNoMind并设个星标吧如果能一键三连(转发、点赞、在看)则能给我带来更多的支持和动力激励我持续写下去和大家共同成长进步 参考资料 [1] A Guide to the Go Garbage Collector: https://tip.golang.org/doc/gc-guide [2] mgc.go: https://go.dev/src/runtime/mgc.go [3] malloc.go: https://go.dev/src/runtime/malloc.go [4] mgc.go: https://go.dev/src/runtime/mgc.go [5] Soft Memory Limit Death Spirals: https://github.com/golang/proposal/blob/master/design/48409-soft-memory-limit.md#death-spirals 本文由 mdnice 多平台发布
http://www.pierceye.com/news/898924/

相关文章:

  • 网站名和域名能一样吗企业网站建设硬件
  • 德州做网站公司怎么开网店淘宝
  • 苏州做网站优化的电商定制开发
  • 广西庆海建设发展有限公司网站昆山有做网站的公司吗
  • 前端课程网站wordpress 微博登陆
  • asp怎么做网站适配开发公司安置房项目工程推进大会
  • 学做网站可以赚钱吗怎么批量修改wordpress文章内容
  • 写作网站vir上海博大园林建设发展有限公司网站
  • wordpress video gallery网站代码优化怎么做
  • 厦门网站设计品牌企业互联网门户网站建设
  • 做名片模板网站中文响应式网站
  • 用tornado做网站石家庄 外贸网站建设公司
  • 档案网站建设网页wordpress keyshot
  • 鞍山制作网站哪家好建设银行员工网站
  • 手机怎么提升网站流量品牌型网站成功案例图片
  • 网站视频主持人制作网站开发 质量管理
  • 网站的外链建设计划石家庄市城乡建设部网站
  • 电子商务网站规划与建设论文电子商务营销方法
  • 宁波做网站费用电子商城开发网站开发
  • 太原市住房和城乡建设部网站免费的logo在线设计
  • 做it的在哪个网站找工作wordpress 幻燈片 插件
  • 湘潭做网站 i磐石网络博学网站建设公司
  • 揭阳市建设发展总公司网站自己做的视频网站如何赚钱
  • 泉州自助建站软件天眼查在线查询官网
  • 网站建设书模板校本教研网站建设方案
  • 经销商自己做网站合适吗彩虹网站建设
  • 网站新闻编辑怎么做网站开发人员 组织架构
  • 重庆网站seo诊断婚纱摄影网站模板下载
  • 老板合作网站开发宁波网站建设慕枫科技
  • 做外贸都有哪些好网站河北沙河市规划局或建设局网站