c#编译器如何处理这个DateTime.ToOADate()

本文关键字:DateTime ToOADate 编译器 何处理 处理 | 更新日期: 2023-09-27 18:02:24

我需要在大型数据集上有非常高性能的循环。我需要比较时间戳,但我的日期是OA格式:

if (md.DT_OA > new DateTime(2011, 3, 13).ToOADate()) 

编译器会在每个循环中计算new DateTime(2011, 3, 13).ToOADate()吗?或者"优化器"会在一开始就解决这个问题吗?

。我能在代码中偷懒而不受惩罚吗?

你可以告诉我-我不太了解编译器是如何工作的…

编辑1

评论启发我做一个适当的测试:

选项2比选项1更接近3% faster。令人惊讶的是没有快多少——编译器似乎非常聪明,或者日期创建速度很快。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Test1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            Go();
        }
        public static void Go() 
        {
            int c = 0;
            DateTime st = DateTime.Now;
            DateTime dt = new DateTime(2011, 3, 13);
            for (int i = 0; i < 1000000; i++) 
            {
                if (DateTime.Now > new DateTime(2011, 3, 13)) // Option 1
                //if (DateTime.Now > dt)                          // Option 2
                {
                    c++;
                }
            }
            MessageBox.Show("Time taken: " + DateTime.Now.Subtract(st).TotalMilliseconds + " c: " + c);
        } 
    }
}

c#编译器如何处理这个DateTime.ToOADate()

我看它没有理由优化…很确定它不会(我知道它不会在IL层进行优化,但这并没有说明JIT的任何问题;但是我真的不认为它会- 它不知道方法每次都会返回相同的东西)。

相反,如果你关心它,把它从循环中提出来:

var oaDate = new DateTime(2011, 3, 13).ToOADate();
...loop...
    if (md.DT_OA > oaDate) {...}

Re just new DateTime(int,int,int)(注释);让我们创建一个测试程序:

    static void Main()
    {
        for (int i = 0; i < 1000; i++)
        {
            if (DateTime.Now > new DateTime(2011, 3, 13)) Console.WriteLine("abc");
        }
    }

如果我们编译它,然后反汇编IL (reflector/ildasm/etc),我们得到:

L_0000: ldc.i4.0 
L_0001: stloc.0 
L_0002: br.s L_002b
L_0004: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now()
L_0009: ldc.i4 0x7db
L_000e: ldc.i4.3 
L_000f: ldc.i4.s 13
L_0011: newobj instance void [mscorlib]System.DateTime::.ctor(int32, int32, int32)
L_0016: call bool [mscorlib]System.DateTime::op_GreaterThan(valuetype [mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime)
L_001b: brfalse.s L_0027
L_001d: ldstr "abc"
L_0022: call void [mscorlib]System.Console::WriteLine(string)
L_0027: ldloc.0 
L_0028: ldc.i4.1 
L_0029: add 
L_002a: stloc.0 
L_002b: ldloc.0 
L_002c: ldc.i4 0x3e8
L_0031: blt.s L_0004
L_0033: ret 

查看L_0009到L_0011—每个循环迭代创建new DateTime (L_0031: blt.s L_0004是循环重复)。如我所料,编译器对您的请求进行了文字处理。