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

Go内存优化与垃圾收集

Go提供了自动化的内存管理机制,但在某些情况下需要更精细的微调从而避免发生OOM错误。本文介绍了如何通过微调GOGC和GOMEMLIMIT在性能和内存效率之间取得平衡,并尽量避免OOM的产生。原文: Memory Optimization and Garbage Collector Management in Go

alt

本文将讨论Go的垃圾收集器、应用程序内存优化以及如何防止OOM(Out-Of-Memory)错误。

Go中的堆(Heap)栈(Stack)

我不会详细介绍垃圾收集器如何工作,已经有很多关于这个主题的文章和官方文档(比如A Guide to the Go Garbage Collector[1]源码[2])。但是,我会提到一些有助于理解本文主题的基本概念。

你可能已经知道,Go的数据可以存储在两个主要的内存存储中: 栈(stack)和堆(heap)。

alt

通常,栈存储的数据的大小和使用时间可以由Go编译器预测,包括函数局部变量、函数参数、返回值等。

栈是自动管理的,遵循后进先出(LIFO)原则。当调用函数时,所有相关数据都放在栈的顶部,函数结束时,这些数据将从栈中删除。栈不需要复杂的垃圾收集机制,其内存管理开销最小,在栈中检索和存储数据的过程非常快。

然而,并不是所有数据都可以存储在栈中。在执行过程中动态更改的数据或需要在函数范围之外访问的数据不能放在栈上,因为编译器无法预测其使用情况,这种数据应该存储在堆中。

与栈不同,从堆中检索数据并对其进行管理的成本更高。

栈里放什么,堆里放什么?

正如前面提到的,栈用于具有可预测大小和寿命的值,例如:

  • 在函数内部声明的局部变量,例如基本数据类型变量(例如数字和布尔值)。
  • 函数参数。
  • 函数返回后不再被引用的返回值。

Go编译器在决定将数据放在栈中还是堆中时会考虑各种细微差别。

例如,预分配大小为64 KB的数据将存储在栈中,而大于64 KB的数据将存储在堆中。这同样适用于数组,如果数组超过10 MB,将存储在堆中。

alt

可以使用逃逸分析(escape analysis)来确定特定变量的存储位置。

例如,可以通过命令行编译参数-gcflags=-m来分析应用程序:

go build -gcflags=-m main.go

如果使用-gcflags=-m参数编译下面的main.go:

package main

func main() {
  var arrayBefore10Mb [1310720]int
  arrayBefore10Mb[0] = 1

  var arrayAfter10Mb [1310721]int
  arrayAfter10Mb[0] = 1

  sliceBefore64 := make([]int8192)
  sliceOver64 := make([]int8193)
  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]

alt
如何管理垃圾收集器

在Go中可以通过某些参数管理垃圾收集器: GOGC环境变量或runtime/debug包中的等效函数SetGCPercent

GOGC参数确定将触发垃圾收集的新未分配堆内存相对于活跃内存的百分比。

GOGC的默认值是100,意味着当新内存达到活跃堆内存的100%时将触发垃圾收集。

当新堆占用活跃堆的100%时,将运行垃圾收集器。
当新堆占用活跃堆的100%时,将运行垃圾收集器。

我们以示例程序为例,通过go tool trace跟踪堆大小的变化,我们用Go 1.20.1版本来运行程序。

在本例中,performMemoryIntensiveTask函数使用了在堆中分配的大量内存。这个函数启动一个队列大小为NumWorker的工作池,任务数量等于NumTasks

package main

