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

Go内存管理

内存管理

文章目录

  • 内存管理
    • 何为内存?
    • 内存为什么需要管理?
    • 内存管理的方式
      • 操作系统存储模型
      • 操作系统是怎么管理内存的?
      • 虚拟内存与物理内存
      • 认识虚拟内存
      • 分页管理
    • Golang 内存模型
      • TCMalloc核心概念
      • go内存管理核心概念
      • GO内存分配
      • GO 内存逃逸机制
        • 一、内存逃逸的本质
        • 二、逃逸分析的核心策略
        • 三、常见逃逸场景解析
          • 1. **指针逃逸**
          • 2. **栈空间不足逃逸**
          • 3. **动态类型逃逸**
          • 4. **闭包引用逃逸**
          • 5. **接口方法调用**
          • 6. **切片动态扩容**
        • 四、逃逸分析的影响
        • 五、如何检测逃逸
      • GO 内存泄漏
        • 内存泄漏定义
        • 常见涉及语言
        • 常见场景
        • 内存泄漏检测与解决
          • 总的来说
          • **工具使用**

何为内存?

  1. 来源:基于内存条
  2. 作用:程序逻辑临时使用时用的变量、全局变量、静态库、函数跳转地址、执行代码、临时开辟的结构体对象

内存为什么需要管理?

  1. 内存中存储的数据越来越多,导致物理内存不足[每个程序索要的内存是程序的极限内存](需要提高内存的利用率和合理分配性)

对于一些语言如:go、java、python,为了能让开发者更关注程序本身的逻辑,提供了一套针对自身程序的内存管理模式:虚拟内存

内存管理的方式

操作系统存储模型

观察上图,我们可以从中捕捉到的关键词是:

  • 多级模型
  • 动态切换

操作系统是怎么管理内存的?

存在问题:

  1. 物理内存无法最大化使用
  2. 程序逻辑内存使用空间独立
  3. 物理内存不足

解决手段:

  1. 读时共享
  2. 写时复制
  3. 内存不足时部分磁盘虚拟化

虚拟内存与物理内存

虚拟内存:一连串连续的逻辑内存,逻辑内存地址映射真实物理内存地址

物理内存:真实基于内存条的实际内存。

认识虚拟内存

虚拟内存的作用:

  • 在用户与硬件间添加中间代理层(没有什么是加一个中间层解决不了的)
  • 优化用户体验(进程感知到获得的内存空间是“连续”的)
  • “放大”可用内存(虚拟内存可以由物理内存+磁盘补足,并根据冷热动态置换,用户无感知)

分页管理

操作系统中通常会将虚拟内存和物理内存切割成固定的尺寸,于虚拟内存而言叫作“页”,于物理内存而言叫作“帧”,原因及要点如下:

  • 提高内存空间利用(以页为粒度后,消灭了不稳定的外部碎片,取而代之的是相对可控的内部碎片)
  • 提高内外存交换效率(更细的粒度带来了更高的灵活度)
  • 与虚拟内存机制呼应,便于建立虚拟地址->物理地址的映射关系(聚合映射关系的数据结构,称为页表)
  • linux 页/帧的大小固定,为 4KB(这实际是由实践推动的经验值,太粗会增加碎片率,太细会增加分配频率影响效率)

内部碎片:比如:页内的内存浪费(7字节可能分配8字节的空间;内存对齐补齐的内存;内存池的预留内存)

外部碎片:比如:内存分配对象大小、释放时机(不可控)[需要考虑物理内存的连续性,比如:剩余两块内存,4KB和2KB的内存块。现在需要6KB的连续物理空间,不存在则分配内存失败]

但是,此时如果存在分页管理,外部的空闲内存块以页帧为单位管理。只要页帧足够,就可以进行内存分配,不需要连续的内存块。这就实现了彻底消除外部碎片的效果。

Golang 内存模型

首先,golang中借用操作系统的存储模型和TCMalloc。理解 TCMalloc 可以有助于理解 go内存管理。虽然之后 Go的内存管理 与TCMalloc不一致地方在不断扩大,但其主要思想、原理和概念都是和TCMalloc一致的…

  1. 借鉴了操作系统的多级缓存和分页管理的机制
  2. 借鉴了TCMalloc。TCMalloc是 Google 开发的一款高效内存分配器,TCMalloc 通过独特设计减少锁竞争,提升多线程环境下内存分配和释放效率 。

TCMalloc核心概念

  • Page

操作系统对内存管理以页为单位,TCMalloc也是这样,只不过TCMalloc里的Page大小与操作系统里的大小并不一定相等,而是倍数关系。《TCMalloc解密》里称x64下Page大小是8KB。

  • Span

一组连续的Page被称为Span,比如可以有2个页大小的Span,也可以有16页大小的Span,Span比Page高一个层级,是为了方便管理一定大小的内存区域,Span是TCMalloc中内存管理的基本单位。

  • ThreadCache

ThreadCache是每个线程各自的Cache,一个Cache包含多个空闲内存块链表,每个链表连接的都是内存块,同一个链表上内存块的大小是相同的,也可以说按内存块大小,给内存块分了个类,这样可以根据申请的内存大小,快速从合适的链表选择空闲内存块。由于每个线程有自己的ThreadCache,所以ThreadCache访问是无锁的。

  • CentralCache

