【问题标题】:Stopwatch giving different results depending on where code resides秒表根据代码所在的位置给出不同的结果
【发布时间】:2015-05-04 23:04:07
【问题描述】:

我在我的 C# 项目中得到了一些令人困惑的 Stopwatch 结果。考虑以下代码:

static void Main(string[] args)
{
    byte[] myEventArray = GetEventByteArrayFromDatabase();
    byte[] myEventItemsArray = GetEventItemByteArrayFromDatabase();
    uint numEvents = 1000;
    uint numEventItems = 1000;

    Stopwatch sw1 = Stopwatch.StartNew();
    TestFunction(ref myEventArray, numEvents, ref myEventItemsArray, numEventItems);
    sw1.Stop();

    float timeTakenInSeconds = (float)sw2.ElapsedTicks / Stopwatch.Frequency;
    Console.WriteLine("Total time: " + timeTakenInSeconds + " seconds. ");
}

static void TestFunction(ref byte[] EventArray, uint numEvents, ref byte[] EventItemArray, uint numEventItems)
{
        Calculator calc = new Calculator();
        calc.Test(EventArray, numEvents, EventItemArray, numEventItems);
}

我运行它,得到大约 0.2 秒的时间。 现在考虑一下:

static void Main(string[] args)
{
    byte[] myEventArray = GetEventByteArrayFromDatabase();
    byte[] myEventItemsArray = GetEventItemByteArrayFromDatabase();
    uint numEvents = 1000;
    uint numEventItems = 1000;

    Stopwatch sw1 = Stopwatch.StartNew();
    Calculator calc = new Calculator();
    calc.Test(myEventArray , numEvents, myEventItemsArray , numEventItems);
    sw1.Stop();

    float timeTakenInSeconds = (float)sw1.ElapsedTicks / Stopwatch.Frequency;
    Console.WriteLine("Total time: " + timeTakenInSeconds + " seconds. ");
}

我运行它,得到了与预期相似的结果。 最后,看看这个:

static void Main(string[] args)
{
    byte[] myEventArray = GetEventByteArrayFromDatabase();
    byte[] myEventItemsArray = GetEventItemByteArrayFromDatabase();
    uint numEvents = 1000;
    uint numEventItems = 1000;

    TestFunction(ref myEventArray, numEvents, ref myEventItemsArray, numEventItems);
}

static void TestFunction(ref byte[] EventArray, uint numEvents, ref byte[] EventItemArray, uint numEventItems)
{
    Stopwatch sw1 = Stopwatch.StartNew();
    Calculator calc = new Calculator();
    calc.Test(EventArray, numEvents, EventItemArray, numEventItems);
    sw1.Stop();

    float timeTakenInSeconds = (float)sw1.ElapsedTicks / Stopwatch.Frequency;
    Console.WriteLine("Total time: " + timeTakenInSeconds + " seconds. ");
}

当我运行 that 时,由于某种原因,计时结果始终快十倍。 任何想法为什么会这样?

更多信息: Calculator 类在 C++/CLI 中定义。我将它用作最终与字节数组一起使用的本机 C++ 代码的包装器。 我也在使用“不安全”编译器标志进行编译。不确定这是否会产生任何影响。 所有代码都在发布模式下编译。

【问题讨论】:

  • 您是在调试还是发布中运行此代码?此外,看起来你正在计时不同的方法。 TestFunction 采用 ref 参数,而 Test 没有。
  • 如果同时激活两个秒表会怎样? (在 TestFunction() 内部和 Main() 内部)
  • 检查 sw1sw2(不幸的是,您将这些名称混为一谈)
  • 抱歉,sw1/sw2 是错字。修好了。
  • 能否尝试在你的计时代码前调用Calculator.Test,让计时时方法已经被JIT编译?

标签: c# c++ c#-4.0


【解决方案1】:

我已经找到了原因。发生这种情况是因为在第一种情况下,我的 Calculator 对象的创建包含在计时结果中,而在第三种情况下则没有。

如果我理解正确的话, 堆栈变量实际上并没有在您键入“new()”的那一行创建,编译器将内存分配移动到方法“prolog”。

查看此页面:https://msdn.microsoft.com/en-us/library/tawsa7cb.aspx

“如果需要,序言将参数寄存器保存在它们的起始地址中,将非易失性寄存器压入堆栈,为本地和临时分配堆栈的固定部分,并可选择建立一个帧指针。”

所以我的“case 1”包含了“new”(因为它发生在 TestFunction 的序言中)而“case 3”排除了它,因为“new”已经发生了。

【讨论】:

  • 有趣。我认为实际分配将是对性能的最大影响。
  • 实际分配是最大的打击 - 它只是没有发生在我认为的地方。
猜你喜欢
  • 2019-05-22
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
  • 2021-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多