本文介绍了DateTime.DayOfWeek微优化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先:


  1. 我要求只是为了好玩而好学这个问题。我不得不承认我喜欢勾搭微优化(虽然他们从来没有导致我的任何发展速度的任何显著增加)。


  2. DateTime.DayOfWeek 方法不重新present在我的任何应用程序的瓶颈。


  3. 和它的不大可能的是在其他任何一个问题。如果有人在想,这种方法在他的应用程序的性能产生影响,
    他应该想想然后,他应该进行分析。


反编译的DateTime 类ILSpy,我们了解如何 DateTime.DayOfWeek 实施

  [__ DynamicallyInvokable]
        公共DAYOFWEEK DAYOFWEEK
        {
            [__DynamicallyInvokable,TargetedPatchingOptOut(性能的关键跨越NGEN图像边界内联)]
            得到
            {
                回报(星期几)((this.InternalTicks / 864000000000L + 1L)%7L);
            }
        }
众长虱子
{
    [__DynamicallyInvokable,TargetedPatchingOptOut(性能关键的内联这种类型的跨NGEN图像边界法)]
    得到
    {
        返回this.InternalTicks;
    }
}

此方法执行以下操作:


  1. 对应于当前的一天蜱蜱现有数在一天内分。


  2. 我们添加1至前述结果,为了使7除法的余数为数字0和6之间。


这是计算出星期几的唯一途径?

有没有可能重新实现这一点是为了使其运行速度更快?


解决方案

让我们做一些调谐。


  1. TimeSpan.TicksPerDay (8640亿)

星期几现在可以pssed如前$ P $:

 公共DAYOFWEEK DAYOFWEEK
{
    得到
    {
        回报(星期几)(((牛蜱GT;> 14)/ 52734375 + 1L)%7L);
    }
}

和我们在模7个, 52734375%7 这是一所以,$ C $上面c等于:

 公共静态DAYOFWEEK dayOfWeekTurbo(这个日期为准​​)
{
    返回(星期几)(((date.Ticks>> 14)+ 1)%7);
}

直观地说,它的工作原理。但是,让我们证明这一点的与code

 公共静态无效的证明()
{
    日期时间日期= DateTime.MinValue;
    日期时间MAX_DATE = DateTime.MaxValue.AddDays(-1);
    而(日期< MAX_DATE)
    {
        如果(date.DayOfWeek!= date.dayOfWeekTurbo())
        {
            Console.WriteLine({0} \\ t {1},date.DayOfWeek,date.dayOfWeekTurbo());
            到Console.ReadLine();
        }
        日期= date.AddDays(1);
    }
}

如果您愿意,您可以运行它,但我向你保证它工作正常。

好了,唯一剩下的东西是有点标杆。

这是一种辅助方法中,为了使code更清楚:

 公共静态的IEnumerable<&日期时间GT; getAllDates()
{
    日期时间D = DateTime.MinValue;
    日期时间最大= DateTime.MaxValue.AddDays(-1);
    而(D<最大)
    {
        产生回报D组;
        D = d.AddDays(1);
    }
}

我想这不需要解释。

 公共静态无效benchDayOfWeek()
{    。DateTime的[]日期= getAllDates()ToArray的();
    //为preventing编译器做的事情,我们不希望
    DAYOFWEEK []富=新DAYOFWEEK [dates.Length]
    对于(INT max_loop = 0; max_loop< 10000; max_loop + = 100)
    {
        秒表ST1,ST2;
        ST1 = Stopwatch.StartNew();
        的for(int i = 0; I< max_loop;我++)
            对于(INT J = 0; J< dates.Length; J ++)
                富[J] =日期[J] .DayOfWeek;
        st1.Stop();        ST2 = Stopwatch.StartNew();
        的for(int i = 0; I< max_loop;我++)
            对于(INT J = 0; J< dates.Length; J ++)
                富[J] =日期[J] .dayOfWeekTurbo();
        st2.Stop();        Console.WriteLine({0},{1},st1.ElapsedTicks,st2.ElapsedTicks);    }
    到Console.ReadLine();
    Console.WriteLine(富[0]);}

输出:

  96,28
172923452,50884515
352004290,111919170
521851120,168153321
683972846,215554958
846791857,264187194
1042803747,328459950
星期一

如果我们做与数据的图表,它看起来像这样:

<$p$p><$c$c>╔══════════════════════╦════════════════════╦═════════════════════╦═════════════╗
║║迭代标准DAYOFWEEK║优化DAYOFWEEK║提速数║
╠══════════════════════╬════════════════════╬═════════════════════╬═════════════╣
║║0║96║28║3.428571429
║║100║172923452║50884515║3.398351188
║║200║352004290║111919170║3.145165301
║║300║521851120║168153321║3.103424404
║║400║683972846║215554958║3.1730787
║║500║846791857║264187194║3.205272156
║║600║1042803747║328459950║3.174827698
╚══════════════════════╩════════════════════╩═════════════════════╩═════════════╝