CentralCache是所有线程共享的缓存,也是保存的空闲内存块链表,链表的数量与ThreadCache中链表数量相同,当ThreadCache的内存块不足时,可以从CentralCache获取内存块;当ThreadCache内存块过多时,可以放回CentralCache。由于CentralCache是共享的,所以它的访问是要加锁的。

  • PageHeap

PageHeap是对堆内存的抽象,PageHeap存的也是若干链表,链表保存的是Span。当CentralCache的内存不足时,会从PageHeap获取空闲的内存Span,然后把1个Span拆成若干内存块,添加到对应大小的链表中并分配内存;当CentralCache的内存过多时,会把空闲的内存块放回PageHeap中。

如下图所示,分别是1页Page的Span链表,2页Page的Span链表等,最后是large span set,这个是用来保存中大对象的。毫无疑问,PageHeap也是要加锁的。

img

前文提到了小、中、大对象,Go内存管理中也有类似的概念,我们看一眼TCMalloc的定义:

  • 小对象大小:0~256KB
  • 中对象大小:257~1MB
  • 大对象大小:>1MB

小对象的分配流程:ThreadCache -> CentralCache -> HeapPage,大部分时候,ThreadCache缓存都是足够的,不需要去访问CentralCache和HeapPage,无系统调用配合无锁分配,分配效率是非常高的。

中对象分配流程:直接在PageHeap中选择适当的大小即可,128 Page的Span所保存的最大内存就是1MB。

大对象分配流程:从large span set选择合适数量的页面组成span,用来存储数据。

go内存管理核心概念

  • free(空闲内存管理相关)

  • scav(垃圾回收相关 )

  • arenas 区域是堆内存的具体分区,用于存放实际数据

  • Page

与TCMalloc中的Page相同,x64架构下1个Page的大小是8KB。上图的最下方,1个浅蓝色的长方形代表1个Page。

  • Span(即mspan)

Span与TCMalloc中的Span相同,Span是内存管理的基本单位,代码中为mspan,一组连续的Page组成1个Span,所以上图一组连续的浅蓝色长方形代表的是一组Page组成的1个Span,另外,1个淡紫色长方形为1个Span。

  • mcache

mcache与TCMalloc中的ThreadCache类似,mcache保存的是各种大小的Span,并按Span class分类,小对象直接从mcache分配内存,它起到了缓存的作用,并且可以无锁访问。但是mcache与ThreadCache也有不同点,TCMalloc中是每个线程1个ThreadCache,Go中是每个P拥有1个mcache。因为在Go程序中,当前最多有GOMAXPROCS个线程在运行,所以最多需要GOMAXPROCS个mcache就可以保证各线程对mcache的无锁访问,线程的运行又是与P绑定的,把mcache交给P刚刚好。

  • mcentral

mcentral与TCMalloc中的CentralCache类似,是所有线程共享的缓存,需要加锁访问。它按Span级别对Span分类,然后串联成链表,当mcache的某个级别Span的内存被分配光时,它会向mcentral申请1个当前级别的Span。

但是mcentral与CentralCache也有不同点,CentralCache是每个级别的Span有1个链表,mcentral是每个级别的Span有2个链表,这和mcentral申请内存有关,有指针(contains pointers)的 Span 链表[存储包含 Go 指针的对象,这些 Span 需要参与垃圾回收标记过程。]和无指针(no pointers)的 Span 链表[存储纯值类型(如整数、浮点数、字符串等),这些 Span 在垃圾回收时可以直接跳过扫描,提高 GC 效率。].

  • mheap

mheap与TCMalloc中的PageHeap类似,它是堆内存的抽象,把从OS申请出的内存页组织成Span,并保存起来。当mcentral的Span不够用时会向mheap申请内存,而mheap的Span不够用时会向OS申请内存。mheap向OS的内存申请是按页来的,然后把申请来的内存页生成Span组织起来,同样也是需要加锁访问的。

但是mheap与PageHeap也有不同点:mheap把Span组织成了树结构,而不是链表,并且还是2棵树,然后把Span分配到heapArena进行管理,它包含地址映射和span是否包含指针等位图,这样做的主要原因是为了更高效的利用内存:分配、回收和再利用。

总体来说:

  • mheap 是全局内存池,管理所有堆内存,并包含所有mcentral实例。(只有一个)
  • mcentral 按span-class(对象大小规格 + 是否含指针)维护 mspan 链表:
    • 每个span-class对应一个mcentral,负责为该规格分配 / 回收mspan
    • mheap申请大块内存(mspan),切割为小块对象后,供mcache缓存。
    • 数量和 span-class 相关(1:1)
  • mcache是每个P独占的本地缓存,包含各 span-class 对应的 mspan 链表:
    • mcentral获取特定span-classmspan,避免频繁加锁访问全局资源。
    • 直接为Goroutine分配对象,提升分配效率。
    • 数量和P相关(1:1)
  • span-class 定义mspan管理的对象大小范围和属性(如是否含指针),是内存分层管理的核心规格。
    • span-class对应的是小对象(大对象是单独独占一个span)
    • 67种

