2010-08-06 84 views
1

另一个“不重要”的性能问题。 不重要的,因为主要代码可读性比几毫秒更重要,但无论如何有趣。 我注意到不同DateTime比较之间存在差异。为什么Date1.CompareTo(Date2)> 0比Date1> Date2更快?

我检查3层的替代品:

Dim clock As New System.Diagnostics.Stopwatch 
    Dim t1, t2, t3 As Long 
    Dim Date1 As Date = Date.Now.AddSeconds(2), Date2 As Date = Date.Now 
    Dim isGreaterThan As Boolean 
    clock.Start() 
    For i As Int32 = 1 To 1000000000 
     isGreaterThan = Date1 > Date2 
    Next 
    clock.Stop() 
    t1 = clock.ElapsedMilliseconds 
    clock.Reset() 
    clock.Start() 
    For i As Int32 = 1 To 1000000000 
     isGreaterThan = Date.Compare(Date1, Date2) > 0 
    Next 
    clock.Stop() 
    t2 = clock.ElapsedMilliseconds 
    clock.Reset() 
    clock.Start() 
    For i As Int32 = 1 To 1000000000 
     isGreaterThan = Date1.CompareTo(Date2) > 0 
    Next 
    clock.Stop() 
    t3 = clock.ElapsedMilliseconds 

结果:

  1. 日期1>日期2 = 13207/13251/13267/13569/13100 = 毫秒
  2. Date.Compare( Date1,Date2)> 0 = 13510/13194/13081/13353/13092 = ms
  3. Date1.CompareTo(Date2)> 0 = 11776/11768/11865/11776/11847 = 毫秒

通常我选择第一方法,因为它是更具有可读性和比其他故障安全。方法3是最快的。这是编译器在我使用运算符重载方法1时会选择的方法吗?如果是,为什么在运行时会有差异? 方法2是最慢的,也许是因为它是共享/静态的?! UPDATE:增加了一些更多的值。现在Metod 1和2相当快。

也许有人可以用事实来澄清它。 谢谢。

+2

在10亿次迭代中,相差不到2秒......实际上并不重要,也不重要。 – Oded 2010-08-06 10:44:36

+1

您是否测量过多次,排除异常值并对结果进行平均? – 2010-08-06 10:45:09

+0

无论原因如何,“缓慢”版本每秒(在您的硬件上)的* 75百万*比较而不是* 85百万*。除非您在某个问题的基准测试中依赖于性能的应用程序处于紧缩环境中,否则更偏好于微观优化的可读性。 – 2010-08-06 10:57:20

回答

2

让我们用一些反射魔法这个功能(全部来自日期时间型):

操作 “>”

public static bool operator >(DateTime t1, DateTime t2) 
{ 
    return (t1.InternalTicks > t2.InternalTicks); 
} 

private long InternalTicks 
{ 
    get 
    { 
     return (((long) this.dateData) & 0x3fffffffffffffffL); 
    } 
} 

// this.dateData is a private field 

比较

public static int Compare(DateTime t1, DateTime t2) 
{ 
    long internalTicks = t1.InternalTicks; 
    long num2 = t2.InternalTicks; 
    if (internalTicks > num2) 
    { 
     return 1; 
    } 
    if (internalTicks < num2) 
    { 
     return -1; 
    } 
    return 0; 
} 

CompareTo

public int CompareTo(DateTime value) 
{ 
    long internalTicks = value.InternalTicks; 
    long num2 = this.InternalTicks; 
    if (num2 > internalTicks) 
    { 
     return 1; 
    } 
    if (num2 < internalTicks) 
    { 
     return -1; 
    } 
    return 0; 
} 

让我们来分析一下:

操作>

  • 两名反对私有财产
  • 每次调用发出一个演员和一个二进制通话And

Compare和CompareT Ø

  • 创建两个变量,并对它们进行比较

CompareTo是最有可能更快,因为它不需要访问outside对象,而是可以借鉴本身的变量之一。

编辑:从看功能我意识到,>性能应该始终保持不变,而CompareCompareTo性能的基础上传递的值:

  • T1更大:最快
  • T2更大:中
  • T1 T2 ==:最慢

虽然,我们谈论的绩效增益或损失是......我该怎么说...我无所谓。 ;)但是这很安静有趣,我同意。

+3

DateTime是一个结构体,因此通过值(复制)传递给方法调用。这会使CompareTo的堆栈帧比其他堆栈帧小。有趣的是,Compare和CompareTo都使用对随机数据执行(略微)更差的分支操作(测试数据总是遵循CPU将优化的同一分支)。我没有尝试过,但我希望操作符<对随机输入更快。 – star 2010-08-06 12:18:36

+0

@star:你的评论应该是一个答案,值得自己投票。 – 2010-08-07 16:02:22

0

如果数字持续存在,可能会有某种缓存在进行。为了检测这个,你可以尝试在你的程序中重新排序测试或重复测试三元组(如ABCABC)。

+0

重新排序时,似乎没有什么区别 – 2010-08-06 11:14:11

相关问题