golang高性能零内存分配通用四叉树插件库quadtree的使用
golang高性能零内存分配通用四叉树插件库quadtree的使用
quadtree是一个用于Golang的四叉树实现库。
特性
- 泛型支持
- 高度优化
- 零内存分配
- 100%测试覆盖率
示例代码
下面是一个完整的使用示例:
import (
"log"
"github.com/s0rg/quadtree"
)
func main() {
// 创建新的四叉树,参数为宽度、高度和最大深度
tree := quadtree.New[int](100.0, 100.0, 4)
// 添加一些点
tree.Add(10.0, 10.0, 5.0, 5.0, 1)
tree.Add(15.0, 20.0, 10.0, 10.0, 2)
tree.Add(40.0, 10.0, 4.0, 4.0, 3)
tree.Add(90.0, 90.0, 5.0, 8.0, 4)
// 查询指定区域内的值
val, ok := tree.Get(9.0, 9.0, 11.0, 11.0)
if !ok {
log.Fatal("not found")
}
log.Println(val) // 应该输出1
const (
distance = 20.0
count = 2
)
// 查找最近的K个邻居
tree.KNearest(80.0, 80.0, distance, count, func(x, y, w, h float64, val int) {
log.Printf("(%f, %f, %f, %f) = %d", x, y, w, h, val)
})
// 输出: (90.000000, 90.000000, 5.000000, 8.000000) = 4
}
性能基准测试
goos: linux
goarch: amd64
pkg: github.com/s0rg/quadtree
cpu: AMD Ryzen 5 5500U with Radeon Graphics
BenchmarkNode/Insert-12 14974236 71.07 ns/op 249 B/op 0 allocs/op
BenchmarkNode/Del-12 6415672 188.3 ns/op 0 B/op 0 allocs/op
BenchmarkNode/Search-12 21702474 51.83 ns/op 0 B/op 0 allocs/op
BenchmarkTree/Add-12 18840514 67.83 ns/op 241 B/op 0 allocs/op
BenchmarkTree/Get-12 21204722 55.46 ns/op 0 B/op 0 allocs/op
BenchmarkTree/Move-12 8061322 147.5 ns/op 0 B/op 0 allocs/op
BenchmarkTree/ForEach-12 18723290 58.60 ns/op 0 B/op 0 allocs/op
BenchmarkTree/KNearest-12 3595956 324.7 ns/op 0 B/op 0 allocs/op
BenchmarkTree/Del-12 6234123 193.1 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/s0rg/quadtree 12.666s
从基准测试结果可以看出,该库在各种操作上都表现出色,且确实实现了零内存分配的目标。
更多关于golang高性能零内存分配通用四叉树插件库quadtree的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang高性能零内存分配通用四叉树插件库quadtree的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Go高性能四叉树库quadtree使用指南
quadtree是一个高性能的Go语言四叉树实现库,特别注重零内存分配和高效查询。下面我将详细介绍它的使用方法和示例代码。
安装
go get github.com/paulmach/orb/quadtree
基本概念
四叉树是一种树数据结构,每个节点最多有四个子节点,用于二维空间划分。常用于:
- 空间索引
- 碰撞检测
- 图像处理
- 地理信息系统(GIS)
基本使用
1. 创建四叉树
package main
import (
"fmt"
"github.com/paulmach/orb"
"github.com/paulmach/orb/quadtree"
)
func main() {
// 定义四叉树边界 (minX, minY, maxX, maxY)
bounds := orb.Bound{Min: orb.Point{0, 0}, Max: orb.Point{100, 100}}
// 创建四叉树
qt := quadtree.New(bounds)
// 可选:设置最大深度和节点容量
// qt := quadtree.NewWithOptions(bounds, quadtree.Options{
// MaxDepth: 10,
// NodeCapacity: 4,
// })
}
2. 插入数据
// 插入点数据
points := []orb.Point{
{10, 10}, {20, 20}, {30, 30}, {40, 40},
{50, 50}, {60, 60}, {70, 70}, {80, 80},
}
for _, p := range points {
qt.Insert(p)
}
// 插入带数据的点
type DataPoint struct {
ID int
Data string
}
qtData := quadtree.New(bounds)
for i, p := range points {
qtData.Insert(quadtree.Point{
Point: p,
Data: DataPoint{ID: i, Data: fmt.Sprintf("point-%d", i)},
})
}
3. 查询操作
// 查找矩形区域内的所有点
searchBound := orb.Bound{Min: orb.Point{15, 15}, Max: orb.Point{45, 45}}
results := qt.InBound(searchBound)
fmt.Println("Points in bound:", results)
// 查找距离某点最近的点
nearest := qt.FindNearest(orb.Point{25, 25})
fmt.Println("Nearest point:", nearest)
// 范围查询带数据的点
dataResults := qtData.InBound(searchBound)
for _, r := range dataResults {
if dp, ok := r.Data.(DataPoint); ok {
fmt.Printf("Point %v with data: %+v\n", r.Point, dp)
}
}
高性能技巧
1. 避免内存分配
// 重用切片减少分配
var reuse []orb.Point
results = qt.InBound(searchBound, reuse[:0])
// 使用预分配的缓冲区
buffer := make([]orb.Point, 0, 10)
results = qt.InBound(searchBound, buffer)
2. 批量插入
// 批量插入比单次插入更高效
allPoints := make([]orb.Point, 0, len(points))
for _, p := range points {
allPoints = append(allPoints, p)
}
qt.InsertAll(allPoints)
3. 自定义数据类型
// 轻量级自定义类型减少内存占用
type LightPoint struct {
X, Y float64
ID uint16
}
qtCustom := quadtree.New(bounds)
for i, p := range points {
qtCustom.Insert(quadtree.Point{
Point: p,
Data: LightPoint{X: p[0], Y: p[1], ID: uint16(i)},
})
}
实际应用示例:碰撞检测
type GameObject struct {
ID int
Bounds orb.Bound
}
// 创建游戏对象四叉树
gameBounds := orb.Bound{Min: orb.Point{0, 0}, Max: orb.Point{1000, 1000}}
gameQT := quadtree.New(gameBounds)
objects := []GameObject{
{1, orb.Bound{Min: orb.Point{100, 100}, Max: orb.Point{150, 150}}},
{2, orb.Bound{Min: orb.Point{200, 200}, Max: orb.Point{250, 250}}},
// 更多对象...
}
// 插入对象中心点
for _, obj := range objects {
center := obj.Bounds.Center()
gameQT.Insert(quadtree.Point{
Point: center,
Data: obj,
})
}
// 检测碰撞
func CheckCollisions(qt *quadtree.Quadtree, obj GameObject) []GameObject {
center := obj.Bounds.Center()
radius := obj.Bounds.Max[0] - obj.Bounds.Min[0] // 假设是正方形
searchBound := orb.Bound{
Min: orb.Point{center[0] - radius, center[1] - radius},
Max: orb.Point{center[0] + radius, center[1] + radius},
}
var collisions []GameObject
for _, item := range qt.InBound(searchBound) {
if other, ok := item.Data.(GameObject); ok && other.ID != obj.ID {
if obj.Bounds.Intersects(other.Bounds) {
collisions = append(collisions, other)
}
}
}
return collisions
}
性能注意事项
- 选择合适的边界大小 - 太大会降低查询效率,太小会导致频繁分裂
- 调整MaxDepth和NodeCapacity参数以适应你的数据分布
- 对于静态数据,构建后不再修改的四叉树性能最佳
- 频繁更新的场景考虑批量更新而非单次操作
quadtree库通过精心设计实现了高性能和低内存开销,非常适合需要高效空间查询的Go应用程序。