import (
 "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
GOGC = 100

在"STATS"选项卡中,可以看到"Heap"字段,显示了在应用程序执行期间堆大小的变化情况,图中红色区域表示堆占用的内存。

在"PROCS"选项卡中,"GC"(垃圾收集器)字段显示的蓝色列表示触发垃圾收集器的时刻。

一旦新堆的大小达到活动堆大小的100%,就会触发垃圾收集。例如,如果活跃堆大小为10 MB,则当当前堆大小达到10 MB时将触发垃圾收集。

跟踪所有垃圾收集调用使我们能够确定垃圾收集器处于活动状态的总时间。

GOGC=100时的GC调用次数
GOGC=100时的GC调用次数

示例中,当GOGC值为100时,将调用垃圾收集器16次,总执行时间为14 ms。

更频繁的调用GC

如果我们将debug.SetGCPercent(10)设置为10%后运行代码,将观察到垃圾收集器调用的频率更高。现在,如果当前堆大小达到活跃堆大小的10%时,将触发垃圾收集。

换句话说,如果活跃堆大小为10 MB,则当前堆大小达到1 MB时就将触发垃圾收集。

GOGC = 10
GOGC = 10

在本例中,垃圾收集器被调用了38次,总垃圾收集时间为28 ms。

GOGC=10时的GC调用次数
GOGC=10时的GC调用次数

可以观察到,将GOGC设置为低于100%的值可以增加垃圾收集的频率,可能导致CPU使用率增加并降低程序性能。

更少的调用GC

如果运行相同程序,但将debug.SetGCPercent(1000)设置为1000%,我们将得到以下结果:

GOGC = 1000
GOGC = 1000

可以看到,当前堆的大小一直在增长,直到达到活跃堆大小的1000%。换句话说,如果活跃堆大小为10 MB,则当前堆大小达到100 MB时将触发垃圾收集。

GOGC=1000时的GC调用次数
GOGC=1000时的GC调用次数

在当前情况下,垃圾收集器被调用一次并执行2毫秒。

关闭GC

还可以通过设置GOGC=off或调用debug.SetGCPercent(-1)来禁用垃圾收集。

下面是禁用垃圾收集器而不设置GOMEMLIMIT时堆的行为:

当GC=off时,堆大小不断增长。
当GC=off时,堆大小不断增长。

可以看到,在关闭GC后,应用程序的堆大小一直在增长,直到程序执行为止。

堆占用多少内存?

在活跃堆的实际内存分配中,通常不像我们在trace中看到的那样定期和可预测的工作。

活跃堆随着每个垃圾收集周期动态变化,并且在某些条件下,其绝对值可能出现峰值。

例如,如果由于多个并行任务的重叠,活跃堆的大小可以增长到800 MB,那么只有在当前堆大小达到1.6 GB时才会触发垃圾收集。

alt

现代开发通常在具有内存使用限制的容器中运行应用。因此,如果容器将内存限制设置为1 GB,并且总堆大小增加到1.6 GB,则容器将失效,并出现OOM(out of memory)错误。

让我们模拟一下这种情况。例如,我们在内存限制为10 MB的容器中运行程序(仅用于测试目的)。Dockerfile:

FROM golang:latest as builder


WORKDIR /src
COPY . .


RUN go env -w GO111MODULE=on


RUN go mod vendor
RUN CGO_ENABLED=0 GOOS=linux go build -mod=vendor -a -installsuffix cgo -o app ./cmd/


FROM golang:latest
WORKDIR /root/
COPY --from=builder /src/app .
EXPOSE 8080
CMD ["./app"]

Docker-compose描述:

version: '3'
services:
 my-app:
   build:
     context: .
     dockerfile: Dockerfile
   ports:
     - 8080:8080
   deploy:
     resources:
       limits:
         memory: 10M

让我们使用前面设置GOGC=1000%的代码启动容器。

可以使用以下命令运行容器:

docker-compose build
docker-compose up

几秒钟后,容器将崩溃,并产生与OOM相对应的错误。

exited with code 137

这种情况非常令人不快: GOGC只控制新堆的相对值,而容器有绝对限制。

alt
如何避免OOM?

从1.19版本开始,在GOMEMLIMIT选项的帮助下,Golang引入了一个名为"软内存管理"的特性,runtime/debug包中名为SetMemoryLimit的类似函数(可以阅读48409-soft-memory-limit.md了解有关此选项的一些有趣的设计细节)提供了相同的功能。

GOMEMLIMIT环境变量设置Go运行时可以使用的总体内存限制,例如: GOMEMLIMIT = 8MiB。要设置内存值,需要使用大小后缀,在本例中为8 MB。

让我们启动将GOMEMLIMIT境变量设置为8MiB的容器。为此,我们将环境变量添加到docker-compose文件中:

version: '3'
services:
 my-app:
    environment:
      GOMEMLIMIT: "8MiB"
   build:
     context: .
     dockerfile: Dockerfile
   ports:
     - 8080:8080
   deploy:
     resources:
       limits:
         memory: 10M

现在,当启动容器时,程序运行没有任何错误。该机制是专门为解决OOM问题而设计的。

这是因为启用GOMEMLIMIT=8MiB后,会定期调用垃圾收集器,并将堆大小保持在一定限制内,结果就是会频繁调用垃圾收集器以避免内存过载。

运行垃圾收集器以使堆大小保持在一定的限制内。
运行垃圾收集器以使堆大小保持在一定的限制内。
成本是什么?

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 多平台发布

相关文章:

Go内存优化与垃圾收集

Go提供了自动化的内存管理机制&#xff0c;但在某些情况下需要更精细的微调从而避免发生OOM错误。本文介绍了如何通过微调GOGC和GOMEMLIMIT在性能和内存效率之间取得平衡&#xff0c;并尽量避免OOM的产生。原文: Memory Optimization and Garbage Collector Management in Go 本…...

【Spring】Bean 的生命周期

一、Bean 的生命周期 Spring 其实就是一个管理 Bean 对象的工厂&#xff0c;它负责对象的创建&#xff0c;对象的销毁等 所谓的生命周期就是&#xff1a;对象从创建开始到最终销毁的整个过程 什么时候创建 Bean 对象&#xff1f;创建 Bean 对象的前后会调用什么方法&#xf…...

云计算基础-存储基础

存储概念 什么是存储&#xff1a; 存储就是根据不同的应用程序环境&#xff0c;通过采取合理、安全、有效的方式将数据保存到某些介质上&#xff0c;并能保证有效的访问&#xff0c;存储的本质是记录信息的载体。 存储的特性&#xff1a; 数据临时或长期驻留的物理介质需要保…...

问题:人的安全知识和技能是天生的。() #媒体#知识分享#学习方法

问题&#xff1a;人的安全知识和技能是天生的。&#xff08;) 人的安全知识和技能是天生的。() 参考答案如图所示 问题&#xff1a;&#xff08;&#xff09;是党和国家的根本所在、命脉所在&#xff0c;是全国各族人民的利益所在、幸福所在。 A.人民当家作主 B.坚持和完善…...

【数据分享】2001~2020年青藏高原植被净初级生产力数据集

各位同学们好&#xff0c;今天和大伙儿分享的是2001~2020年青藏高原植被净初级生产力数据集。如果大家有下载处理数据等方面的问题&#xff0c;您可以私信或评论。 朱军涛. (2022). 青藏高原植被净初级生产力数据集&#xff08;2001-2020&#xff09;. 国家青藏高原数据中心. …...

【Spring MVC篇】返回响应

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Spring MVC】 本专栏旨在分享学习Spring MVC的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、返回静态页面…...

阿里云BGP多线精品EIP香港CN2线路低时延,价格贵

阿里云香港等地域服务器的网络线路类型可以选择BGP&#xff08;多线&#xff09;和 BGP&#xff08;多线&#xff09;精品&#xff0c;普通的BGP多线和精品有什么区别&#xff1f;BGP&#xff08;多线&#xff09;适用于香港本地、香港和海外之间的互联网访问。使用BGP&#xf…...

(08)Hive——Join连接、谓词下推

前言 Hive-3.1.2版本支持6种join语法。分别是&#xff1a;inner join&#xff08;内连接&#xff09;、left join&#xff08;左连接&#xff09;、right join&#xff08;右连接&#xff09;、full outer join&#xff08;全外连接&#xff09;、left semi join&#xff08;左…...

创新技巧|迁移到 Google Analytics 4 时如何保存历史 Universal Analytics 数据

Google Universal Analytics 从 2023 年 7 月起停止收集数据&#xff08;除了付费 GA360 之外&#xff09;。它被Google Analytics 4取代。为此&#xff0c;不少用户疑惑&#xff1a;是否可以将累积&#xff08;历史&#xff09;数据从 Google Analytics Universal 传输到 Goog…...

一个小而实用的 Python 包 pangu,实现在中文和半宽字符(字母、数字和符号)之间自动插入空格

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一个小巧的库&#xff0c;可以避免自己重新开发功能。利用 Python 包 pangu&#xff0c;可以轻松实现在 CJK&#xff08;中文、日文、韩文&#xff09;和半宽字符&#xff08;字母、数字和符号&#xf…...

openJudge | 中位数 C语言

总时间限制: 2000ms 内存限制: 65536kB 描述 中位数定义&#xff1a;一组数据按从小到大的顺序依次排列&#xff0c;处在中间位置的一个数或最中间两个数据的平均值&#xff08;如果这组数的个数为奇数&#xff0c;则中位数为位于中间位置的那个数&#xff1b;如果这组数的个…...

ctfshow-文件上传(web151-web161)

目录 web151 web152 web153 web154 web155 web156 web157 web158 web159 web160 web161 web151 提示前台验证不可靠 那限制条件估计就是在前端设置的 上传php小马后 弹出了窗口说不支持的格式 查看源码 这一条很关键 这种不懂直接ai搜 意思就是限制了上传类型 允许…...

cudnn免登录下载

现在要下载cuDNN&#xff0c;点击下载的页面后都是出现要求先加入Nvidia developers才能进行下载&#xff0c;但这个注册的过程非常慢&#xff0c;常常卡在第二个步骤&#xff0c;这里根据亲身的经验介绍一个可以绕过这个注册或登陆步骤的方式直接下载cuDNN。遇到此类问题的可以…...

SQLyog安装配置(注册码)连接MySQL

下载资源 博主给你打包好了安装包&#xff0c;在网盘里&#xff0c;只有几Mb&#xff0c;防止你下载到钓鱼软件 快说谢谢博主&#xff08;然后心甘情愿的点个赞~&#x1f60a;&#xff09; SQLyog.zip 安装流程 ①下载好压缩包后并解压 ②打开文件夹&#xff0c;双击安装包 ③…...

java+SSM+mysql 开放式实验管理系统78512-计算机毕业设计项目选题推荐(免费领源码)

摘 要 我国高校开放式实验管理普遍存在实验设备使用率较低、管理制度不完善,实验设备共享程度不高等诸多问题。要在更大范围推行开放式实验管理,就必须在开放式实验教学管理流程中,通过引入信息化管理加大信息技术在其中的应用,才能真正发挥这种教学模式的开放性优势。 本系统…...

代码随想录算法训练营第三十三天|1005.K次取反后最大化的数组和、134.加油站、135.分发糖果

1005.K次取反后最大化的数组和 public class Solution {public int LargestSumAfterKNegations(int[] nums, int k) {int cnt0;int sum0;int minint.MaxValue;Array.Sort(nums);for(int i0;i<nums.Length;i){if(nums[i]>0){continue;}else{nums[i]-nums[i];cnt;}if(cntk…...

解决LeetCode编译器报错的技巧:正确处理位操作中的数据类型

一天我在leetcode上刷题时&#xff0c;遇到了这样的题目&#xff1a; 随即我写了如下的代码&#xff1a; int convertInteger(int A, int B) {int count 0;int C A ^ B;int flag 1;while(flag){if (C & flag){count;}flag<<1;}return count;} 但LeetCode显示如下…...

一周学会Django5 Python Web开发-Django5操作命令

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计11条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…...

反转链表【基础算法精讲 06】

视频地址 反转链表【基础算法精讲 06】_哔哩哔哩_bilibili 概念 链表的每一个结点都包含节点值 和1指向下一个结点的next指针 , 链表的最后一个结点指向空; 206 . 反转链表 用cur记录当前遍历到的结点 &#xff0c; 用pre表示下一个结点 &#xff0c; 用nxt表示cur的下一个…...

Git 初学

目录 一、需求的产生 二、版本控制系统理解 1. 认识版本控制系统 2. 版本控制系统分类 &#xff08;1&#xff09;集中式版本控制系统 缺点&#xff1a; &#xff08;2&#xff09;分布式版本控制系统 三、初识 git 四、git 的使用 例&#xff1a;将 “ OLED文件夹 ”…...

智胜未来,新时代IT技术人风口攻略-第四版(弃稿)

文章目录 前言鸿蒙生态科普调研人员画像高校助力鸿蒙高校鸿蒙课程开设占比教研力量并非唯一原因 企业布局规划全盘接纳仍需一段时间企业对鸿蒙的一些诉求 机构入场红利机构鸿蒙课程开设占比机构对鸿蒙的一些诉求 鸿蒙实际体验高校用户群体高度认同与影响体验企业用户群体未来可…...

渗透专用虚拟机(公开版)

0x01 工具介绍 okfafu渗透虚拟机公开版。解压密码&#xff1a;Mrl64Miku&#xff0c;压缩包大小&#xff1a;15.5G&#xff0c;解压后大小&#xff1a;16.5G。安装的软件已分类并在桌面中体现&#xff0c;也可以使用everything进行查找。包含一些常用的渗透工具以及一些基本工…...

HCIA-HarmonyOS设备开发认证V2.0-3.2.轻量系统内核基础-时间管理

目录 一、时间管理1.1、时间接口1.2、代码分析&#xff08;待续...&#xff09; 坚持就有收获 一、时间管理 时间管理以系统时钟为基础&#xff0c;给应用程序提供所有和时间有关的服务。系统时钟是由定时器/计数器产生的输出脉冲触发中断产生的&#xff0c;一般定义为整数或长…...

嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第五天-ARM Linux编程之file_operations详解 (物联技术666)

链接&#xff1a;https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd1688 提取码&#xff1a;1688 struct file_operations{ struct module *owner; // 指向拥有该结构的模块的指针&#xff0c;避免正在操作时被卸载&#xff0c;一般为初始化THIS_MODULES loff_t &#…...

第9章 网络编程

9.1 网络通信协议 通过计算机网络可以实现多台计算机连接&#xff0c;但是不同计算机的操作系统和硬件体系结构不同&#xff0c;为了提供通信支持&#xff0c;位于同一个网络中的计算机在进行连接和通信时必须要遵守一定的规则&#xff0c;这就好比在道路中行驶的汽车一定要遵…...

Python setattr函数

在Python编程中&#xff0c;setattr()函数是一个有用且灵活的内置函数&#xff0c;用于设置对象的属性值。它可以在运行时动态地设置对象的属性&#xff0c;无论是新建对象还是已有对象。本文将深入探讨setattr()函数的用法、语法、示例代码&#xff0c;并探讨其在实际编程中的…...

[C#]winform制作仪表盘好用的表盘控件和使用方法

【仪表盘一般创建流程】 在C#中制作仪表盘文案&#xff08;通常指仪表盘上的文本、数字或指标显示&#xff09;涉及到使用图形用户界面&#xff08;GUI&#xff09;组件&#xff0c;比如Windows Forms、WPF (Windows Presentation Foundation) 或 ASP.NET 等。以下是一个使用W…...

探索弗洛姆的思想:人类本质与爱的哲学

探索弗洛姆的思想&#xff1a;人类本质与爱的哲学 摘要&#xff1a;艾里希弗洛姆是20世纪著名的德裔美国哲学家和精神分析学家&#xff0c;他的理论在心理学、社会学和哲学领域均产生了广泛影响。弗洛姆的核心思想围绕人的本性、自由发展以及爱的重要性展开&#xff0c;强调了人…...

【碎片知识点】安装Linux系统 VMware与kali

天命&#xff1a;VMware就是可以运行操作系统的载体&#xff0c;kali就是Linux的其中一个分支 天命&#xff1a;Linux有两个分支版本&#xff1a;centos与ubuntu&#xff0c;kali底层就是ubuntu&#xff08;所有Linux用起来都差不多&#xff0c;没啥区别&#xff09; 天命&…...

Android 车载应用开发之SystemUI 详解

一、SystemUI SystemUI全称System User Interface,直译过来就是系统级用户交互界面,在 Android 系统中由SystemUI负责统一管理整个系统层的 UI,它是一个系统级应用程序(APK),源码在/frameworks/base/packages/目录下,而不是在/packages/目录下,这也说明了SystemUI这个…...

C# CAD-Xdata数据 添加(一)

运行环境Visual Studio 2022 c# cad2016 一、XData&#xff08;扩展数据&#xff09;特定代码值 XData&#xff08;扩展数据&#xff09;特定代码值 XData通过一系列DXF组码&#xff08;DxfCode&#xff09;存储不同类型的数据&#xff0c;包括但不限于ASCII字符串、已注册应…...

【NLP】MHA、MQA、GQA机制的区别

Note LLama2的注意力机制使用了GQA。三种机制的图如下&#xff1a; MHA机制&#xff08;Multi-head Attention&#xff09; MHA&#xff08;Multi-head Attention&#xff09;是标准的多头注意力机制&#xff0c;包含h个Query、Key 和 Value 矩阵。所有注意力头的 Key 和 V…...

nginx upstream server主动健康监测模块添加https检测功能

1 缘起 前面的《nginx upstream server主动健康检测模块ngx_http_upstream_check_module 使用和源码分析》系列已经分析了ngx_http_upstream_check_module的实现原理&#xff0c;并且在借助这个模块的框架实现了一个udp健康检测的新功能。   但是ngx_http_upstream_check_mod…...

OCP的operator——(4)用户任务:使用Operator创建etcd集群

文章目录 环境在namespace中安装Operator先决条件使用Web console从OperatorHub安装删除 使用CLI从OperatorHub安装从已安装的Operator创建应用使用Operator创建etcd集群报错从web console debug从命令行debug分析 参考 环境 RHEL 9.3Red Hat OpenShift Local 2.32 在namespa…...

win7自带截图工具保存失效解决办法

今日发现一台远航技术的win7中自带的截图工具使用时正常&#xff0c;保存图片时没有弹出保存位置的对话窗口&#xff0c;无法正常保存图片。解决方案如下&#xff1a; 1、进入注册表编辑器。开始-搜索程序和文件-输入 regedit 按下回车键&#xff0c;打开注册表&#xff1b; 2、…...

Android14之Android Rust模块编译语法(一百八十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…...

分布式文件系统 SpringBoot+FastDFS+Vue.js【三】

分布式文件系统 SpringBootFastDFSVue.js【三】 七、创建后台--分角色管理7.1.创建后台数据库表7.2.创建实体类7.2.1.Admin7.2.2.Menu7.2.3.MenuBean7.2.4.Role7.2.5.RoleMenu 7.3.编辑配置文件application.yml7.4.编写工具类7.4.1.AuthContextHolder7.4.2.HttpUtils7.4.3.Stri…...

【深度学习每日小知识】全景分割

全景分割 全景分割是一项计算机视觉任务&#xff0c;涉及将图像或视频分割成不同的对象及其各自的部分&#xff0c;并用相应的类别标记每个像素。与传统的语义分割相比&#xff0c;它是一种更全面的图像分割方法&#xff0c;传统的语义分割仅将图像划分为类别&#xff0c;而不…...

机器人能否返回原点

657. 机器人能否返回原点 在二维平面上&#xff0c;有一个机器人从原点 (0, 0) 开始。给出它的移动顺序&#xff0c;判断这个机器人在完成移动后是否在 (0, 0) 处结束。 移动顺序由字符串 moves 表示。字符 move[i] 表示其第 i 次移动。机器人的有效动作有 R&#xff08;右&a…...

Mysql5.6忘记密码,如何找回(windows)

mysql5.6安装 第一步&#xff1a;关闭正在运行的数据库服务 net stop mysql第二步&#xff1a;在my.ini文件当中的[mysqld] 任意一个位置放入 skip-grant-tables第三步&#xff1a;启动mysql服务 net start mysql第四步&#xff1a;服务启动成功后就可以登录了&#xff0c;…...

算法训练营day29, 贪心算法3

import ( "sort" ) // 1005. K 次取反后最大化的数组和 func largestSumAfterKNegations(nums []int, k int) int { //先从小到大排序 sort.Ints(nums) sum : 0 //将数组中负数转为正数 for i : 0; i < len(nums); i { if nums[i] < 0 && k > 0 …...

164基于matlab的奇异值分解、小波降噪、zoom细化

基于matlab的奇异值分解、小波降噪、zoom细化。程序已调通&#xff0c;可直接运行。 164 奇异值分解 小波降噪 zoom细化 (xiaohongshu.com)...

每日OJ题_算法_递归③力扣206. 反转链表

目录 力扣206. 反转链表 解析代码 力扣206. 反转链表 206. 反转链表 LCR 024. 反转链表 难度 简单 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,…...

【Linux】指令 【whereis】

whereis是一个用于查找特定文件在文件系统中的位置的命令。 主要查找二进制文件或帮助文件&#xff0c;适用于那些不属于常规文件系统的特殊文件。 查找ping命令的二进制文件&#xff0c;你可以使用如下命令&#xff1a; whereis -b ping查看命令的帮助文件&#xff0c;可以添…...

牛客网SQL进阶128:未完成试卷数大于1的有效用户

官网链接&#xff1a; 未完成试卷数大于1的有效用户_牛客题霸_牛客网现有试卷作答记录表exam_record&#xff08;uid用户ID, exam_id试卷ID, st。题目来自【牛客题霸】https://www.nowcoder.com/practice/46cb7a33f7204f3ba7f6536d2fc04286?tpId240&tqId2183007&ru%2…...

GitHub的使用操作

记得看目录哦&#xff01; 1. 创建仓库2. 下载desktop3. 把创建的库克隆到本地4. 文件拷贝到本地仓库![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/7171ac6c4ca14e3b8d22717121f79c9e.png)5. 在网址后面加/compare进行比较6. 给系统添加功能 1. 创建仓库 2. 下载…...

智慧公厕管理软件

随着城市化的不断推进&#xff0c;城市公共设施逐渐完善&#xff0c;其中智慧公厕的建设也在不断提速。智慧公厕作为城市基础设施的重要组成部分&#xff0c;对城市卫生水平提升有着不可忽视的作用。而智慧公厕管理软件更是智慧公厕管理的基础&#xff0c;是公共厕所智慧化管理…...

【30秒看懂大数据】数据中台

知幽科技是一家专注企业数字/智化&#xff0c;围绕数据价值应用的一站式数智化解决方案的咨询公司&#xff0c;也包括了为企业提供定制化数据培训&#xff0c;力求做企业最好的数智化决策伙伴。 点击上方「蓝字」关注我们 30秒看懂大数据专栏 让您在有限的碎片化时间&#xf…...

【UI自动化测试技术】自动化测试研究:Python+Selenium+Pytest+Allure,详解UI自动化测试,了解元素交互的常用方法(精)(三)

导言 在之前的文章里&#xff0c;我们一起学习了定位方式、等待机制等内容。相信通过之前的学习&#xff0c;你已经掌握了WEB自动化的一些入门知识&#xff0c;具备了编写代码的一些基础知识和能力。这篇文章&#xff0c;让我们一起学习一下模拟键盘事件。 在实际的项目当中&a…...

GPT-4带来的思想火花

GPT-4能够以其强大的生成能力和广泛的知识储备激发出众多思想火花。它能够在不同的情境下生成新颖的观点、独特的见解和富有创意的解决方案&#xff0c;这不仅有助于用户突破思维定势&#xff0c;还能促进知识与信息在不同领域的交叉融合。 1.GPT-4出色的创新思考和知识整合能…...