【问题标题】:Why is my ElapsedMilliseconds always zero here?为什么我的 ElapsedMilliseconds 总是在这里为零?
【发布时间】:2016-04-10 05:35:34
【问题描述】:

所以我试图衡量我创建的哈希集的性能与List 和以下代码块中相同元素的性能

        Stopwatch Watch = new Stopwatch();
        long tList = 0, tHset = 0; // ms
        foreach ( string Str in Copy )
        {
            // measure time to look up string in ordinary list
            Watch.Start();
            if ( ListVersion.Contains(Str) ) { }
            Watch.Stop();
            tList += Watch.ElapsedMilliseconds;
            // now measure time to look up same string in my hash set
            Watch.Reset();
            Watch.Start();
            if ( this.Contains(Str) ) { }
            Watch.Stop();
            tHset += Watch.ElapsedMilliseconds;
            Watch.Reset();
        }
        int n = Copy.Count;
        Console.WriteLine("Average milliseconds to look up in List: {0}", tList / n);
        Console.WriteLine("Average milliseconds to look up in hashset: {0}", tHset / n);

它为两者输出0。知道这是为什么吗?相关文档:https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch(v=vs.110).aspx

【问题讨论】:

  • 因为操作太快了,你不应该这样衡量性能。

标签: c# .net performance data-structures


【解决方案1】:

这是因为运算比Stapwatch 的精度要快。

不要单独测量Contains 调用中的每一个,而是单独测量它们中的一组:

Stopwatch Watch = new Stopwatch();
long tList = 0, tHset = 0; // ms

// measure time to look up string in ordinary list
Watch.Start();
foreach ( string Str in Copy )
{
    if ( ListVersion.Contains(Str) ) { }
}
Watch.Stop();
tList = Watch.ElapsedMilliseconds;
// now measure time to look up same string in my hash set
Watch.Reset();
Watch.Start();
foreach ( string Str in Copy )
{
    if ( this.Contains(Str) ) { }
}
Watch.Stop();
tHset = Watch.ElapsedMilliseconds;

Console.WriteLine("Total milliseconds to look up in List: {0}", tList);
Console.WriteLine("Total milliseconds to look up in hashset: {0}", tHset);

如您所见,我还更改了代码以打印花费的总时间而不是平均时间。对于如此快速的操作,性能通常以 Xs per Y 操作而不是平均值来表示。例如。每 1000 万次查找需要 40 毫秒。

此外,在发布模式下,您的部分代码可能会被优化掉,因为它实际上并没有做任何事情。考虑计算 Contains 返回 true 的元素数量,并在最后打印出该数字。

【讨论】:

  • 嗯?如果我的编译器假定我的 if 语句在程序中没有完成任何事情,那它会很愚蠢
  • @user6048670 但是你的 if 什么都不做。如果编译器认识到这一点,它又是多么愚蠢?
  • 它必须是一个非常聪明的编译器才能理解对容器的Contains 方法的调用没有副作用。我怀疑程序集元数据是否包含足够的信息来告诉编译器类似的事情。
【解决方案2】:

您可以保持代码不变,而不是这样做:

Watch.ElapsedMilliseconds

你这样做:

Watch.Elapsed.TotalMilliseconds

这样你将得到毫秒的小数部分

【讨论】:

    猜你喜欢
    • 2021-09-13
    • 1970-01-01
    • 2010-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多