为什么我的C#嵌套for循环很慢?
我正在创建一个游戏作为一个学校项目,并认为这将是一个好主意,使用colormapping创建水平,但我使用的方法是很由于某种原因缓慢。为什么我的C#嵌套for循环很慢?
public List<Entity> LoadLevel(Level level)
{
List<Entity> ents = new List<Entity>();
Color[] clrs = new Color[level.getColorMap.Height*level.getColorMap.Width];
level.getColorMap.GetData(clrs);
for (int x = 0; x < level.getColorMap.Width; x++)
{
for (int y = 0; y < level.getColorMap.Height; y++)
{
if (clrs[x + y * level.getColorMap.Width] == new Color(0, 0, 0))
{
ents.Add(new Terrain(new Vector2(x, y)));
ents.Last().Animation.setImageIndex(0);
ents.Last().Animation.Play();
}
if (clrs[x + y * level.getColorMap.Width] == new Color(6, 6, 6))
{
ents.Add(new Terrain(new Vector2(x, y)));
ents.Last().Animation.setImageIndex(6);
ents.Last().Animation.setSpeed(69);
ents.Last().Animation.Play();
}
if (clrs[x + y * level.getColorMap.Width] == new Color(9, 9, 9))
{
ents.Add(new Terrain(new Vector2(x, y)));
ents.Last().Animation.setImageIndex(9);
ents.Last().Animation.setSpeed(69);
ents.Last().Animation.Play();
}
}
}
return ents;
}
我在LoadContent()中调用这个函数,执行大约需要半分钟,为什么它很慢?
我对编码风格有一些注释。很可能这不是你的问题的原因,但更快知道更早。一般来说,你应该避免做重复和不必要的工作。我甚至不会称之为优化,我会称之为规则。它应该是你总是编码的方式。
如果
level.getColorMap
需要一段时间?即使你不需要这样做,你可以一遍又一遍地重复它。你通常不应该依赖这个事实,即财产很便宜。调用一次并记住它的结果。ents.Last()
相当快,但不是免费的。如果你不需要它,不要打电话给它。建立新的地形并记住它的指针。在每个循环中新的
Color(0, 0, 0)
是坏的。不要把循环提升视为理所当然。即使您实际需要三个颜色对象,您也很可能会构建1200万个颜色对象。你的代码也有很多的重复。一般来说,在复制和粘贴代码之前请三思。 DRY
循环顺序不好。您从一行到另一行跳转破坏缓存局部性。你应该处理整行,然后转到下一个。
当您只需添加时避免乘法运算。的改进
实施例:
public void AddTerrain(List<Entity> ents, int selector, int x, int y)
{
Terrain newT = new Terrain(new Vector2(x, y));
ents.Add(newT);
var animation = newT.Animation;
animation.setImageIndex(selector);
if (selector > 0)
{
animation.setSpeed(69);
}
animation.Play();
}
public List<Entity> LoadLevel(Level level)
{
List<Entity> ents = new List<Entity>();
var colorMap = level.getColorMap;
int colorMapWidth = colorMap.Width;
int colorMapHeight = colorMap.Height;
Color[] clrs = new Color[colorMapWidth * colorMapHeight];
Color[] colors = new Color[] { new Color(0, 0, 0), new Color(6, 6, 6), new Color(9, 9, 9) };
colorMap.GetData(clrs);
int ci = 0;
for (int y = 0; y < colorMapHeight; y++)
{
for (int x = 0; x < colorMapWidth; x++)
{
Color c = clrs[ci++];
for (int i = 0; i < colors.Length; ++i)
{
if (c == colors[i])
{
AddTerrain(ents, c.R, x, y);
break;
}
}
}
}
return ents;
}
非常好的建议。反转x和y循环可能是最大的变化。缓存是一件非常重要的事情。 – vyrp
(发布代表OP的)。
这个问题实际上是在terrainobject的构造函数中,创建它的collider的函数显得非常不好优化,感谢您的帮助!
这更适合[code review](http://codereview.stackexchange.com/) – Rob
'level.getColorMap.Height'和'level.getColorMap.Width'有多大? – Unlocked
他们都是2048大。 –