Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 时间跨度';s的比较太慢了_C#_.net_Performance - Fatal编程技术网

C# 时间跨度';s的比较太慢了

C# 时间跨度';s的比较太慢了,c#,.net,performance,C#,.net,Performance,最近我有一个奇怪的性能问题。 我需要将周期中的时间间隔与大量迭代进行比较。 我使用DateTime.TimeOfDay属性来比较这些间隔。然而,我发现这些比较与日期时间比较非常慢。所以,我必须创建一年一个月一天的日期时间,以加快时间间隔比较。 我准备了一个小例子来说明我的意思 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text;

最近我有一个奇怪的性能问题。 我需要将周期中的时间间隔与大量迭代进行比较。 我使用DateTime.TimeOfDay属性来比较这些间隔。然而,我发现这些比较与日期时间比较非常慢。所以,我必须创建一年一个月一天的日期时间,以加快时间间隔比较。 我准备了一个小例子来说明我的意思

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DatesBenchmark
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            DateTime firstDate = DateTime.Now;
            DateTime secondDate = DateTime.Now.AddSeconds(5);
            for (int i = 0; i < 2000000; i++)
            {
                var a = firstDate.TimeOfDay > secondDate.TimeOfDay;
                //var a = firstDate > secondDate;
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);
            Console.ReadKey();
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
命名空间DatesBenchmark
{
班级计划
{
静态void Main(字符串[]参数)
{
秒表sw=新秒表();
sw.Start();
DateTime firstDate=DateTime.Now;
DateTime secondDate=DateTime.Now.AddSeconds(5);
对于(int i=0;i<2000000;i++)
{
变量a=firstDate.TimeOfDay>secondDate.TimeOfDay;
//var a=第一个日期>第二个日期;
}
sw.Stop();
控制台写入线(软件延迟毫秒);
Console.ReadKey();
}
}
}
在我的笔记本电脑上,我得到了15毫秒(如果循环中的第一行被注释),而不是176毫秒(如果循环中的第二行被注释)


我的问题很简短。为什么?

您从未使用过
a
,因此在第二种情况下,编译器可以优化整个语句,因为它不会产生任何副作用,并且从不使用变量。在第一种情况下,无法确保在日期时间调用的属性不会产生副作用(优化分析没有那么深入),因此需要保留该行


最重要的是,在确定一天中的时间时,至少需要进行一些计算(它需要将日期时间中的节拍数修改为一天中的节拍数),这意味着它会更慢,这只是一个多少的问题。

您从未使用过
a
,因此,在第二种情况下,编译器可以优化整个语句,因为它不会产生任何副作用,并且永远不会使用变量。在第一种情况下,无法确保在日期时间调用的属性不会产生副作用(优化分析没有那么深入),因此需要保留该行


除此之外,在确定一天中的时间时,至少需要进行一些计算(它需要将日期时间中的节拍数修改为一天中的节拍数),这意味着它会更慢,这只是一个多少的问题。

调用foo.TimeOfDay就是这样做的:

public TimeSpan TimeOfDay
{
    get
    {
        return new TimeSpan(this.InternalTicks % 864000000000L);
    }
}
通过访问超过200万次迭代的2个
DateTime
实例上的
TimeOfDay
属性,您将创建400万个
Timespan
实例。然而,这并不是最大的花费

进一步挖掘,你有:

internal long InternalTicks
{
    get
    {
        return (long)(this.dateData & 4611686018427387903uL);
    }
}
因此,您有400万个实例化、余数计算、强制转换和
&
操作。这些都是便宜的操作(“便宜”当然是一个相对的术语),但它们加起来是数量上的

实际的比较是微不足道的:

public static bool operator >(TimeSpan t1, TimeSpan t2)
{
    return t1._ticks > t2._ticks;
}
在调试模式下编译OPs代码,我看到:

  • 空循环:4ms
  • var a=firstDate>secondDate6ms(表明未进行优化)
  • var a=firstDate.TimeOfDay40毫秒
  • var a=firstDate.TimeOfDay>secondDate.TimeOfDay80ms
  • TimeSpan a=新的TimeSpan(滴答声),b=新的TimeSpan(滴答声)7ms
  • 在VS 2012中针对该程序运行性能分析,81%的样本来自
    DateTime.get_TimeOfDay()

    运行x64,发布模式,启用所有优化:

  • 空循环:3ms
  • var a=firstDate>secondDate6ms
  • var a=firstDate.TimeOfDay20ms
  • var a=firstDate.TimeOfDay>secondDate.TimeOfDay40毫秒
  • TimeSpan a=新的TimeSpan(滴答声),b=新的TimeSpan(滴答声)6ms
  • 因此:

    • 微观基准可能具有误导性(尽管并非毫无用处)
    • 在确定是否存在问题之前启用优化
    • 性能似乎随着优化而加倍
    • 在任何情况下,所讨论的陈述似乎都不会被优化
    • 实例化是费用中有形但很小的一部分
    • Cast/算术运算占了其余的费用
    • 在循环之前将属性值存储在变量中可以极大地提高性能

      • 调用foo.TimeOfDay就是这样做的:

        public TimeSpan TimeOfDay
        {
            get
            {
                return new TimeSpan(this.InternalTicks % 864000000000L);
            }
        }
        
        通过访问超过200万次迭代的2个
        DateTime
        实例上的
        TimeOfDay
        属性,您将创建400万个
        Timespan
        实例。然而,这并不是最大的花费

        进一步挖掘,你有:

        internal long InternalTicks
        {
            get
            {
                return (long)(this.dateData & 4611686018427387903uL);
            }
        }
        
        因此,您有400万个实例化、余数计算、强制转换和
        &
        操作。这些都是便宜的操作(“便宜”当然是一个相对的术语),但它们加起来是数量上的

        实际的比较是微不足道的:

        public static bool operator >(TimeSpan t1, TimeSpan t2)
        {
            return t1._ticks > t2._ticks;
        }
        
        在调试模式下编译OPs代码,我看到:

      • 空循环:4ms
      • var a=firstDate>secondDate6ms(表明未进行优化)
      • var a=firstDate.TimeOfDay40毫秒
      • var a=firstDate.TimeOfDay>secondDate.TimeOfDay80ms
      • TimeSpan a=新的TimeSpan(滴答声),b=新的TimeSpan(滴答声)7ms
      • 在VS 2012中针对该程序运行性能分析,81%的样本来自
        DateTime.get_TimeOfDay()

        运行x64,发布模式,启用所有优化:

      • 空循环:3ms
      • var a=firstDate>secondDate6ms
      • var a=firstDate.TimeOfDay20ms
      • var a=firstDate.TimeOfDay>secondDate.TimeOfDay40毫秒
      • T