GoLand GC(垃圾回收机制)简介及调优

news2024/11/29 4:33:14

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 main

import "fmt"

// 一个简单的结构体类型
type Person struct {
    Name string
    Age  int
}

func main() {
    // 栈上的对象分配
    // 创建一个名为 "Alice" 年龄为 25 的 Person 对象,分配在栈上
    alice := Person{Name: "Alice", Age: 25}
    
    // 动态内存分配
    // 创建一个名为 "Bob" 年龄为 30 的 Person 对象,使用 new 函数分配在堆上
    bob := new(Person)
    bob.Name = "Bob"
    bob.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 / 100

Total heap memory = Live heap + New heap memory
# 前两者推出:
New heap memory = (Live heap + GC roots) * GOGC / 100
  • Target heap memory(目标堆内存):这是垃圾回收器的目标,它表示希望控制整个堆的大小。这个值由Go运行时系统设置,并可以通过环境变量 GOGC 来调整。它主要影响新分配的堆内存的大小,而不是已经存在的堆内存。

  • Live heap(活动堆内存):这是当前正在使用的堆内存的大小。这包括程序中正在使用的对象和数据结构。

  • GC roots(垃圾回收根节点):这表示垃圾回收器需要考虑的根节点的数量。根节点是程序中的全局变量、栈上的对象等。它们是指向堆内存的引用,这是刚才提到的对象图的根结点。

  • GOGC(Go语言的垃圾回收阈值):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 工作来自活动堆,并且(不切实际地)应用程序不使用额外的内存。

  • GC=100(默认情况)时
    在这里插入图片描述
  • GC=50时
    在这里插入图片描述
  • GC=-1(关闭gc)时
    在这里插入图片描述

GC调优

同第一节所说,我们的目的有两个:

  • 需要知道什么东西最占内存
  • 修改gc机制的频次或阈值

查看内存,手动调优

举个例子,代码来自:go pprof

package main

import (
	"fmt"
	"net/http"
	_ "net/http/pprof"
	"sync"
	"time"
)

func main() {
	// we need a webserver to get the pprof webserver
	go func() {
		http.ListenAndServe("localhost:6060", nil)
	}()
	fmt.Println("hello world")
	var wg sync.WaitGroup
	wg.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 24
      flat  flat%   sum%        cum   cum%
 7104.01kB 60.64% 60.64%  7104.01kB 60.64%  main.leakyFunction
 2562.81kB 21.88% 82.52%  2562.81kB 21.88%  runtime.allocm
 1024.01kB  8.74% 91.26%  1024.01kB  8.74%  runtime.doaddtimer
  512.20kB  4.37% 95.63%   512.20kB  4.37%  runtime.malg
  512.11kB  4.37%   100%   512.11kB  4.37%  net/http.ListenAndServe (inline)
         0     0%   100%   512.11kB  4.37%  main.main.func1
         0     0%   100%  1024.01kB  8.74%  runtime.bgscavenge
         0     0%   100%  1025.12kB  8.75%  runtime.mcall
         0     0%   100%  1024.01kB  8.74%  runtime.modtimer
         0     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?seconds=120    

#导致同步原语阻塞的堆栈跟踪
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。
ps:gc真好哇!知道我乱七八槽的不会用,只给了我一个接口。
比如:

package main
import (
	"runtime/debug"
)

func main() {
	debug.SetGCPercent(30) 
	//......
}

还是上面的代码,将gc改成30后,我查看了前六次gc的日志和gc为默认值100情况下:

# gc为30
# GODEBUG=gctrace=1 go run pprof.go 
gc 1 @0.505s 0%: 0.053+2.3+1.1 ms clock, 0.64+0/0.94/1.2+14 ms cpu, 3->4->2 MB, 4 MB goal, 12 P
gc 2 @0.509s 0%: 0.034+3.6+0.002 ms clock, 0.41+0/1.3/2.7+0.033 ms cpu, 4->4->2 MB, 5 MB goal, 12 P
gc 3 @0.513s 0%: 0.031+5.0+0.002 ms clock, 0.37+0.95/0.63/3.9+0.028 ms cpu, 3->3->2 MB, 4 MB goal, 12 P
gc 4 @0.519s 0%: 0.057+3.2+0.002 ms clock, 0.68+0/4.1/0.72+0.027 ms cpu, 4->4->3 MB, 5 MB goal, 12 P
gc 5 @1.024s 0%: 0.060+6.0+0.003 ms clock, 0.72+0/3.3/4.6+0.041 ms cpu, 5->5->4 MB, 6 MB goal, 12 P
gc 6 @1.031s 0%: 0.029+11+0.074 ms clock, 0.35+0.87/6.6/0.42+0.88 ms cpu, 7->10->10 MB, 8 MB goal, 12 P

# gc为100
# GODEBUG=gctrace=1 go run pprof.go 
gc 1 @0.505s 0%: 0.062+2.4+0.002 ms clock, 0.74+0/1.1/1.6+0.033 ms cpu, 4->4->1 MB, 5 MB goal, 12 P
gc 2 @0.510s 0%: 0.027+6.0+0.002 ms clock, 0.33+0.18/3.9/0.55+0.032 ms cpu, 5->6->4 MB, 6 MB goal, 12 P
gc 3 @1.018s 0%: 0.12+11+0.002 ms clock, 1.5+0/11/0.29+0.030 ms cpu, 9->9->7 MB, 10 MB goal, 12 P
gc 4 @1.534s 0%: 0.044+12+0.002 ms clock, 0.53+0/13/2.4+0.030 ms cpu, 15->15->8 MB, 16 MB goal, 12 P
gc 5 @2.050s 0%: 0.046+16+0.002 ms clock, 0.55+0/3.6/13+0.032 ms cpu, 20->20->7 MB, 21 MB goal, 12 P
gc 6 @2.567s 0%: 0.075+16+0.002 ms clock, 0.90+0/6.2/15+0.034 ms cpu, 15->15->15 MB, 16 MB goal, 12 P

如何查看分析日志呢,见下一小节。
其实可以明显的看出来,gc为30时,目标堆大小,明显要比gc为100的时候要小得多。这样我们就省下来很多的内存,可以存一些自己想要的学习资料(好好好,拿内存当存储是吧…)

查看gc日志

查看gc日志信息(参考自:GODEBUG-GC):

# GODEBUG=gctrace=1 go run debug.go
gc 1 @0.049s 0%: 0.016+0.26+0.015 ms clock, 0.19+0.13/0.33/0.18+0.19 ms cpu, 4->4->0 MB, 5 MB goal, 12 P
gc 2 @0.816s 0%: 0.11+0.39+0.003 ms clock, 1.3+0.19/0.65/0.62+0.037 ms cpu, 4->4->0 MB, 5 MB goal, 12 P
gc 3 @0.824s 0%: 0.15+0.33+0.002 ms clock, 1.8+0/0.39/0.51+0.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
ChatGPT[doge]

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

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

相关文章

Go学习第十五章——Gin参数绑定bind与验证器

Go web框架——Gin&#xff08;参数绑定bind与验证器&#xff09; 1 bind参数绑定1.1 JSON参数1.2 Query参数1.3 Uri绑定动态参数1.4 ShouldBind自动绑定 2 验证器2.1 常用验证器2.2 gin内置验证器2.3 自定义验证的错误信息2.4 自定义验证器 1 bind参数绑定 在Gin框架中&#…

Unity Meta Quest 一体机开发(三):Oculus Integration 基本原理、概念与结构+玩家角色基本配置

文章目录 &#x1f4d5;教程说明&#x1f4d5;输入数据&#x1f4d5;Oculus Integration 处理手部数据的推荐流程&#x1f4d5;VR 中交互的基本概念&#x1f4d5;Oculus Integration 中的交互流程&#x1f4d5;配置一个基本的玩家物体⭐OVRCameraRig⭐OVRInteraction⭐OVRHandP…

MC红显材质包安装

红显材质包安装 UP介绍视频 https://www.bilibili.com/video/BV1ML4y1u7nd/?vd_source3b8afcc2613780d7607382bae034945a 材质包下载地址&#xff1a; 需要 OptiFine 或 CITResewn 模组&#xff08;以后还会支持其他自定义贴图模组&#xff09; 下载&#xff1a;https://xek…

【python与数据结构】(leetcode算法预备知识)

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ python与数据结构 Python 中常见的数据类型数据结构1.数组&#xff08;Array&#xff09;2.链表&#xff08;Linked List&#xff09;3.哈希表&#xff08;Hash Table&#xff09;4.队列&#xff08;Queue&#x…

7.多线程之单例模式

单例模式 文章目录 单例模式1. 什么是单例模式2. 饿汉模式3. 懒汉模式3.1 单线程版&#xff1a;3.2 多线程版 1. 什么是单例模式 单例模式是一种设计模式&#xff0c;常见的设计模式还有工厂模式、建造者模式等。 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码…

Java练习题2022-1

HashSet是Java中常用的Set集合&#xff0c;向HashSet集合中添加数据对象时&#xff0c;首先会调用对象的hashCode()方法获取哈希码&#xff0c;根据哈希码计算对象的存储位置&#xff0c;如果相应位置上已经有数据对象&#xff0c;则会调用对象的equals()方法判断新加入的对象与…

【HarmonyOS】鸿蒙操作系统架构

HarmonyOS架构 一. 鸿蒙系统定位二. 架构整体遵从分层设计三. HarmonyOS具有的技术特性四. HarmonyOS有三大特征 其它相关推荐&#xff1a; 软考系统架构之案例篇(架构设计相关概念) 系统架构之微服务架构 系统架构设计之微内核架构 所属专栏&#xff1a;系统架构设计师 一. 鸿…

分类预测 | Matlab实现KOA-CNN-LSTM-selfAttention多特征分类预测

分类预测 | Matlab实现KOA-CNN-LSTM-selfAttention多特征分类预测 目录 分类预测 | Matlab实现KOA-CNN-LSTM-selfAttention多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现KOA-CNN-LSTM-selfAttention开普勒算法优化卷积长短期记忆神经网络融合…

Camtasia Mac 2023版怎么给视频加字幕

在视频制作过程中&#xff0c;字幕和马赛克是两项非常常用的编辑功能&#xff0c;添加字幕可以提高观众的观看体验&#xff0c;添加马赛克可以保护视频创作者不想公开的画面内容。Camtasia作为一款知名的视频制作软件&#xff0c;在具备基本的录制和视频编辑功能的同时&#xf…

Python运维学习Day01-文件基本操作

这里写自定义目录标题 1.遍历目录下所有的文件1.1 这里主要利用os.walk 函数的功能 2. 计算文件的 MD5 值3. 我们组合下两个函数&#xff0c;遍历下某个文件夹下的文件的md5码 1.遍历目录下所有的文件 def getFileName(directory):file_list []for dir_name, sub_dir,file_na…

CC002:ContextCapture倾斜摄影建模流程

摘要&#xff1a;本文主要介绍cc倾斜摄影建模流程&#xff0c;包括工程创建、影像添加、任务序列路径指定、空三、像控点的导入与刺点、空三优化、三维重建、定义生产三维产品的格式等流程&#xff0c;其中实验数据来源为多普云职业教育平台。 一、实验数据获取 本实验使用cc软…

【深度学习】吴恩达课程笔记(三)——参数VS超参数、深度学习的实践层面

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 吴恩达课程笔记——参数VS超参数、深度学习的实践层面 六、参数VS超参数1.参数和超参数的区别2.什么是超参数&#xff1f;3.如何寻找超参数的最优值&#xff1f; 七、深度学习的实践层面1.训练 / 验证 / 测试集(T…

python 应用 之 转图片格式webp

需求&#xff1a;将图片转成webp格式 目录 一、python 图片转webp格式 1、安装python 2、webp 依赖的包 1&#xff09;、PIP 安装Pillow 2)、VSCODE 选择python版本 2.1&#xff09;、测试是否安装成功 2.2&#xff09;、vscode选择python版本 3、python程序 1&#…

【深度学习】吴恩达课程笔记(二)——浅层神经网络、深层神经网络

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 笔记链接 【深度学习】吴恩达课程笔记(一)——深度学习概论、神经网络基础 吴恩达课程笔记——浅层神经网络、深层神经网络 四、浅层神经网络1.双层神经网络表示2.双层神经网络的前向传播第一层前向传播第二层前…

数据库简史:多主数据库架构的由来和华为参天引擎的机遇

注&#xff1a;本文发表后&#xff0c;收到了很多后台反馈&#xff0c;其中关于大型机的早期成就不容省略。微调重发本文&#xff0c;纯属个人观点&#xff0c;错谬之处&#xff0c;仍然期待指正。 2023年10月13日&#xff0c;在北京举办的“2023金融业数据库技术大会"上&…

前端 :用HTML和css制作一个小米官网的静态页面

1.HTML&#xff1a; <body><div id "content"><div id "box"><div id "top"><div id "top-left"><span id "logo">MI</span><span id "text-logo">小米账…

Java之数据类型与变量

目录 1. 字面常量 2. 数据类型 3. 变量 3.1 变量概念 3.2 语法格式 3.3 整型变量 3.3.1 整型变量 3.3.2 长整型变量 3.3.3 短整型变量 3.3.4 字节型变量 3.4 浮点型变量 3.4.1 双精度浮点型 3.4.2 单精度浮点型 3.5 字符型变量 3.6 布尔型变量 3.7 类型转换 3.7…

Kafka集群修改单个Topic数据保存周期

在大数据部门经常使用Kafka集群&#xff0c;有的时候大数据部门可能在Kafka中的Topic数据保存时间不需要很长&#xff0c;一旦被消费后就不需要一直保留。默认Topic存储时间为7day&#xff0c;个别的Topic或者某台Kafka集群需要修改Topic数据保存的一个周期&#xff0c;调整为3…

攻克组合优化问题!美国DARPA选中全栈量子经典计算公司Rigetti

&#xff08;图片来源&#xff1a;网络&#xff09; 近日&#xff0c;美国量子计算公司Rigetti宣布&#xff0c;它被美国国防高级研究计划局 (DARPA) 选中&#xff0c;加入想象未来量子实际应用 (IMPAQT) 计划&#xff0c;推进先进量子算法的研发&#xff0c;去解决组合优化问…

课题学习(九)----阅读《导向钻井工具姿态动态测量的自适应滤波方法》论文笔记

一、 引言 引言直接从原论文复制&#xff0c;大概看一下论文的关键点&#xff1a; 垂直导向钻井工具在近钻头振动和工具旋转的钻井工作状态下&#xff0c;工具姿态参数的动态测量精度不高。为此&#xff0c;通过理论分析和数值仿真&#xff0c;提出了转速补偿的算法以消除工具旋…