Tôi nhận ra đây là cách quá xa vào khu vực tối ưu hóa vi mô, nhưng tôi tò mò muốn hiểu tại sao Cuộc gọi đến DateTime.Now và DateTime.UtcNow quá "đắt tiền" . Tôi có một chương trình mẫu chạy một vài kịch bản của làm một số "công việc" (thêm vào một truy cập) và cố gắng để làm điều này trong 1 giây. Tôi có một số cách tiếp cận làm cho nó làm công việc cho một số lượng hạn chế thời gian. Các ví dụ cho thấy DateTime.Now và DateTime.UtcNow chậm hơn đáng kể so với Environment.TickCount, nhưng thậm chí chậm hơn so với chỉ để cho một luồng ngủ riêng biệt trong 1 giây và sau đó thiết lập một giá trị để cho biết luồng công nhân dừng lại.Tại sao DateTime.Now DateTime.UtcBây giờ quá chậm/tốn kém
Vì vậy, câu hỏi của tôi là những:
- Tôi biết rằng UtcNow là nhanh hơn bởi vì nó không có thông tin múi giờ, tại sao nó vẫn còn quá chậm hơn nhiều so với TickCount?
- Tại sao đọc boolean nhanh hơn int?
- Cách lý tưởng để đối phó với các loại tình huống này là nơi bạn cần cho phép một thứ gì đó chạy trong một khoảng thời gian hạn chế, nhưng bạn không muốn lãng phí thời gian kiểm tra thời gian hơn là thực sự làm công việc?
Hãy tha thứ tính cách rườm rà của ví dụ:
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;
}
}
Cảm ơn Jon. Tôi sẽ nhìn vào giờ. Tôi nhận ra "công việc" trong ví dụ của tôi là không thực tế. Tuy nhiên tôi đã tò mò về nơi tác động lớn đến từ đâu. –
@ My Other Me: Về cơ bản, so với công việc tăng lượt truy cập, gần như mọi công việc sẽ được tính là một tác động lớn :) –