Вопрос по c# – DateTime.Now вызывает блокировку ввода-вывода?

3

На конференции кто-то сказал мне, чтоDateTime.Now вызывает блокировку ввода-вывода, что я никогда не переставал рассматривать. Если это так, почему?

Странно, почему этот вопрос получает так много голосов с таким небольшим количеством справочной информации. Мой следующий вопрос:"I've heard that too many stackoverflow exceptions can cause the computer to blow, if it does, why??" Rango
Могу ли я спросить, почему вы не спросили человека, который сказал вам это? Default
Это провокационный вопрос. Какова была тема конференции? .Net в целом? Телефон с операционной системой Виндоус? XNA? Austin Salonen
Это первый раз, когда я что-то слышал об этом. MSDN говорит, что вы, например, не должны использовать DateTime.Now для тестирования производительности, но это только объясняет, что, говоря, у него нет хорошего разрешения. lesderid
Я не уверен, что это проблемаI/O обязательно блокировать настолько, насколько это возможно, чтобы выполнялся системный вызов, и, таким образом, точно так же, как когда вы делаете вызов функции ввода-вывода, вы даете системе возможность взять управление у вашего процесса и передать его другой. jswolf19

Ваш Ответ

3   ответа
5

Ну, учитывая что

с помощьюILSpy наmscorelib мы можем выяснить, чтоDateTime.Now, выглядит так:

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);
    }
}

ФункцияGetDateTimeNowUtcOffsetFromUtc выглядит как:

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 вместо этого выглядит как:

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;
}

в конце концовGetCurrentOneYearLocal выглядит как:

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;
}

Интересная функцияGetTimeZoneInformationприсутствует вkernel32.dll который описан в документации как:

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

Для доступа к информации о времени Windows фактически используетIO доступ. Не уверен, что этоcan быть определенным как «блокирование», но это определенно влияет на системную информацию, сохраненную на диске, по крайней мере, на его части.

Во всяком случае, удивительно, что все происходит на такой активно используемой собственности, какDateTime.Now.
@TimSchmelter: на самом деле это те вопросы, на которые такие люди, как я, могут высказывать только предположения. Потому что только человек, которыйactually реализовал это в ОС Windows (чтоcan меняюсь, я себе представляю, между разными версиями) могу датьexact ответ.
@ Кодо: на самом деле это мой ответ :)
@Tigran: информация о часовом поясе рано или поздно будет кэширована. Но текущее время извлекается из чипа южного моста (или его эквивалента), и это требует блокирования ввода-вывода. Так что действительно интересная часть не в коде .NET, а вGetTimeZoneInformation.
@TimSchmelter: Итак, яsuppose что его читают с диска, учитывая также другую документацию, например, оDYNAMIC_TIME_ZONE где информация хранится в реестре, поэтому должна быть также считана из него. Что не означает, не говоря уже о том, что ОС может обналичить ее при запуске и прочитать ее из памяти (на самом деле, скорее всего, из некоторого файла, отображенного в память).
2

Если вы посмотрите на источник с каким-то отражателем, подобным инструменту DateTime.Now, вызовите Win APIGetSystemTimeAsFileTime и после этого он создает новый объект DateTime, используяконструктор которые имеют один параметр int64 с тиками с 1 января 0001 в 00: 00: 00.000. Здесь не видно ничего, что могло бы вызвать блокировку ввода-вывода, и об этом нет упоминания в документации GetSystemTimeAsFileTime.

Думаю, вы упустили, откуда на самом деле исходит текущее время: чип южного моста. Для доступа к нему требуется ввод-вывод и его блокировка.
ну ты прав, +1 за ответ
4

Никто до сих пор не ответил, откуда на самом деле исходит текущее время. Я не в курсе новейшей архитектуры ПК. Но несколько лет назадчасы реального времени был частью микросхемы вне процессора (южный мост). Таким образом, чтобы получить время, вы должны были выполнить некоторые операции ввода-вывода с этим чипом. (Это не доступ к диску, а операция ввода-вывода.)

И поскольку текущий процесс должен ждать ответа от часов, он блокирует ввод / вывод.

Так что этот человек на конференции был прав.

Похожие вопросы