3倍速度更快。

注:code编译使用Visual Studio 2013,发布模式,并与一切关闭,但应用程序运行。 (包括VS,当然)。

我跑的注意到了,这种方法可以当它是不是约会边界上失败。

由于乔恩斯基特的评论这个答案,

I decided to edit it.

If we change the proof() method,

public static void proof()
{
    DateTime date = DateTime.MinValue;
    DateTime max_date = DateTime.MaxValue.AddSeconds(-1);
    while (date < max_date)
    {
        if (date.DayOfWeek != date.dayOfWeekTurbo2())
        {
            Console.WriteLine("{0}\t{1}", date.DayOfWeek, date.dayOfWeekTurbo2());
            Console.ReadLine();
        }
        date = date.AddSeconds(1);
    }
}

Fails!

Jon Skeet was right. Let's follow Jon Skeet's advice and apply the division.

public static DayOfWeek dayOfWeekTurbo2(this DateTime date)
{
    return (DayOfWeek)((((date.Ticks >> 14) / 52734375L )+ 1) % 7);
}

Also, we change the method getAllDates().

public static IEnumerable<DateTime> getAllDates()
{
    DateTime d = DateTime.MinValue;
    DateTime max = DateTime.MaxValue.AddHours(-1);
    while (d < max)
    {
        yield return d;
        d = d.AddHours(1);
    }
}

And benchDayOfWeek()

public static void benchDayOfWeek()
{

    DateTime[] dates = getAllDates().ToArray();
    DayOfWeek[] foo = new DayOfWeek[dates.Length];
    for (int max_loop = 0; max_loop < 10000; max_loop ++)
    {


        Stopwatch st1, st2;
        st1 = Stopwatch.StartNew();
        for (int i = 0; i < max_loop; i++)
            for (int j = 0; j < dates.Length; j++)
                foo[j] = dates[j].DayOfWeek;
        st1.Stop();

        st2 = Stopwatch.StartNew();
        for (int i = 0; i < max_loop; i++)
            for (int j = 0; j < dates.Length; j++)
                foo[j] = dates[j].dayOfWeekTurbo2();
        st2.Stop();

        Console.WriteLine("{0},{1}", st1.ElapsedTicks, st2.ElapsedTicks);

    }
    Console.ReadLine();
    Console.WriteLine(foo[0]);

}

It will still be faster? the answer is yes

Output:

90,26
43772675,17902739
84299562,37339935
119418847,47236771
166955278,72444714
207441663,89852249
223981096,106062643
275440586,125110111
327353547,145689642
363908633,163442675
407152133,181642026
445141584,197571786
495590201,217373350
520907684,236609850
511052601,217571474
610024381,260208969
637676317,275558318
╔══════════════════════╦════════════════════╦════════════════════════╦═════════════╗
║ Number of iterations ║ Standard DayOfWeek ║ Optimized DayOfWeek(2) ║  Speedup    ║
╠══════════════════════╬════════════════════╬════════════════════════╬═════════════╣
║                    1 ║           43772675 ║               17902739 ║ 2.445026708 ║
║                    2 ║           84299562 ║               37339935 ║ 2.257624766 ║
║                    3 ║          119418847 ║               47236771 ║ 2.528090817 ║
║                    4 ║          166955278 ║               72444714 ║ 2.304588821 ║
║                    5 ║          207441663 ║               89852249 ║ 2.308697504 ║
║                    6 ║          223981096 ║              106062643 ║ 2.111781205 ║
║                    7 ║          275440586 ║              125110111 ║ 2.201585338 ║
║                    8 ║          327353547 ║              145689642 ║ 2.246923958 ║
║                    9 ║          363908633 ║              163442675 ║ 2.226521519 ║
║                   10 ║          407152133 ║              181642026 ║ 2.241508433 ║
║                   11 ║          445141584 ║              197571786 ║ 2.25306251  ║
║                   12 ║          495590201 ║              217373350 ║ 2.279903222 ║
║                   13 ║          520907684 ║              236609850 ║ 2.201546909 ║
║                   14 ║          511052601 ║              217571474 ║ 2.348895246 ║
║                   15 ║          610024381 ║              260208969 ║ 2.344363391 ║
║                   16 ║          637676317 ║              275558318 ║ 2.314124725 ║
╚══════════════════════╩════════════════════╩════════════════════════╩═════════════╝

2x faster.

这篇关于DateTime.DayOfWeek微优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-11 22:38