Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
283 views
in Technique[技术] by (71.8m points)

c# - DateTime.Now causes IO blocking?

On a conference someone told me that DateTime.Now causes IO blocking, something that I have never stopped to consider. If it does, why?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Well, considering that

using ILSpy on mscorelib we can find out, that DateTime.Now, appears in this way:

public static DateTime Now
{
    get
    {
        DateTime utcNow = DateTime.UtcNow;
        bool isAmbiguousDst = false;
        long ticks = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousDst).Ticks;
        long num = utcNow.Ticks + ticks;
        if (num > 3155378975999999999L)
        {
            return new DateTime(3155378975999999999L, DateTimeKind.Local);
        }
        if (num < 0L)
        {
            return new DateTime(0L, DateTimeKind.Local);
        }
        return new DateTime(num, DateTimeKind.Local, isAmbiguousDst);
    }
}

The function GetDateTimeNowUtcOffsetFromUtc appears like:

internal static TimeSpan GetDateTimeNowUtcOffsetFromUtc(DateTime time, out bool isAmbiguousLocalDst)
{
    isAmbiguousLocalDst = false;
    TimeZoneInfo.OffsetAndRule oneYearLocalFromUtc = TimeZoneInfo.GetOneYearLocalFromUtc(time.Year);
    TimeSpan timeSpan = oneYearLocalFromUtc.offset;
    if (oneYearLocalFromUtc.rule != null)
    {
        bool isDaylightSavingsFromUtc = TimeZoneInfo.GetIsDaylightSavingsFromUtc(time, time.Year, oneYearLocalFromUtc.offset, oneYearLocalFromUtc.rule, out isAmbiguousLocalDst);
        timeSpan += (isDaylightSavingsFromUtc ? oneYearLocalFromUtc.rule.DaylightDelta : TimeSpan.Zero);
    }
    return timeSpan;
}

GetOneYearLocalFromUtc instead appears like:

private static TimeZoneInfo.OffsetAndRule GetOneYearLocalFromUtc(int year)
{
    if (TimeZoneInfo.s_oneYearLocalFromUtc == null || TimeZoneInfo.s_oneYearLocalFromUtc.year != year)
    {
        TimeZoneInfo currentOneYearLocal = TimeZoneInfo.GetCurrentOneYearLocal();
        TimeZoneInfo.AdjustmentRule rule = (currentOneYearLocal.m_adjustmentRules == null) ? null : currentOneYearLocal.m_adjustmentRules[0];
        TimeZoneInfo.s_oneYearLocalFromUtc = new TimeZoneInfo.OffsetAndRule(year, currentOneYearLocal.BaseUtcOffset, rule);
    }
    return TimeZoneInfo.s_oneYearLocalFromUtc;
}

finally GetCurrentOneYearLocal appears like:

private static TimeZoneInfo GetCurrentOneYearLocal()
{
    Win32Native.TimeZoneInformation timeZoneInformation = default(Win32Native.TimeZoneInformation);
    long num = (long)UnsafeNativeMethods.GetTimeZoneInformation(out timeZoneInformation);
    TimeZoneInfo result;
    if (num == -1L)
    {
        result = TimeZoneInfo.CreateCustomTimeZone("Local", TimeSpan.Zero, "Local", "Local");
    }
    else
    {
        result = TimeZoneInfo.GetLocalTimeZoneFromWin32Data(timeZoneInformation, false);
    }
    return result;
}

The interesting function is GetTimeZoneInformation, present in kernel32.dll which described in documentation like:

Retrieves the current time zone settings. These settings control the translations between Coordinated Universal Time (UTC) and local time.

To access that time information Windows actually uses IO access. Not sure if this can be defined like a "blocking", but it's definitely acessing system information saved on the disk, at least part of it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...