Performance 为什么这种D代码比类似的C#实现慢?

Performance 为什么这种D代码比类似的C#实现慢?,performance,d,Performance,D,我在玩D,移植了一个用C#编写的示例项目,以测试它的性能。我不会撒谎说看到D比C慢很多我并不感到惊讶,因为这是我第一次尝试用D写东西 简而言之,C#在32秒内执行代码,而D需要54秒。对于一个代码片段来说,代码有点大,但是如果有人能提供一点时间来解释为什么会发生这种情况/我的D代码出了什么问题,那就太好了 下面是我的一小段代码: void ProcessReel(int reelIndex, string pattern, Game game) { counter++; if(r

我在玩D,移植了一个用C#编写的示例项目,以测试它的性能。我不会撒谎说看到D比C慢很多我并不感到惊讶,因为这是我第一次尝试用D写东西

简而言之,C#在32秒内执行代码,而D需要54秒。对于一个代码片段来说,代码有点大,但是如果有人能提供一点时间来解释为什么会发生这种情况/我的D代码出了什么问题,那就太好了

下面是我的一小段代码:

void ProcessReel(int reelIndex, string pattern, Game game)
{
    counter++;
    if(reelIndex == game.Reels.length) 
    {
        Symbol winningSymbol;
        auto patternLength = 0;


        auto p3_1 = pattern[0..3];
        auto p3_2 = pattern[2..5];
        auto p4_1 = pattern[0..4];
        auto p4_2 = pattern[1..5];

        auto pos = GetFromDict(p3_1, p3_2, game);
        if(pos != null)
        {
            winningSymbol = pos._Symbol;
            patternLength = pos.PatternLength;
        }

        pos = GetFromDict(p4_1, p4_2, game);
        if(pos != null)
        {
            winningSymbol = pos._Symbol;
            patternLength = pos.PatternLength;
        }

        if(pattern in patternTable)
        {
            auto combination = patternTable[pattern];
            winningSymbol = combination._Symbol;
            patternLength = combination.PatternLength;
        }

        if(winningSymbol !is null)
        {
            winningSymbol.Combinations++;
        }
        return;
    }

    auto reel = game.Reels[reelIndex];
    for(int i = 0; i < reel.ReelStrip.length; i++)
    {
        auto p = pattern;
        auto sym = reel.ReelStrip[i];
        p ~= std.conv.to!string(sym);
        ProcessReel(reelIndex + 1, p, game);
    }
}
谢谢

更新

这是C代码。它应该是并行运行的,这就是为什么它里面有一个锁,但是为了公平竞争,我将它设置为串行,然而,即使有了这个锁,C#胜过D

publicstaticvoidprocessreel(int-reeldex、Dictionary-dict、字符串模式、AnalyzedResult结果)
{
如果(reelIndex==result.Game.ReelCollection[0].Reels.Count)//这是最后一卷。分析这些废话的时间到了:((
{
符号winningSymbol=null;
var模式长度=0;
var p3_1=模式子串(0,3);
var p3_2=模式子串(2,3);
var p4_1=模式子串(0,4);
var p4_2=模式子串(1,4);
if(result.PatternTable.ContainsKey(p3_1)| | result.PatternTable.ContainsKey(p3_2))
{
var winCombination=Helper.GetFromDict(p3_1,p3_2,结果);
var symbol=winCombination.symbol;
winningSymbol=符号;
patternLength=winCombination.patternLength;
}
if(result.PatternTable.ContainsKey(p4_1)| result.PatternTable.ContainsKey(p4_2))
{
var winCombination=Helper.GetFromDict(p4_1,p4_2,结果);
var symbol=winCombination.symbol;
winningSymbol=符号;
patternLength=winCombination.patternLength;
}
if(result.PatternTable.ContainsKey(pattern))
{
var winCombination=result.PatternTable[pattern];
var symbol=winCombination.symbol;
winningSymbol=符号;
patternLength=winCombination.patternLength;
}
如果(winningSymbol!=null)
{
锁(dict)
{
var d=dict[模式长度];
if(d.ContainsKey(winningSymbol.Code))
d[winningSymbol.Code]。组合+=1;
其他的
d、 添加(winningSymbol.Code,新winningSymbol,patternLength,1));
}
}
返回;
}
var reel=result.Game.ReelCollection[0]。Reels[reelIndex];
//如果(reelIndex==0)
//{
//平行。对于(0,reel.ReelStrip.Length,r1=>
//    {
//var p=模式;
//var sym=卷轴卷轴带[r1];
//p+=sym;
//ProcessReel(reelIndex+1,dict,p,result);
//    });
//}
//否则
//{
对于(int r1=0;r1
更新2


我刚刚下载了GDCC4.9。它很有帮助,计算时间从54秒降到了38秒,但仍然低于.NET/C#…

有一些因素使得D版速度变慢

1.)

如果在此处进行2次查找而不是1次,则应使用以下方法:

auto combination = pattern in patternTable;
if(combination) {
    ...
GetFromDict函数也是如此

(二) 数组连接速度慢,最好使用std.array.Appender

(三) 不需要使用std.container.Array,您可以使用带appender的standart D数组

4)去!字符串(sym)速度慢,可以在0范围内提高sym的速度。。10与:

cast(char)('0' + sym)
(五) DMD速度较慢。您应该尝试使用ldc和gdc,并带有适当的标志,例如:

gdc -O3 -finline -fno-bounds-check  -frelease
通过一些改变,我可以使它从50秒到15秒快很多倍

这是我的密码:

更新

我有一些错误,这里是另一个版本,速度稍慢,但应该给出正确的结果:


我没有看到任何C。(如果它在你的链接中,请包含在这里。)也许是一个问题?在每个问题上使用探查器,找出哪些功能/操作执行的显著不同。它很可能是依赖于数据的。p3_2和p4_2的边在D中应该与在C中不同吗?GetFromDict在D中是什么样子的?“这很有帮助,计算时间从54秒下降到38秒,但仍然低于.NET/C…”,但“C在32秒内执行代码”。其实差别不大。现代的JIT虚拟机通常没有得到足够的信任-是否预期D会更快?难以置信,D真的很有效。我没想到性能会比CLR高出一倍。谢谢Kozzi:)我有一些错误是没有按预期工作:这里是更好的版本是小斯洛,但准确:是的,我也注意到了,但无法纠正:)。在我的电脑上,它需要大约2秒才能完成,比CLR快得多。有一件事我不明白,“0”在这段代码中扮演什么角色?模式~“0”:模式~sym?再次感谢:)因为我从int[]更改为string[],所以当代码获取revel.revelStrip[I]时,如果int[]不是值,它将返回0,但如果string[]返回“”(空字符串),因此当发生“”时,将使用“0”
auto combination = pattern in patternTable;
if(combination) {
    ...
cast(char)('0' + sym)
gdc -O3 -finline -fno-bounds-check  -frelease