一尘不染

附加片性能差..为什么呢?

go

我目前正在使用GoLang创建游戏。我正在测量FPS。我注意到使用for循环将7 fps损失附加到切片上,如下所示:

vertexInfo := Opengl.OpenGLVertexInfo{}

for i := 0; i < 4; i = i + 1 {
    vertexInfo.Translations = append(vertexInfo.Translations, float32(s.x), float32(s.y), 0)
    vertexInfo.Rotations = append(vertexInfo.Rotations, 0, 0, 1, s.rot)
    vertexInfo.Scales = append(vertexInfo.Scales, s.xS, s.yS, 0)
    vertexInfo.Colors = append(vertexInfo.Colors, s.r, s.g, s.b, s.a)

}

我正在为每个精灵,每个平局做这些。问题是,为什么只循环几次并将相同的内容附加到这些切片中,我会得到如此巨大的性能影响?有没有更有效的方法可以做到这一点?这不像我要添加大量数据。每个切片包含大约16个元素,如上所示(4
x 4)。

当我简单地将所有16个元素合而为一时,[]float32{1..16}fps大约提高了4。

更新: 我对每个附录进行了基准测试,似乎每个附录都要以1 fps的速度执行。考虑到此数据是非常静态的,这似乎很多。我只需要进行4次迭代…

更新: 添加了github repo
https://github.com/Triangle345/GT


阅读 203

收藏
2020-07-02

共1个答案

一尘不染

append()如果目标切片的容量小于追加后切片的长度,则内置函数需要创建一个新的后备阵列。这也需要将当前元素从目标复制到新分配的数组,因此开销很大。

由于使用切片文字来创建Opengl.OpenGLVertexInfo值,因此追加到的切片很可能是空切片。即使append()为将来考虑并分配了比添加指定元素所需的数组更大的数组,但在您的情况下,很可能需要多次重新分配才能完成4个迭代。

如果这样创建和初始化,则可以避免重新分配vertexInfo

vertexInfo := Opengl.OpenGLVertexInfo{
    Translations: []float32{float32(s.x), float32(s.y), 0, float32(s.x), float32(s.y), 0, float32(s.x), float32(s.y), 0, float32(s.x), float32(s.y), 0},
    Rotations:    []float64{0, 0, 1, s.rot, 0, 0, 1, s.rot, 0, 0, 1, s.rot, 0, 0, 1, s.rot},
    Scales:       []float64{s.xS, s.yS, 0, s.xS, s.yS, 0, s.xS, s.yS, 0, s.xS, s.yS, 0},
    Colors:       []float64{s.r, s.g, s.b, s.a, s.r, s.g, s.b, s.a, s.r, s.g, s.b, s.a, s.r, s.g, s.b, s.a},
}

还要注意,此struct文字将不必在切片后重新分配数组。但是,如果在代码的其他位置(我们看不到),您将更多元素附加到这些片中,则可能会导致重新分配。如果是这种情况,则应创建容量更大的片,以覆盖“未来”分配(例如make([]float64, 16, 32))。

2020-07-02