它们通过分层协作,实现了高效的并发内存分配与管理。

  1. object size:代码里简称size,指申请内存的对象大小。
  2. size class:代码里简称class,它是size的级别,相当于把size归类到一定大小的区间段,比如size[1,8]属于size class 1,size(8,16]属于size class 2。
  3. span class:指span的级别,但span class的大小与span的大小并没有正比关系。span class主要用来和size class做对应,1个size class对应2个span class,2个span class的span大小相同,只是功能不同,1个用来存放包含指针的对象,一个用来存放不包含指针的对象,不包含指针对象的Span就无需GC扫描了。
  4. num of page:代码里简称npage,代表Page的数量,其实就是Span包含的页数,用来分配内存。

GO内存分配

按对象大小分配:

0~16B,不包含指针的对象 Tiny分配(span-class)

0~16B,包含指针的对象 正常分配(span-class)

16B~32KB 正常分配(span-class)

32KB ~ ∞ 大对象分配(mspan独占)

分配调用流程:

在这里插入图片描述

GO 内存逃逸机制

一、内存逃逸的本质

Go 语言中的内存逃逸是编译器优化技术,核心目标是自动决定变量应该分配在栈上还是堆上。其触发条件是变量的生命周期超出当前函数的作用域。这种机制允许 Go 开发者无需手动管理内存(如 C++ 中的 new/delete),同时保证程序的内存安全。

二、逃逸分析的核心策略

逃逸分析的决策逻辑可总结为:

  1. 外部引用原则

    • 如果变量在函数外部存在引用(如返回指针、赋值给全局变量等),必须分配在堆上

    • 示例:

      func escapeToHeap() *int {x := 10  // x逃逸到堆return &x
      }
      
  2. 栈优先原则

    • 如果变量仅在函数内部使用(无外部引用),优先分配在栈上

    • 示例:

      func stayOnStack() int {x := 10  // x分配在栈上return x
      }
      
  3. 栈容量限制

    • 即使无外部引用,如果变量占用内存过大(超过栈空间限制),仍会分配到堆上
    • 具体阈值与 Go 版本和平台有关(通常为几 KB 到几十 KB)
  4. 动态类型约束

    • 当变量类型为interface{}时(动态类型),由于编译期无法确定实际类型大小,必须逃逸到堆

    • 示例:

      func dynamicTypeEscape() interface{} {x := struct{}{}  // x逃逸到堆return x
      }
      
  5. 引用类型发生二次间接引用极大可能逃逸

    引用类型:func()函数类型;interface{}接口类型;slice;map;channel;*(指针类型);

    二次间接引用场景举例:func([]string) ; map[string]interface{} ; slice[*int] ; chan []stirng

    其中标中的类型为将要逃逸的类型

三、常见逃逸场景解析
1. 指针逃逸
  • 场景:函数返回局部变量的指针

  • 原因:指针在函数外部被引用,生命周期超出函数范围

  • 示例:

    func createPtr() *int {x := 10  // x逃逸到堆return &x
    }
    
2. 栈空间不足逃逸
  • 场景:创建大型数组或结构体

  • 原因:栈空间有限(通常为几 MB),大型对象会导致栈溢出

  • 示例:

    func largeArray() {arr := [1000000]int{}  // 可能逃逸到堆
    }
    
3. 动态类型逃逸
  • 场景:将对象赋值给 interface {} 类型

  • 原因:interface {} 的底层实现需要指针和类型信息,编译期无法确定实际大小

  • 示例:

    func printAny(x interface{}) {fmt.Println(x)
    }func callPrintAny() {num := 42  // num逃逸到堆printAny(num)
    }
    
4. 闭包引用逃逸
  • 场景:闭包引用外部函数的局部变量

  • 原因:闭包可能在外部函数返回后执行,需要保证变量生命周期

  • 示例:

    func closureEscape() func() int {x := 10  // x逃逸到堆return func() int {return x}
    }
    
5. 接口方法调用
  • 场景:通过接口调用方法

  • 原因:接口调用需要动态分派,可能导致接收者逃逸

  • 示例:

    type Printer interface {Print()
    }type Data struct {Value int
    }func (d Data) Print() {fmt.Println(d.Value)
    }func interfaceEscape(p Printer) {p.Print()  // 可能导致p的接收者逃逸
    }
    
6. 切片动态扩容
  • 场景:append 操作导致切片容量超过预分配值

  • 原因:扩容时需要分配新的底层数组,并复制数据

  • 示例:

    func sliceEscape() {s := make([]int, 0, 1)s = append(s, 1)  // 第一次append可能不逃逸s = append(s, 2)  // 第二次append可能导致扩容,底层数组逃逸到堆
    }
    
四、逃逸分析的影响
  1. 性能影响
    • 堆分配比栈分配慢(涉及 GC 开销)
    • 过度逃逸会导致 GC 压力增大,降低程序性能
  2. 内存布局
    • 栈上对象随函数返回自动回收
    • 堆上对象需要 GC 周期回收,可能导致内存碎片
  3. 代码优化建议
    • 尽量避免返回局部变量的指针
    • 减少使用 interface {} 类型
    • 预估切片容量,减少动态扩容
    • 优先使用值接收者而非指针接收者(除非需要修改原对象)
五、如何检测逃逸
  1. 编译命令

    go build -gcflags="-m -m" main.go
    
    • -m 选项显示逃逸分析信息
    • 多个-m会输出更详细的分析
  2. 典型输出示例

    ./main.go:10:9: &x escapes to heap:
    ./main.go:10:9:   flow: ~r0 = &x:
    ./main.go:10:9:     from &x (address-of) at ./main.go:11:9
    ./main.go:10:9:     from return &x (return) at ./main.go:11:2
    

