Go内存池概念介绍内存池是一种用于管理内存分配的技术,通过预先分配一定数量的内存块,减少频繁的系统调用开销。Go语言内部也使用了类似的技术来优化内存分配。Go内存池实现Go语言中的内存池主要通过runtime包实现,具体来说,通过mcentral和mspan结构体来管理内
概念介绍 内存池是一种用于管理内存分配的技术,通过预先分配一定数量的内存块,减少频繁的系统调用开销。Go 语言内部也使用了类似的技术来优化内存分配。
Go 内存池实现
Go 语言中的内存池主要通过 runtime
包实现,具体来说,通过 mcentral
和 mspan
结构体来管理内存。
示例代码分析 虽然 Go 语言的内存池实现是内部细节,但可以通过一些示例代码来了解内存分配的过程。
package main
import (
"fmt"
"runtime"
"unsafe"
)
func main() {
// 分配一个 10 字节的内存块
data := make([]byte, 10)
fmt.Printf("Allocated %d bytes\n", len(data))
// 打印内存分配信息
runtime.ReadMemStats(&memstats)
fmt.Printf("Total allocated: %d bytes\n", memstats.Alloc)
fmt.Printf("Total sys: %d bytes\n", memstats.Sys)
fmt.Printf("Num alloc: %d\n", memstats.NumAlloc)
fmt.Printf("Num sys: %d\n", memstats.NumSys)
}
var memstats runtime.MemStats
概念介绍 内存分配器负责管理内存的分配和回收。Go 语言使用了一种称为 分代收集 的策略,通过不同的代来管理不同生命周期的对象。
Go 内存分配器实现 Go 语言的内存分配器主要包括以下几个组件:
示例代码分析 通过打印内存统计信息,可以观察内存分配的过程。
package main
import (
"fmt"
"runtime"
)
func main() {
// 分配多个对象
for i := 0; i < 1000; i++ {
_ = make([]byte, 10)
}
// 打印内存统计信息
runtime.ReadMemStats(&memstats)
fmt.Printf("Total allocated: %d bytes\n", memstats.Alloc)
fmt.Printf("Total sys: %d bytes\n", memstats.Sys)
fmt.Printf("Num alloc: %d\n", memstats.NumAlloc)
fmt.Printf("Num sys: %d\n", memstats.NumSys)
}
var memstats runtime.MemStats
概念介绍 垃圾收集器负责自动回收不再使用的内存。Go 语言使用了一种称为 三色标记复制 的算法来实现垃圾收集。
Go 垃圾收集器实现 Go 语言的垃圾收集器主要包括以下几个阶段:
示例代码分析 通过设置垃圾收集间隔,可以观察垃圾收集的过程。
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
// 设置垃圾收集间隔
runtime.SetGCPercent(-1) // 禁用自动 GC
runtime.GC() // 手动触发一次 GC
// 分配多个对象
for i := 0; i < 1000; i++ {
_ = make([]byte, 10)
}
// 触发垃圾收集
runtime.GC()
// 打印内存统计信息
runtime.ReadMemStats(&memstats)
fmt.Printf("Total allocated: %d bytes\n", memstats.Alloc)
fmt.Printf("Total sys: %d bytes\n", memstats.Sys)
fmt.Printf("Num alloc: %d\n", memstats.NumAlloc)
fmt.Printf("Num sys: %d\n", memstats.NumSys)
fmt.Printf("Num GC: %d\n", memstats.NumGC)
// 等待一段时间,让 GC 运行
time.Sleep(2 * time.Second)
}
var memstats runtime.MemStats
内存池 内存池通过预先分配内存块来减少系统调用的开销。Go 语言内部通过 mcentral 和 mspan 来管理内存区域。
内存分配器 内存分配器负责管理内存的分配和回收。Go 语言使用了 分代收集 策略,通过不同的代来管理不同生命周期的对象。
垃圾收集器 垃圾收集器负责自动回收不再使用的内存。Go 语言使用了 三色标记复制 算法来实现垃圾收集。
减少内存分配
优化垃圾收集
内存池示例
通过 runtime
包可以观察内存分配和回收的过程。
package main
import (
"fmt"
"runtime"
)
func main() {
// 分配多个对象
for i := 0; i < 1000; i++ {
_ = make([]byte, 10)
}
// 打印内存统计信息
runtime.ReadMemStats(&memstats)
fmt.Printf("Total allocated: %d bytes\n", memstats.Alloc)
fmt.Printf("Total sys: %d bytes\n", memstats.Sys)
fmt.Printf("Num alloc: %d\n", memstats.NumAlloc)
fmt.Printf("Num sys: %d\n", memstats.NumSys)
}
var memstats runtime.MemStats
内存分配器示例
通过 runtime
包可以观察内存分配的过程。
package main
import (
"fmt"
"runtime"
)
func main() {
// 分配多个对象
for i := 0; i < 1000; i++ {
_ = make([]byte, 10)
}
// 打印内存统计信息
runtime.ReadMemStats(&memstats)
fmt.Printf("Total allocated: %d bytes\n", memstats.Alloc)
fmt.Printf("Total sys: %d bytes\n", memstats.Sys)
fmt.Printf("Num alloc: %d\n", memstats.NumAlloc)
fmt.Printf("Num sys: %d\n", memstats.NumSys)
}
var memstats runtime.MemStats
垃圾收集器示例
通过 runtime
包可以观察垃圾收集的过程。
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
// 设置垃圾收集间隔
runtime.SetGCPercent(-1) // 禁用自动 GC
runtime.GC() // 手动触发一次 GC
// 分配多个对象
for i := 0; i < 1000; i++ {
_ = make([]byte, 10)
}
// 触发垃圾收集
runtime.GC()
// 打印内存统计信息
runtime.ReadMemStats(&memstats)
fmt.Printf("Total allocated: %d bytes\n", memstats.Alloc)
fmt.Printf("Total sys: %d bytes\n", memstats.Sys)
fmt.Printf("Num alloc: %d\n", memstats.NumAlloc)
fmt.Printf("Num sys: %d\n", memstats.NumSys)
fmt.Printf("Num GC: %d\n", memstats.NumGC)
// 等待一段时间,让 GC 运行
time.Sleep(2 * time.Second)
}
var memstats runtime.MemStats
概念介绍 栈内存主要用于存储函数调用时的局部变量和函数参数。栈内存的特点是先进后出(LIFO),分配和释放速度快,但容量有限。
栈内存分配过程
示例代码分析 通过简单的函数调用来观察栈内存的分配和释放过程。
package main
import (
"fmt"
"runtime"
)
func main() {
// 调用函数
testStack()
}
func testStack() {
var a [1000]int // 分配一个较大的数组
fmt.Println("Array allocated on stack")
fmt.Printf("Size of array: %d bytes\n", unsafe.Sizeof(a))
fmt.Printf("Total allocated: %d bytes\n", runtime.MemStats().Alloc)
}
func (m *runtime.MemStats) Alloc() int {
return int(m.Alloc)
}
概念介绍 指针用于存储内存地址,通过指针可以间接访问内存中的数据。Go 语言中的指针主要有两种类型:栈指针和堆指针。
栈指针 栈指针是指指向栈内存的指针。栈指针通常用于存储局部变量的地址。
堆指针 堆指针是指指向堆内存的指针。堆指针通常用于存储动态分配的数据结构,如数组、切片、结构体等。
示例代码分析 通过示例代码来观察栈指针和堆指针的使用。
package main
import (
"fmt"
"unsafe"
"runtime"
)
func main() {
// 栈指针示例
var a int = 10
fmt.Printf("Stack pointer address: %p\n", &a)
fmt.Printf("Size of int: %d bytes\n", unsafe.Sizeof(a))
// 堆指针示例
b := new(int)
*b = 20
fmt.Printf("Heap pointer address: %p\n", b)
fmt.Printf("Size of int: %d bytes\n", unsafe.Sizeof(*b))
// 打印内存统计信息
runtime.ReadMemStats(&memstats)
fmt.Printf("Total allocated: %d bytes\n", memstats.Alloc)
fmt.Printf("Total sys: %d bytes\n", memstats.Sys)
fmt.Printf("Num alloc: %d\n", memstats.NumAlloc)
fmt.Printf("Num sys: %d\n", memstats.NumSys)
}
var memstats runtime.MemStats
栈内存分配 栈内存主要用于存储函数调用时的局部变量和函数参数。
package main
import (
"fmt"
"runtime"
)
func main() {
// 调用函数
testStack()
}
func testStack() {
var a [1000]int // 分配一个较大的数组
fmt.Println("Array allocated on stack")
fmt.Printf("Size of array: %d bytes\n", unsafe.Sizeof(a))
fmt.Printf("Total allocated: %d bytes\n", runtime.MemStats().Alloc)
}
func (m *runtime.MemStats) Alloc() int {
return int(m.Alloc)
}
代码分析
栈指针 栈指针是指向栈内存的指针,通常用于存储局部变量的地址。
package main
import (
"fmt"
"unsafe"
)
func main() {
// 栈指针示例
var a int = 10
fmt.Printf("Stack pointer address: %p\n", &a)
fmt.Printf("Size of int: %d bytes\n", unsafe.Sizeof(a))
}
代码分析
堆指针是指向堆内存的指针,通常用于存储动态分配的数据结构。
package main
import (
"fmt"
"unsafe"
"runtime"
)
func main() {
// 堆指针示例
b := new(int)
*b = 20
fmt.Printf("Heap pointer address: %p\n", b)
fmt.Printf("Size of int: %d bytes\n", unsafe.Sizeof(*b))
// 打印内存统计信息
runtime.ReadMemStats(&memstats)
fmt.Printf("Total allocated: %d bytes\n", memstats.Alloc)
fmt.Printf("Total sys: %d bytes\n", memstats.Sys)
fmt.Printf("Num alloc: %d\n", memstats.NumAlloc)
fmt.Printf("Num sys: %d\n", memstats.NumSys)
}
var memstats runtime.MemStats
代码分析
栈内存和堆内存结合 结合栈内存和堆内存的使用,展示两者的区别。
package main
import (
"fmt"
"unsafe"
"runtime"
)
func main() {
// 栈指针示例
var a int = 10
fmt.Printf("Stack pointer address: %p\n", &a)
fmt.Printf("Size of int: %d bytes\n", unsafe.Sizeof(a))
// 堆指针示例
b := new(int)
*b = 20
fmt.Printf("Heap pointer address: %p\n", b)
fmt.Printf("Size of int: %d bytes\n", unsafe.Sizeof(*b))
// 打印内存统计信息
runtime.ReadMemStats(&memstats)
fmt.Printf("Total allocated: %d bytes\n", memstats.Alloc)
fmt.Printf("Total sys: %d bytes\n", memstats.Sys)
fmt.Printf("Num alloc: %d\n", memstats.NumAlloc)
fmt.Printf("Num sys: %d\n", memstats.NumSys)
}
var memstats runtime.MemStats
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!