问题描述
首先:
-
我要求只是为了好玩而好学这个问题。我不得不承认我喜欢勾搭微优化(虽然他们从来没有导致我的任何发展速度的任何显著增加)。
-
的
DateTime.DayOfWeek
方法不重新present在我的任何应用程序的瓶颈。 -
和它的不大可能的是在其他任何一个问题。如果有人在想,这种方法在他的应用程序的性能产生影响,
他应该想想然后,他应该进行分析。
反编译的DateTime
类ILSpy,我们了解如何 DateTime.DayOfWeek
实施
[__ DynamicallyInvokable]
公共DAYOFWEEK DAYOFWEEK
{
[__DynamicallyInvokable,TargetedPatchingOptOut(性能的关键跨越NGEN图像边界内联)]
得到
{
回报(星期几)((this.InternalTicks / 864000000000L + 1L)%7L);
}
}
众长虱子
{
[__DynamicallyInvokable,TargetedPatchingOptOut(性能关键的内联这种类型的跨NGEN图像边界法)]
得到
{
返回this.InternalTicks;
}
}
此方法执行以下操作:
-
对应于当前的一天蜱蜱现有数在一天内分。
-
我们添加1至前述结果,为了使7除法的余数为数字0和6之间。
这是计算出星期几的唯一途径?
有没有可能重新实现这一点是为了使其运行速度更快?
让我们做一些调谐。
- 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微优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!