通过理解和利用逃逸分析机制,Go 开发者可以写出更高效、更符合语言特性的代码,避免不必要的堆分配和 GC 压力。

GO 内存泄漏

内存泄漏定义

内存泄漏指程序中已分配的内存,在使用完毕后因未被正确释放或无法被回收,导致这部分内存资源持续占用,无法重新分配利用。随着时间推移,泄漏的内存不断累积,最终会耗尽系统资源,引发程序性能严重下降、响应迟缓,甚至导致程序崩溃或系统不稳定。在 Go 语言中,尽管拥有自动垃圾回收(GC)机制,但由于代码逻辑缺陷,仍可能产生内存泄漏问题 。

常见涉及语言
  1. 手动内存管理语言(如 C/C++):开发者需手动使用malloc/freenew/delete等函数分配和释放内存。一旦遗漏释放操作,或者释放逻辑错误(如重复释放、释放时机不当),就会造成内存泄漏。例如在 C 语言中,若动态分配内存后忘记调用free函数:
int* ptr = (int*)malloc(sizeof(int));
// 使用ptr
// 未调用free(ptr),导致内存泄漏
  1. 自动 GC 语言(如 Go、Java):这类语言依赖自动垃圾回收机制来管理内存,理论上无需开发者手动释放内存。然而,若代码中存在对象的无效引用、循环引用、资源未关闭等情况,也会导致内存无法被 GC 回收,从而引发内存泄漏。例如在 Go 语言中,即使有 GC,错误的代码逻辑仍会导致泄漏。
常见场景
  1. 对象长期引用但不使用
    • 原理:程序中存在对象被长期持有引用,但后续不再使用该对象,导致 GC 无法回收其占用的内存。例如,将对象放入全局变量或静态集合中,却不再对其进行任何操作。
    • 示例
var globalList []*MyObjectfunc createObject() {obj := &MyObject{}globalList = append(globalList, obj)// 后续不再使用obj,但globalList持续引用,导致obj无法被回收
}
  1. 循环引用
    • 原理:多个对象之间形成环形引用关系,导致每个对象都被其他对象引用,即使这些对象实际已不再被程序使用,GC 也无法识别并回收它们。虽然 Go 语言的 GC 采用三色标记法,一定程度上能处理循环引用,但复杂的数据结构仍可能出现问题。
    • 示例
type Node struct {data intnext *Node
}func createCycle() {a := &Node{}b := &Node{}a.next = bb.next = a// a和b形成循环引用,若后续无其他引用,仍可能导致内存泄漏
}
  1. goroutine 永久性阻塞
    • 原理:启动的 goroutine 因死锁、等待永远不会满足的条件(如无缓冲通道接收操作但无发送操作)等原因被永久阻塞,且 goroutine 内部持有的资源无法释放,随着大量阻塞 goroutine 的创建,会消耗大量内存资源。
    • 示例
func blockedGoroutine() {ch := make(chan int)go func() {<-ch // 等待接收,但无其他协程向ch发送数据,导致该协程永久阻塞}()
}
  1. 资源未关闭
    • 原理:在操作文件、网络连接、数据库连接等资源时,若未调用对应的关闭方法释放资源,资源相关的内存及系统句柄等会持续占用,无法被回收。
    • 示例
func readFileWithoutClose() {file, err := os.Open("test.txt")if err != nil {return}// 未调用file.Close()关闭文件,可能导致内存泄漏及文件句柄资源占用data := make([]byte, 1024)file.Read(data)
}
  1. 定时器未清理
    • 原理:创建的定时器(time.Timertime.Ticker)若不再使用却未停止或清理,会持续占用内存及系统资源,导致泄漏。
    • 示例
func leakTimer() {ticker := time.NewTicker(time.Second)go func() {for {<-ticker.C// 业务逻辑,但未停止ticker,若该协程持续运行,会导致泄漏}}()
}
内存泄漏检测与解决
总的来说
  1. 定期内存分析:使用 pprof 定期监控内存使用情况,对比不同时间点的内存快照。
  2. goroutine 数量监控:统计活跃 goroutine 数量,异常增长可能意味着存在阻塞。
  3. 资源管理原则:
    • 打开资源后立即使用 defer 关闭
    • 使用 context.Context 控制 goroutine 生命周期
    • 优先使用无状态或短生命周期的对象
  4. 测试覆盖:编写压力测试,模拟长时间运行场景,检测内存增长趋势。

通过结合工具检测和代码优化,可以有效避免 Go 程序中的内存泄漏问题。

工具使用
  1. pprof 工具

作用:分析内存分配和使用情况,定位内存泄漏点。

示例代码(存在内存泄漏):

package mainimport ("net/http"_ "net/http/pprof"
)var data []bytefunc leakHandler(w http.ResponseWriter, r *http.Request) {// 每次请求都会追加1MB数据,但从不清理data = append(data, make([]byte, 1024*1024)...)w.Write([]byte("Memory leaked!"))
}func main() {http.HandleFunc("/leak", leakHandler)// 启动pprof服务http.ListenAndServe(":6060", nil)
}

检测步骤

  1. 启动程序go run main.go

  2. 触发泄漏:多次访问 http://localhost:6060/leak

  3. 采集内存快照:

    go tool pprof http://localhost:6060/debug/pprof/heap
    
  4. 分析结果:

    (pprof) top 10  # 查看内存占用最高的10个函数
    (pprof) list leakHandler  # 查看leakHandler函数的内存分配情况
    (pprof) web  # 可视化分析(需安装graphviz)
    

关键指标

  • inuse_space:当前堆上占用的内存
  • alloc_space:程序运行期间累计分配的内存
  • 若两者差距持续增大,可能存在泄漏。
  1. go tool trace

作用:可视化程序运行过程,发现阻塞的 goroutine。

示例代码(存在 goroutine 阻塞):

package mainimport ("os""runtime/trace"
)func main() {f, _ := os.Create("trace.out")defer f.Close()trace.Start(f)defer trace.Stop()ch := make(chan int)go func() {<-ch // 无发送操作,永久阻塞}()select {} // 主协程阻塞
}

检测步骤

  1. 生成跟踪文件go run main.go

  2. 分析跟踪文件:

    go tool trace trace.out
    
  3. 在浏览器中查看:

    • 选择 Goroutine analysis 查看阻塞的 goroutine
    • 选择 Network blocking profile 查看网络阻塞情况

相关文章:

Go内存管理

内存管理 文章目录 内存管理何为内存&#xff1f;内存为什么需要管理&#xff1f;内存管理的方式操作系统存储模型操作系统是怎么管理内存的&#xff1f;虚拟内存与物理内存认识虚拟内存分页管理 Golang 内存模型TCMalloc核心概念go内存管理核心概念GO内存分配GO 内存逃逸机制一…...

解决软件连接RabbitMQ突发System.IO.IOException: 无法从传输连接中读取数据: 远程主机强迫关闭了一个现有的连接异常

一、问题描述 系统再运行时&#xff0c;突然出现 System.Exception: [RabbitMQ.Send Error] RabbitMQ.Client.Exceptions.AlreadyClosedException: Already closed: The AMQP operation was interrupted: AMQP close-reason, initiated by Library, code541, text“Unexpected…...

基于局部显著位置感知的异常掩码合成方法在CT图像肺部疾病异常检测与病变定位中的应用|文献速递-深度学习医疗AI最新文献

Title 题目 Local salient location-aware anomaly mask synthesis for pulmonary disease anomaly detection and lesion localization in CT images 基于局部显著位置感知的异常掩码合成方法在CT图像肺部疾病异常检测与病变定位中的应用 01 文献速递介绍 肺部疾病是全球发…...

【cursor疑惑】cursor续杯后使用agent对话时,提示“需要pro或商业订阅的用户才能使用“

背景 cursor的pro会员体验过期了&#xff0c;想再次体验deepseek、Claude等agent对话提示:“免费版本不可以使用agent对话功能(英文忘记截图了&#xff0c;大意是这样)”。 处理方法 Step-1&#xff1a;再次续杯cursor的pro会员14天体验 详情&#xff0c;见&#xff1a;【c…...

2022年下半年信息系统项目管理师——综合知识真题及答案(3)

2022年下半年信息系统项目管理师 ——综合知识真题及答案&#xff08;3&#xff09; 零、时光宝盒 &#xff08;https://blog.csdn.net/weixin_69553582 逆境清醒&#xff09; 此文是我2025-05-19回复头条上某作者文章时的评论记录&#xff0c;原作者的文章是写那些被有组织…...

华为云Flexus+DeepSeek征文|基于华为云Flexus云服务的云服务器单机部署Dify-LLM应用开发平台

目录 一、前言 二、华为云Flexus云服务优势 三、华为云Flexus一键部署Dify 3.1 选择模板 3.2 参数配置 3.3 资源栈设置 3.4 配置确认 3.5 创建执行计划 3.6 部署 四、Dify-LLM应用开发平台初体验 4.1 访问Dify-LLM应用开发平台 4.2 设置管理员账户 4.3 登录Dify-LLM应用开发平台…...

NC105NC106美光固态颗粒NC108NC109

NC105NC106美光固态颗粒NC108NC109 美光固态颗粒技术矩阵深度解析&#xff1a;NC105/NC106/NC108/NC109的性能博弈与市场卡位 一、技术基因图谱&#xff1a;解密NC系列颗粒的底层架构 1. TLC与QLC的技术路线分野 美光NC系列颗粒呈现出清晰的技术分层&#xff1a;NC105/NC10…...

洛谷U536262 井底之“鸡” 附视频讲解

题目截图 题目背景 2024年山东财经大学新生赛的时候&#xff0c;xz_chicken厌倦了在鸡舍的生活&#xff0c;于是决定把他的主人ZQH写成QH鸡&#xff0c;然而除了在第一题中已经出现了ZQH所在队伍征途再起的合影&#xff0c;同时xz_chicken还露出其他马脚&#xff0c;比如说答案…...

特征筛选方法总结(面试准备15)

非模型方法 一.FILTER过滤法&#xff1a; 1.缺失值比例&#xff08;80%以上缺失则删除&#xff09;/方差 注意&#xff1a; 连续变量只删方差为0的&#xff0c;因为变量取值范围会影响方差大小。 离散类的看各类取值占比,如果是三分类变量可以视作连续变量。 函数&#xff1a;V…...

深入解析分布式数据库TiDB:原理、优化与架构实践

前言 在云计算与大数据时代&#xff0c;传统单机数据库面临三大挑战&#xff1a;海量数据存储、高并发访问和实时分析需求。MySQL 分库分表方案复杂、NoSQL 缺乏 ACID 支持、MPP 数仓难以处理 OLTP… 在这样的背景下&#xff0c;TiDB 应运而生。作为一款开源的分布式 NewSQL 数…...

YouTube视频字幕转成文章算重复内容吗?

很多创作者误以为「自己说的话不算抄袭」&#xff0c;却不知道YouTube自动生成的字幕早已被搜索引擎存档。 去年就有案例&#xff1a;某美食博主将教程视频字幕转为图文&#xff0c;结果原创度检测仅42%&#xff0c;导致页面权重暴跌。 本文揭秘5个实操技巧&#xff1a;从删除…...

codeup添加流水线docker自动化部署

在项目根目录下增加Dockerfile文件 # 使用基础镜像 FROM maven:3.8.4-openjdk-17-slim AS build # 设置工作目录 WORKDIR /app # 复制项目源代码 COPY . . # 构建项目 RUN mvn clean package -DskipTests # 验证JAR包是否生成 RUN ls -l target/your-project.jar # 使用合适的…...

面试点补充

目录 1. 搭建lnmp Linux 系统基础命令 nginx相关命令 MySQL 相关命令 PHP 相关命令 验证命令 下载并部署 Discuz! X3.4 论坛 到 Nginx 网站 2. 脑裂 2.1 脑裂的定义 2.2 脑裂产生的原因 1. 主备节点之间的心跳线中断 2. 优先级冲突 3. 系统或服务负载过高 2.3 如何…...

深入解析 Oracle session_cached_cursors 参数及性能对比实验

在 Oracle 数据库管理中&#xff0c;session_cached_cursors参数扮演着至关重要的角色&#xff0c;它直接影响着数据库的性能和资源利用效率。本文将深入剖析该参数的原理、作用&#xff0c;并通过性能对比实验&#xff0c;直观展示不同参数设置下数据库的性能表现。 一、sessi…...

MyBatis:动态SQL

文章目录 动态SQLif标签trim标签where标签set标签foreach标签include标签和sql标签 Mybatis动态SQL的官方文档&#xff1a; https://mybatis.net.cn/dynamic-sql.html 动态SQL 动态SQL是 MyBatis的强大特性之一,如果是使用JDBC根据不同条件拼接sql很麻烦&#xff0c;例如拼接…...

数据库性能调优:索引设计、缓存配置与查询计划优化

在高并发、大数据量场景下,数据库性能直接影响系统稳定性与用户体验。 本文将从索引设计、缓存配置、查询计划优化三大核心维度出发,结合实战案例与代码示例,系统解析数据库性能调优的关键策略,并深入讲解 EXPLAIN ANALYZE 与 索引覆盖策略 的应用技巧。 一、索引设计:从…...

安全强化的Linux

SElinux简介 SELinux是security-Enhanced Linux的缩写,意思是安全强化的linux SELinux主要由美国国家安全局(NSA)开发,当初开发的目的是为了避免资源的误用。传统的访问控制在我们开启权限后,系统进程可以直接访问 当我们对权限设置不严谨时,这种访问方式就是系统的安全漏洞 在…...

计算机网络(2)——应用层(上)

1.应用层概述 应用层(Application Layer)属于计算机网络体系结构中的最顶层&#xff0c;直接面向用户&#xff0c;提供各种网络服务和应用程序的接口 本文主要的学习内容如下&#xff1a; (1)网络应用进程通信方式 客户端-服务器方式点对点方式混合方式 (2)网络应用的需求与传输…...

day017-磁盘管理-实战

文章目录 1. 硬盘命名规则2. 添加硬盘2.1 查看硬盘名称 3. 硬盘分区3.1 分区命名规则&#xff1a;mbr分区表格式3.2 创建分区&#xff1a;fdisk3.2.1 fdisk -l&#xff1a;查看硬盘及分区信息3.2.2 fdisk /dev/sdc :为该硬盘分区3.2.3 创建扩展分区和逻辑分区3.2.4 保存设置并退…...

Win10 安装单机版ES(elasticsearch),整合IK分词器和安装Kibana

一. 先查看本机windows是否安装了ES(elasticsearch)&#xff0c;检查方法如下&#xff1a; 检查进程 按 Ctrl Shift Esc 组合键打开 “任务管理器”。在 “进程” 选项卡中&#xff0c;查看是否有 elasticsearch 相关进程。如果有&#xff0c;说明系统安装了 ES。 检查端口…...

STM32 控制 OLED 全攻略(二):实现字符和汉字的显示

目录 一 前言 二 OLED介绍 &#xff08;一&#xff09;SSD1306 &#xff08;二&#xff09;OLED屏幕 三 显示原理结合代码解释 1 指令---0x00 2 数据---0x40 3 初始化oled函数 4 codetab.h 四 显示字符串的原理 &#x1f9fe; ASCII 编码范围&#xff1a; ✅ OLED_S…...

c#将json字符串转换为对象数组

在C#中&#xff0c;将JSON字符串转换为对象数组是一个常见的需求&#xff0c;特别是在处理来自Web API的响应或需要反序列化本地文件内容时。这可以通过使用Newtonsoft.Json&#xff08;也称为Json.NET&#xff09;库或.NET Core内置的System.Text.Json来完成。以下是如何使用这…...

Cryosparc里头restack的妙用

在Cryosparc里头经常需要迁移job或者将particle打包成relion可以识别的模式&#xff0c;总是会遇到一个问题&#xff0c;我们需要的颗粒明明很少&#xff0c;但总是保存出一大堆东西来。原因就是&#xff0c;他会把最开初的particle都给你算进来&#xff0c;而不是某个作业对应…...

.bat文档如何运行Python程序

.bat文档如何运行Python程序 在Windows操作系统中&#xff0c;你可以通过几种方式来运行Python程序&#xff0c;即使是通过.bat批处理文件。.bat文件是一种批处理脚本&#xff0c;它允许你执行一系列命令。以下是一些步骤和示例&#xff0c;说明如何从.bat文件运行Python程序。…...

力扣HOT100之二叉树:230. 二叉搜索树中第 K 小的元素

这道题直接用最笨的办法来做的&#xff0c;用递归来做&#xff0c;我们定义一个全局变量vector<int> element&#xff0c;然后使用中序遍历&#xff0c;每当碰到一个非空节点就将其加入到向量中&#xff0c;这样依赖当向量中的元素小于k时&#xff0c;就返回0&#xff0c…...

【Nextcloud】使用 LNMP 架构搭建私有云存储:Nextcloud 实战指南

目录 一、环境准备与基础配置 1. 系统环境要求 2. 初始化系统配置 二、搭建 LNMP 基础架构 1. 一键安装 LNMP 组件 2. 启动数据库服务 三、部署 Nextcloud 存储服务 1. 上传并解压安装包 2. 设置目录权限&#xff08;测试环境配置&#xff09; 3. 配置 MariaDB 数据库…...

已知6、7、8月月平均气温和标准差,求夏季季平均温度与标准差

由下面定理&#xff0c;得出平方和的公式&#xff1a;&#xff08;即每天的温度平方和&#xff09; 这样就可以推出季平均的算法&#xff1a; 举例&#xff1a;在Excel用公式算&#xff0c;不要手算&#xff1a; 因此季平均&#xff1a;(B2*C2B3*C3B4*C4)/SUM(B2:B4) 季标准差…...

【cursor指南】cursor免费续杯pro会员试用

背景 心血来潮(其实是被逼的)&#xff0c;开始需要cursor里面的agent对话。cursor用着用着就会出现点数耗尽、试用到期等问题&#xff0c;于是自行开始找免费的cursor会员续用方法。 Part01&#xff1a;参考链接鸣谢 1. Cursor 全攻略&#xff1a;注册、使用到无限续杯&…...

Visual Studio解决方案构建三剑客:生成/重新生成/清理完全指南(实战经验总结)

文章目录 当你在VS里右键解决方案时...一、先看实战场景&#xff08;老板发飙警告&#xff09;二、三大命令解剖课&#xff08;重点标记版&#xff09;2.1 生成解决方案&#xff08;F7&#xff09;2.2 重新生成解决方案&#xff08;CtrlAltF7&#xff09;2.3 清理解决方案&…...

《JVM如何判断一个对象可以被回收?图文详解GC Root算法》

大家好呀&#xff01;我是你们的老朋友Java技术博主&#x1f44b; 今天咱们来聊聊Java虚拟机(JVM)中一个超级重要的话题——垃圾回收机制(Garbage Collection)和GC Root可达性分析&#xff01;这可是Java程序员必须掌握的核心知识点哦&#xff01;&#x1f60e; &#x1f31f;…...

常用算法/机理模型演示平台搭建(一)

算法/机理模型演示平台搭建 一、算法列表(app/algorithms)二、行业机理模型 (app/models)三、如何使用本项目旨在为初学者提供 35种 常用算法和 9种 行业机理模型的简单Python实现或概念说明。每个算法都有其独特的应用场景,从数据预测、质量检测、过程控制到结构分析和优化问…...

一文详解红黑树

一文详解红黑树 前言一、基本概念与特性1.1 红黑树的定义1.2 红黑树的特性 二、红黑树的节点结构与表示三、红黑树的基本操作3.1 插入操作3.2 删除操作 四、红黑树的应用场景4.1 编程语言的集合类4.2 数据库索引4.3 Linux 内核进程调度 总结 前言 在数据结构的领域中&#xff…...

Windows 安装显卡驱动

1.第一步&#xff1a;打开Nvidia 官网驱动下载页面 2.第二步&#xff1a;选择相关信息&#xff0c; 玩游戏选择&#xff0c;GeForce Game Ready ,创意设计、摄影直播 选择 NVIDIA Studio 驱动程序 &#xff08;NVIDIA Studio Driver - WHQL.&#xff09; 2.第三步&#xff1…...

【C语言】易错题 经典题型

出错原因&#xff1a;之前运行起来的可执行程序没有关闭 关闭即可 平均数&#xff08;average&#xff09; 输入3个整数&#xff0c;输出它们的平均值&#xff0c;保留3位小数。 #include <stdio.h> int main() {int a, b, c;scanf("%d %d %d", &a, &…...

C++类与对象--5 运算符重载

对已有的运算符进行重新定义&#xff0c;赋予不同的功能&#xff0c;以适应不同的数据类型 5.1 加号运算符 实现两个自定义数据类型的加运算 (1)通过成员函数实现“”重载 class Number { public:Number(int a, int b):m_A(a),m_B(b){}Number(){}Number operator(Number &a…...

接口排查不能靠猜:实战中如何用抓包工具精准定位问题(含 Charles 使用示例)

几乎每个写代码的开发者都经历过这样的时刻&#xff1a;接口突然返回空、请求超时、前端数据没更新……你试过重启服务、翻查日志、改代码打印&#xff0c;最后还是无解。 我想说&#xff0c;其实很多问题的答案都藏在“网络请求”里&#xff0c;只是你没有去看。 这篇文章&a…...

【占融数科-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…...

4.7 时间模块

时间模块&#xff1a; * 1. time&#xff1a;操作时间本身 2.datetime&#xff1a;主要用于设置某一时间 3.calendar&#xff1a;主要用于时间份量计算 import time # 1. actimr:把一个表示时间的元组转换为字符串。要是不给出参数则返回当前本地时间。 print(time.asctime())…...

SHIMADZU岛津 R300RC300 Operation Manual

SHIMADZU岛津 R300RC300 Operation Manual...

(C语言篇)处理字符串的四个基础函数

strlen、strcpy、strcat、strcmp使用以及注意事项 在C语言中&#xff0c;strlen、strcpy、strcat、strcmp是处理字符串的四个基础函数&#xff0c;都在<string.h>头文件中声明。下面为你详细介绍它们的功能、用法和注意事项。 1. strlen - 计算字符串长度 函数原型&am…...

mysql的安装方式

1.yum/apt安装 yum安装&#xff1a; 先搭建yum仓库&#xff0c;可以在清华源内找&#xff1a;mysql | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror vim /etc/yum.repos.d/mysql.repo[mysql-connectors-community] nameMySQL Connectors Communit…...

嵌入式(C语言篇)Day11

嵌入式Day11 一、动态内存分配核心函数 &#xff08;一&#xff09;函数列表 函数名功能头文件返回值malloc分配连续的size字节堆内存stdlib.h成功返回首地址&#xff08;void*&#xff09;&#xff0c;失败返回NULLcalloc分配num个元素size字节/元素的堆内存&#xff0c;自…...

Java集合框架解析:从基础到底层源码

Java集合框架解析&#xff1a;从基础到底层源码 一、集合体系 1.1 两大核心接口深度解析 Collection 单列集合 List 系列 ArrayList&#xff1a;动态数组实现&#xff0c;初始容量10&#xff0c;扩容策略为 原容量的1.5倍// JDK17 扩容源码片段 int newCapacity oldCapacity…...

C语言实现android/linux按键模拟

C语言实现 input事件模拟 #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <linux/input.h>int main() {int fd open("/dev/input/event0", O_RDWR);if (fd < 0) {perror("Failed to open device");ret…...

VisionPro:轴承错位标识

找出轴承缺陷并标记:效果 1.打开导入图片 2.添加CogToolblock:方便后续写代码 3.对零件进行模板匹配 4.对图片进行预处理(重点) 5.添加找圆工具和展开工具 根据下图将线链接 6.添加模板匹配工具并运行 7.训练模板 好的全找出来 8.代码编写 红色框为添加的代码(下面有完整代码) …...

专题五:floodfill算法(扫雷游戏精讲)

以leetcode529题 题目解析&#xff1a; M表示&#xff1a;未挖出的地雷 E表示&#xff1a;未挖出的空白方块 什么叫未挖出&#xff0c;就是你没玩的时候&#xff0c;棋盘是什么样的&#xff0c;就是你站在上帝视角看待棋盘 B&#xff1a;表示挖出来是空白的&#xff0c;如…...

MySQL企业版免费开启,强先体验

近期Oracle突然宣布&#xff0c;MySQL企业版面向开发者免费开放下载&#xff0c;这一消息瞬间引爆DBA圈。作为数据库领域的“顶配车型”&#xff0c;企业版长期因高昂授权费让中小团队望而却步&#xff0c;如今免费开放无异于“劳斯莱斯开进菜市场”。 本文将深度拆解企业版的…...

React Contxt详解

React Contxt详解 React 的 Context API 是用于跨组件层级传递数据的解决方案&#xff0c;尤其适合解决「prop drilling」&#xff08;多层组件手动传递 props&#xff09;的问题。以下是关于 Context 的详细解析&#xff1a; 文章目录 React Contxt详解一、Context 核心概念二…...

前端工程的相关管理 git、branch、build

环境配置 标准环境打包 测试版&#xff1a;npm run build-test 预生产&#xff1a;npm run build-preview 正式版&#xff1a;npm run build 建议本地建里一个 .env.development.local 方便和后端联调时修改配置相关信息。 和 src 同级有一下区分环境的文件&#xff1a; .env.d…...

鸿蒙 Location Kit(位置服务)

移动终端设备已经深入人们日常生活的方方面面&#xff0c;如查看所在城市的天气、新闻轶事、出行打车、旅行导航、运动记录。这些习以为常的活动&#xff0c;都离不开定位用户终端设备的位置。 Location Kit 使用多种定位技术提供服务&#xff0c;可以准确地确定设备在室外/室…...