Dev*_*dse 5 c# compiler-construction performance
我一直在研究C#迷宫发生器一段时间,它可以生成类似128000x128000像素的迷宫.所有内存使用已经优化,因此我目前正在考虑加速这一代.
我发现一个问题(更多的是关注点)是以下(只是一些示例代码来说明问题):
当pixelChanged为null时,此代码在我的机器上运行大约1.4秒:
public void Go()
{
for (int i = 0; i < bitjes.Length; i++)
{
BitArray curArray = bitjes[i];
for (int y = 0; y < curArray.Length; y++)
{
curArray[y] = !curArray[y];
GoDrawPixel(i, y, false);
}
}
}
public void GoDrawPixel(int i, int y, Boolean enabled)
{
if (pixelChanged != null)
{
pixelChanged.Invoke(new PixelChangedEventArgs(i, y, enabled));
}
}
Run Code Online (Sandbox Code Playgroud)
以下代码实际运行速度快0.4秒
public void Go()
{
for (int i = 0; i < bitjes.Length; i++)
{
BitArray curArray = bitjes[i];
for (int y = 0; y < curArray.Length; y++)
{
curArray[y] = !curArray[y];
if (pixelChanged != null)
{
pixelChanged.Invoke(new PixelChangedEventArgs(i, y, false));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
似乎只是调用"空"方法占用了该算法使用的cpu的大约20%.这不奇怪吗?我试图在调试和发布模式下编译解决方案,但没有发现任何明显的差异.
这意味着我在此循环中进行的每个方法调用都会使代码减慢大约0.4秒.由于迷宫生成器代码当前包含许多单独的方法调用,这些调用超出了不同的操作,因此开始获得实质性的安装.
我还检查了Stack Overflow上的谷歌和其他帖子,但还没有真正找到解决方案.
是否可以自动优化这样的代码?(也许像项目Roslyn这样的东西?)或者我应该把所有东西放在一个大方法中?
编辑:我也对这两种案例中JIT/CLR代码差异的分析感兴趣.(所以问题实际上来自哪里)
Edit2: 所有代码都是在发布模式下编译的
这是一个问题,JIT 对方法进行了内联优化(其中整个方法代码实际上被注入到调用父代码中),但这只发生在编译为 32 字节或更少的方法中。我不知道为什么存在 32 字节限制,并且还希望在 C# 中看到一个“内联”关键字,就像在 C/C++ 中完全针对这些问题。
我要尝试的第一件事就是让它静态而不是实例:
public static void GoDrawPixel(PixelChangedEventHandler pixelChanged,
int x, int y, bool enabled)
{
if (pixelChanged != null)
{
pixelChanged.Invoke(new PixelChangedEventArgs(x, y, enabled));
}
}
Run Code Online (Sandbox Code Playgroud)
这改变了一些事情:
callvirt成为call-避免了一些小的开销ldarg0/ ldfld对(this.pixelChanged)成为单ldarg0接下来我要看的是PixelChangedEventArgs; 如果它避免大量分配,那么作为结构传递它可能会更便宜; 或者只是:
pixelChanged(x, y, enabled);
Run Code Online (Sandbox Code Playgroud)
(原始参数而不是包装器对象 - 需要更改签名)
| 归档时间: |
|
| 查看次数: |
5400 次 |
| 最近记录: |