猿问

附加到切片性能不佳.. 为什么?

我目前正在使用 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。


更新:我对每个 append 进行了基准测试,似乎每个 append 都需要 1 fps 来执行..考虑到这些数据非常静态,这似乎很多..我只需要 4 次迭代......


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


慕仙森
浏览 159回答 2
2回答

白猪掌柜的

append()如果目标切片的容量小于追加后切片的长度,则内置函数需要创建一个新的后备数组。这也需要将当前元素从目的地复制到新分配的数组中,因此开销很大。您附加到的切片很可能是空切片,因为您使用切片文字来创建您的Opengl.OpenGLVertexInfo值。即使append()考虑未来并分配比附加指定元素所需的更大的数组,在您的情况下,可能需要多次重新分配才能完成 4 次迭代。如果您vertexInfo像这样创建和初始化,您可以避免重新分配:vertexInfo := Opengl.OpenGLVertexInfo{&nbsp; &nbsp; 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},&nbsp; &nbsp; Rotations:&nbsp; &nbsp; []float64{0, 0, 1, s.rot, 0, 0, 1, s.rot, 0, 0, 1, s.rot, 0, 0, 1, s.rot},&nbsp; &nbsp; Scales:&nbsp; &nbsp; &nbsp; &nbsp;[]float64{s.xS, s.yS, 0, s.xS, s.yS, 0, s.xS, s.yS, 0, s.xS, s.yS, 0},&nbsp; &nbsp; Colors:&nbsp; &nbsp; &nbsp; &nbsp;[]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},}另请注意,此结构文字将负责不必重新分配切片后面的数组。但是如果在代码的其他地方(我们没有看到),您将更多元素附加到这些切片中,它们可能会导致重新分配。如果是这种情况,您应该创建覆盖“未来”分配(例如make([]float64, 16, 32))的更大容量的切片。

扬帆大鱼

空切片是空的。要追加,它必须分配内存。然后你做更多的追加,这必须分配更多的内存。要加快速度,请使用固定大小的数组或用于make创建具有正确长度的切片,或在声明切片时使用项目初始化切片。
随时随地看视频慕课网APP

相关分类

Go
我要回答