我意识到这对微优化 Realm 来说太遥不可及,但是我很好奇理解为什么对DateTime.Now和DateTime.UtcNow的调用是如此“昂贵”。我有一个示例程序,该程序运行一些完成某些“工作”(添加到计数器)的场景,并尝试执行1秒钟。我有几种方法可以使其在有限的时间内完成工作。这些示例显示DateTime.Now和DateTime.UtcNow明显比Environment.TickCount慢,但与仅让一个单独的线程睡眠1秒然后设置一个值以指示工作线程停止相比,这仍然很慢。
所以我的问题是:
请原谅这个例子的冗长:
class Program
{
private static volatile bool done = false;
private static volatile int doneInt = 0;
private static UInt64 doneLong = 0;
private static ManualResetEvent readyEvent = new ManualResetEvent(false);
static void Main(string[] args)
{
MethodA_PrecalcEndTime();
MethodB_CalcEndTimeEachTime();
MethodC_PrecalcEndTimeUsingUtcNow();
MethodD_EnvironmentTickCount();
MethodX_SeperateThreadBool();
MethodY_SeperateThreadInt();
MethodZ_SeperateThreadLong();
Console.WriteLine("Done...");
Console.ReadLine();
}
private static void MethodA_PrecalcEndTime()
{
int cnt = 0;
var doneTime = DateTime.Now.AddSeconds(1);
var startDT = DateTime.Now;
while (DateTime.Now <= doneTime)
{
cnt++;
}
var endDT = DateTime.Now;
Console.WriteLine("Time Taken: {0,30} Total Counted: {1,20}", endDT.Subtract(startDT), cnt);
}
private static void MethodB_CalcEndTimeEachTime()
{
int cnt = 0;
var startDT = DateTime.Now;
while (DateTime.Now <= startDT.AddSeconds(1))
{
cnt++;
}
var endDT = DateTime.Now;
Console.WriteLine("Time Taken: {0,30} Total Counted: {1,20}", endDT.Subtract(startDT), cnt);
}
private static void MethodC_PrecalcEndTimeUsingUtcNow()
{
int cnt = 0;
var doneTime = DateTime.UtcNow.AddSeconds(1);
var startDT = DateTime.Now;
while (DateTime.UtcNow <= doneTime)
{
cnt++;
}
var endDT = DateTime.Now;
Console.WriteLine("Time Taken: {0,30} Total Counted: {1,20}", endDT.Subtract(startDT), cnt);
}
private static void MethodD_EnvironmentTickCount()
{
int cnt = 0;
int doneTick = Environment.TickCount + 1000; // <-- should be sane near where the counter clocks...
var startDT = DateTime.Now;
while (Environment.TickCount <= doneTick)
{
cnt++;
}
var endDT = DateTime.Now;
Console.WriteLine("Time Taken: {0,30} Total Counted: {1,20}", endDT.Subtract(startDT), cnt);
}
private static void MethodX_SeperateThreadBool()
{
readyEvent.Reset();
Thread counter = new Thread(CountBool);
Thread waiter = new Thread(WaitBool);
counter.Start();
waiter.Start();
waiter.Join();
counter.Join();
}
private static void CountBool()
{
int cnt = 0;
readyEvent.WaitOne();
var startDT = DateTime.Now;
while (!done)
{
cnt++;
}
var endDT = DateTime.Now;
Console.WriteLine("Time Taken: {0,30} Total Counted: {1,20}", endDT.Subtract(startDT), cnt);
}
private static void WaitBool()
{
readyEvent.Set();
Thread.Sleep(TimeSpan.FromSeconds(1));
done = true;
}
private static void MethodY_SeperateThreadInt()
{
readyEvent.Reset();
Thread counter = new Thread(CountInt);
Thread waiter = new Thread(WaitInt);
counter.Start();
waiter.Start();
waiter.Join();
counter.Join();
}
private static void CountInt()
{
int cnt = 0;
readyEvent.WaitOne();
var startDT = DateTime.Now;
while (doneInt<1)
{
cnt++;
}
var endDT = DateTime.Now;
Console.WriteLine("Time Taken: {0,30} Total Counted: {1,20}", endDT.Subtract(startDT), cnt);
}
private static void WaitInt()
{
readyEvent.Set();
Thread.Sleep(TimeSpan.FromSeconds(1));
doneInt = 1;
}
private static void MethodZ_SeperateThreadLong()
{
readyEvent.Reset();
Thread counter = new Thread(CountLong);
Thread waiter = new Thread(WaitLong);
counter.Start();
waiter.Start();
waiter.Join();
counter.Join();
}
private static void CountLong()
{
int cnt = 0;
readyEvent.WaitOne();
var startDT = DateTime.Now;
while (doneLong < 1)
{
cnt++;
}
var endDT = DateTime.Now;
Console.WriteLine("Time Taken: {0,30} Total Counted: {1,20}", endDT.Subtract(startDT), cnt);
}
private static void WaitLong()
{
readyEvent.Set();
Thread.Sleep(TimeSpan.FromSeconds(1));
doneLong = 1;
}
}
最佳答案
TickCount
只是读取一个不断增加的计数器。这只是您可以做的最简单的事情。DateTime.UtcNow
需要查询系统时间-别忘了TickCount
非常乐于忽略用户更改时钟或NTP之类的事情,而UtcNow
必须考虑到这一点。
现在您已经表达了对性能的关注-但是在给出的示例中,您要做的只是增加一个计数器。我希望在您的真实代码中,您将做的工作更多。如果您要进行大量工作,则可能会使UtcNow
花费的时间相形见.。在执行其他任何操作之前,您应该先进行测量,以查明您是否实际上正在尝试解决不存在的问题。
如果确实需要改进,则: