我需要更换秒表以避免使用getter作为其属性。我将使用QueryPerformanceCounter实现它。 我只需要刻度没有别的。
任何人都可以提供代码snipet,以获得正确的刻度(1/10000毫秒)或任何其他小而稳定的值。
请注意我的服务器将时钟粒度设置为 0.5 ms (不确定它是否会影响QueryPerformanceCounter),但只是为了让您知道。
请注意 - 我不需要计时器。我只需要测量代码部分之间的时间间隔。
编辑:以避免混淆我真的想知道QueryPerformanceCounter中的 lpPerformanceCount (out lpPerformanceCount);
答案 0 :(得分:10)
http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.gettimestamp.aspx
Stopwatch.GetTimestamp
您不必实例化Stopwatch
对象,GetTimestamp
应该返回滴答数,而不管其上下文。
答案 1 :(得分:5)
[DllImport("Kernel32.dll")]
private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
[DllImport("Kernel32.dll")]
private static extern bool QueryPerformanceFrequency(out long lpFrequency);
取自http://www.codeproject.com/Articles/2635/High-Performance-Timer-in-C
旧但它应该仍然有用
编辑:StopWatch
的内部实际使用QueryPerformanceCounter
,因此使用托管代码应提供相同的结果,并具有更好的兼容性。
答案 2 :(得分:1)
请勿在未经测试的情况下使用StopWatch进行高分辨率计时。我测试它已经有几年了,但当时它给出了默认的窗口时间分辨率。你可以说,因为如果它使用默认的窗口分辨率,真的,非常快的事情将需要0或10-15毫秒(默认分辨率实际上是线程上下文切换的分辨率,可能是在每个上下文中更新默认的Windows时钟开关,大约每10-15毫秒)。
答案 3 :(得分:1)
我使用下面的类将系统上的时间精确到100ns。
public class MStopwatch : Stopwatch
{
private double _frequencyScaler;
public MStopwatch()
{
_frequencyScaler = 1.0 / Stopwatch.Frequency;
}
public double ElapsedSeconds
{
get
{
return ElapsedTicks * _frequencyScaler;
}
}
}
答案 4 :(得分:0)
不是直接的答案(但可能需要支持信息):
一些提供的答案非常适合直接回答您的问题。但是,为了完成你想要做的事情,我想补充一些注意事项。
首先,考虑在运行时发生的实时(jit)编译器的时序开销。获取初始时间戳的任何代码然后执行 stuff ,然后获取最终时间戳以减去delta的t2-t1,对于 stuff 中的任何功能,如果你包括您在当前进程中尚未调用的任何函数,然后在第一次调用它时,您将支付jit开销以将字节码编译为本机代码。在这种情况下,成本并不代表性能关键代码的实际运行时成本,这可能是频繁调用的代码,但其jit成本仅支付一次(在此过程中首次调用它)。因此,多次调用定时代码,抛出第一个时间,然后取平均值。
此外要注意垃圾收集器的运行时成本。如果您只是在玩游戏,那么对可以严格避免分配新对象的代码进行基准测试可能是有趣的。但有时这并不容易,特别是当您调用其实现无法更改的函数时。此外,我必须告诉你,生产代码的实际性能开销无法避免垃圾收集开销,因此获得一个真实的数字应该包括这个开销。也就是说,如果您的 stuff 包含分配新对象的代码,那么它可能会启动垃圾收集器,这将是昂贵的,因此请准备好您可能想要丢弃的一些潜在异常值。
其次,好的答案提供了代码来声明从系统dll调用的外部函数,这很好。在一般情况下获得这些签名是正确的,有时可能会令人讨厌,所以我想提一个很好的资源:pinvoke.net。 搜索QueryPerformanceCounter给了我一些签名,这些签名让我对已经给出的答案进行了剪切和粘贴,对于您想要进行的任何系统调用来说,它都是一个很好的资源。
http://pinvoke.net/search.aspx?search=QueryPerformanceCounter&namespace=[All]
答案 5 :(得分:-1)
I don't remember from where I copied it, but this code works well for me:
public class QueryPerfCounter
{
[DllImport("KERNEL32")]
private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
[DllImport("Kernel32.dll")]
private static extern bool QueryPerformanceFrequency(out long lpFrequency);
private long start;
private long stop;
private long frequency;
double multiplier = 1.0e6; // usecs / sec
public QueryPerfCounter()
{
if (QueryPerformanceFrequency(out frequency) == false)
{
// Frequency not supported
throw new Win32Exception();
}
}
public void Start()
{
QueryPerformanceCounter(out start);
}
public void Stop()
{
QueryPerformanceCounter(out stop);
}
public double Duration(int iterations)
{
return ((((stop - start) * multiplier) / frequency) / iterations);
}
}