Visual Studio C#2010 Express Debug运行速度比发布速度快

时间:2012-09-06 22:04:09

标签: c# debugging visual-studio-debugging visual-c#-express-2010

我有一个只有2个线程的Windows窗体应用程序。这些线程彼此之间有ZERO交互,Ala运行第一个线程而不会弄乱第二个线程。它们之间没有同步,因为不需要发生这种情况。第一个线程处理应用程序的UI,更改颜色和标签,并运行一个计时器来捕获一些用户输入,此计时器每200毫秒触发一次。第二个线程涉及更多,并且不断地运行其编码,直到用户退出应用程序关闭。

第二个线程首先从内存中读取并将数据存储到List中,然后使用此数据进行一些计算。我有一个StopWatch类计时器来测量完成第二个线程的一次迭代所需的时间。该计时器在线程的最开始复位并启动,然后在线程完成迭代后停止并打印到控制台。这是我获取性能数据的地方。我一直允许Thread运行至少1000次迭代,然后做一个不包括第一次运行的平均值。

构建的DEBUG版本,即由VSHOST运行的构建版本,或者在Visual Studio C#2010 Express中运行F5的版本。时间平均值为0.00035s,即0.35ms。

当应用程序在VSHOST之外运行时,可以通过按Ctrl-F5或从命中BUILD时生成的.exe运行应用程序。我还使用REBUILD来测试这个绝对的ZERO变化。时间平均为.365s,即365ms。这与Release Build相比大约慢了1000倍。

我完全不知道发生了什么。 VSHOST做的是什么让程序运行得如此之快。我确保所有变量初始化都被考虑并且正确。话虽如此,我不知道为什么这样的事情会发生。任何有关我为什么会获得这样的表现的见解Dip?

作为旁注,我使用的计算机是64位,有一个带有超线程的四核i7,16 GB的RAM和两个HD6750。所以这似乎不是一个拥有太多线程的问题,这里可能存在的唯一问题就是超线程。

我的应用程序所做的代码片段。但是,由于读取的内存地址是发生减速的地方,因此无法提供工作代码。

namespace Test Snippet
{
public struct Data
{
    public float X;
    public float Y;
    public float Z;
    public float dX;
    public float dY;

    public Data(int c)
    {
        this.X = ReadFloat(Base + 0x50 + (c * 0x10));
        this.Y = ReadFloat(Base + 0x50 + (c * 0x10));
        this.Z = ReadFloat(Base + 0x50 + (c * 0x10));
        if (this.Z == 1)
        {
            targetindex = c;
        }
        this.dX = 0;
        this.dY = 0;
    }
}
class Class1
{
    public int Base = new int();
    public List<Data> data = new List<Data>();
    public int targetindex = new int();
    public Data targetdata = new Data();

    public void GetData()
    {
        while (true)
        {
            data.Clear();
            for (int c = 0; c < 64; c++)
            {
                Data tempdata = new Data();
                teampdata = new Data(c);
                data.Add(tempdata);
            }
            if (data.Count != 0)
            {
                targetdata = data[targetindex];
                data.RemoveAt(targetindex);
                targetdata.dX = ReadFloat(Base + 0x66);
                targetdata.dY = ReadFloat(Base + 0x65);
                Data[] tempdatarray = new Data[data.Count];
                for (int j = 0; j < tempdatarray.Length; j++)
                {
                    tempdatarray[j].dX = (float)Math.Acos(targetdata.dX * 10);
                    tempdatarray[j].dY = (float)Math.Acos(targetdata.dY * 10);
                }
            }

        }
    }
}

}

编辑::我尝试了相同的程序,但没有使用线程。我有用于捕获用户输入的Timer调用的线程函数。我得到了相同的结果。这意味着线程似乎不是问题。我也在不同的计算机上进行了测试,由于某种原因,我没有得到巨大的差异。这让我相信我的计算机可能有问题,或者由于其超线程能力而处理我的处理器处理线程的问题。任何人都知道超线程是否会导致多线程应用程序出现问题,而该应用程序未在程序中明确使用它。老实说,我不知道如何设置。

3 个答案:

答案 0 :(得分:1)

我没有看到任何内容表示您正在选择发布版本。这是工具栏上的一个选项。如果您直接运行调试版本,可能正在寻找找不到的东西。

编辑:除了我错过的头衔!!!! : - )

答案 1 :(得分:1)

首先,您应该进行一些性能分析。要么使用分析工具,要么只使用计时器打印某些消息,显示某些事情需要多长时间 - 这应该允许您至少确定哪些代码行正在缓慢运行,即使它没有告诉您运行的原因在调试器下这么慢。没有这些信息,你只需要猜测。

现在,猜测......

我认为问题与使用控制台有关,基于这些观察

  • 写入控制台窗口本身实际上相对较慢 - 在运行将大量内容写入控制台的应用程序时,您可以看到这一点。如果你打开窗口然后运行需要很长时间,但是如果你最小化控制台窗口,相同的操作可以更快地运行批次
  • 据我所知,你每隔0.35ms向控制台写一条消息。这是一个很多的消息。
  • 根据您运行应用程序的方式,Visual Studio实际上会在调试时将控制台输出重定向到Visual Studo中的“输出”窗口。

我的猜测是,Visual Studio中的控制台窗口比不调试时使用的等效机制快得多,并且额外减速的原因实际上是您的日志记录代码。尝试取出基于控制台的日志记录并记录到文件中,看看它是否有所不同,甚至只是减少记录消息的次数,例如记录完成100次迭代所需的时间 - 这将减少控制台对您的性能产​​生的影响(如果有的话)。

答案 2 :(得分:0)

问题与HyperThreading无关。我找不到这个链接,但2004年英特尔有一个很好的技术说明,说明它是如何工作的(没有任何营销宣传)。但缺点是:Core 0可能是真正的核心,Core 1可能是与Core 0共享相同硬件的逻辑核心。对于我们的观点(app devs),核心0和1都是真实的,我们不会必须关心Core 1是一个逻辑核心的事实(除了显而易见的,逻辑核心仅提供粗略的13-30%的整体提升,再次在技术描述中提到)。 Windows在实际核心和逻辑核心上调度线程方面做得相当不错。您所要做的就是创建两个线程,Windows将在Cores 0和1上分别运行一个线程。您可以在BIOS中禁用HyperThreading,以编程方式为线程设置处理器关联,或者如果您需要,可以从任务管理器设置关联试验。

话虽如此,试验HyperThreading并不能帮助您解决问题。您应该按照已经提到的那样进行操作并分析发布版本。还要在事件日志中查找奇怪的错误。并运行sysinternal的Process Explorer,看看是否在I / O上花费了太多时间。谁知道,也许发布版本在某种程度上会在这台机器上的设备驱动程序中引发一些古怪的行为。

编辑:这是英特尔的技术描述(yay Wikipedia),实际上是从2002年开始的:http://download.intel.com/technology/itj/2002/volume06issue01/vol6iss1_hyper_threading_technology.pdf