为什么我的C#嵌套for循环速度慢?

为什么我的C#嵌套for循环速度慢?,c#,performance,xna,nested-loops,monogame,C#,Performance,Xna,Nested Loops,Monogame,我正在创建一个游戏作为一个学校项目,并认为这将是一个好主意,使用颜色映射创建水平,但我使用的方法是非常缓慢的,因为某些原因 public List<Entity> LoadLevel(Level level) { List<Entity> ents = new List<Entity>(); Color[] clrs = new Color[level.getColorMap.Height*level.g

我正在创建一个游戏作为一个学校项目,并认为这将是一个好主意,使用颜色映射创建水平,但我使用的方法是非常缓慢的,因为某些原因

        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;


    }
公共列表加载级别(级别)
{
List ents=新列表();
Color[]clrs=new Color[level.getColorMap.Height*level.getColorMap.Width];
level.getColorMap.GetData(clrs);
对于(int x=0;x

我在LoadContent()中调用这个函数,执行起来大约需要半分钟,为什么这么慢?

我对编码风格有一些说明。很可能这不是你问题的原因,但最好早点知道。一般来说,你应该避免重复和不必要的工作。我甚至不会称之为优化,我会称之为规则。这应该是您编写代码的方式

  • 如果
    level.getColorMap
    需要一段时间怎么办?你一遍又一遍地叫它,即使你不需要这样做。你一般不应该相信这样一个事实,那就是房产很便宜。打一次电话,记住结果

  • ents.Last()
    相当快,但不是免费的。如果你不需要它,就不要叫它。建立新地形并记住指向它的指针

  • 每个循环中新的
    颜色(0,0,0)
    都不好。不要把吊环当作理所当然的事。最有可能的是,即使您实际需要三个颜色对象,您也会构造12000000个颜色对象

  • 你的代码也有很多两面性。通常,在复制和粘贴代码之前要三思而后行。干的

  • 循环顺序不好。从一行跳到另一行会破坏缓存的位置。您应该处理整行,然后转到下一行

  • 当你只需要加法时,避免乘法

改进示例:

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;
}
public void AddTerrain(列表元素、整数选择器、整数x、整数y)
{
地形牛顿=新地形(新矢量2(x,y));
添加(牛顿);
var animation=newT.animation;
setImageIndex(选择器);
如果(选择器>0)
{
动画设定速度(69);
}
动画。播放();
}
公共列表加载级别(级别)
{
List ents=新列表();
var colorMap=level.getColorMap;
int colorMapWidth=colorMap.Width;
int colorMapHeight=colorMap.Height;
颜色[]clrs=新颜色[colorMapWidth*colorMapHeight];
颜色[]颜色=新颜色[]{新颜色(0,0,0),新颜色(6,6,6),新颜色(9,9,9)};
colorMap.GetData(clrs);
int-ci=0;
对于(int y=0;y
(代表OP发布)


问题实际上出在terrainobject的构造函数中,用于创建其碰撞器的函数似乎优化得非常糟糕,感谢您的帮助

这更适合于
level.getColorMap.Height
level.getColorMap.Width
?它们都是2048大。我们不知道所有这些动画方法都做什么。注释所有以“ents”开头的行。如果有帮助,问题不在这段代码中。@AntonínLejsek可能在这段代码中<例如,code>getColorMap
可能正在从磁盘加载彩色地图。您是对的,“成本”是这段代码的外部因素,但它仍然是可以改进的。在任何情况下,持续访问
level.getColorMap
level.getColorMap.Width
而不是将其存储在局部变量中都有点像是一种味道。另外,缺少
else if
而不是冗余计算。非常好的建议。反转x和y循环可能是最大的变化。缓存是一件非常重要的事情。