我写了一段如下代码:
为了进行测试,我调用了ComputeAndLog方法,在性能监视器中我可以看到非零的平均值。然而,一旦我结束测试,平均性能计数器值就会降至零。知道为什么会这样吗?
可能我用错计数器了?
我的要求是我有一个函数,我必须平均计算出这个函数需要多少时间才能完成。如下所示:
void ComputeAndLog()
{
Stopwatch stopWatch = Stopwatch.StartNew();
FunctionWhoseAveragetTimeIsToBeMeasured();
write_counter(stopWatch.ElapsedTicks);
}
void write_counter(long timeForCompletion)
{
averageTimeCounter.IncrementBy(timeForCompletion);
averageBaseCounter.Increment();
}
谢谢xoxo
AverageTimer32/64不会计算您执行的所有测量的平均值。相反,它提供了测量值与测量操作数的比值。
基本上,代码的问题是每次执行测量时都使用新的计时器。
要了解AverageTimer的工作原理,了解其背后的公式可能会有所帮助。这也回答了为什么需要AverageBase才能使用AverageTimer。
AverageTimer的公式如下:
((N1 - N0) / F) / (B1 - B0)
带有
- N1时间t的电流读数(AverageTimer)
- 在t-1之前的N0读数(AverageTimer)
- t处的B1电流计数器(AverageBase)
- B0计数器之前,在t-1(平均基数)
- F用于计算节拍/秒的系数
简言之,公式化器以节拍为单位获取当前时间,并减去前一个时间。结果除以因子F得出自上次t-1测量以来运行的操作时间。
现在你把它除以当前计数器减去之前的计数器。这可能通常是一个。因此,您可以获得一次测量的平均操作时间。
使用AverageBase,您现在可以跨过各种测量点。想象一下这样一种情况:你可以只每执行十分之一的操作就设置一次计数器。自上次测量以来,您会将所有十次操作的AverageTimer增加新的时间测量,但将AverageBase增加十。最终,您将收到一次操作的平均时间(即使您已经测量了所有十次操作调用)。
看看你的代码示例,你发送的总是从定时器开始到定时器结束的差异。设这是一系列数字,如10、9、8、7、6,同时将AverageBase增加1。
对于第二次测量,您知道将收到以下结果:
(9-10)/F/(1-0)=-1/F/1
为了简单起见,F为1,结果得到-1。
然而,要提交的正确值应该是
10,19,27,34,40
同样的例子,我们将得到
(19-10)/F/(1-0)=9/F/1
同样,当F为1时,你的手术平均时间为9。正如您所看到的,下一个测量值需要大于上一个,这样AverageTimer才能正常工作。
在您的示例中,您可能使用全局秒表。使用Start()(而不是Restart()),而不是重新启动它。如上所述,计数器将在内部计算时间差。这样你就能得到正确的测量结果。
归零也是有意义的,一旦你完成了测试或程序结束,计数器可能会关闭,不再提供任何值。您可以通过调用计数器上的Close()方法手动执行此操作。
我也遇到过类似的问题。我在AverangeCounter的PerformanceMonitor中有一个很好的输出。但在程序中,操作NextValue总是返回0。顺便说一下,在ElapsedTime计数器中,同样的操作返回了我想要的值。
然后我了解AverageTimer32的核心(我希望如此)。您不应该希望AverageTimer32显示某些工作的平均时间。它只是一个计时器,用于计算一次操作的平均时间并显示它。如果没有工作进行,则不存在任何操作时间,并且计数器的值为0。
如果我每次添加刻度来计算NextValue,它将返回秒数(据我所知,它返回的是最后一个值,而不是平均值。AverageTimer32计数器的名称可能会让任何人误解)。若我缓存它,那个么我可以将它转换成更可读的形式,并将其用作程序中计数器的值(若您在收到0的第二次请求NextValue)。
此外,我想更正之前的答案。你应该使用
10、9、8、7、6
而不是
10,19,27,34,40
当您使用IncreaseBy和方法时
10,19,27,34,40
当您在RawValue中手动设置Stopwatch.GetTimestamp()时。