Задержка на время меньше 1 мс

Тема в разделе "WASM.WIN32", создана пользователем Avalonec, 6 мар 2005.

  1. Avalonec

    Avalonec New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    111
    Адрес:
    Тула
    Люди!

    Используя Sleep, 1 мы добиваемся задержки в 1 мс. Вопрос как получить задержку меньше этого значения порядка в 10 раз и чтобы не жрала проценты CPU?

    Есть возможно решить данную проблему заданием n-ого числа тредов. Можно ли иначе?
     
  2. Chingachguk

    Chingachguk New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2002
    Сообщения:
    340
    меньше этого значения порядка в 10 раз



    Тогда это будет около 100 мкс. Вряд ли это получится из user-кода, учитывая, что (например) в 98-ой таймер шлепает примерно ~600 мкс.



    На форуме vingrad.ru недавно было обсуждение метода на основе rdtsc на основе определенной заранее частоты cpu. В любом случае практически любой код из user-mode имеет недостаток быть прерванным высокоуровневым сервисом.
     
  3. Sokol_2

    Sokol_2 New Member

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    23
    Адрес:
    South Africa
    >> Используя Sleep, 1 мы добиваемся задержки в 1 мс



    Используая Sleep, максимум, чего ты можешь добиться, это 10 мс, даже если напишешь

    Sleep( 1 ). Держи пару идей из моего source кода:



    Идея первая:



    void TestTimeDelay( DWORD wMs )

    {

    LARGE_INTEGER freq;

    LARGE_INTEGER count_start;

    LARGE_INTEGER count_end;

    LONGLONG count_dif;

    HANDLE hndl;





    hndl = GetCurrentThread();

    SetThreadPriority( hndl, THREAD_PRIORITY_TIME_CRITICAL );



    QueryPerformanceFrequency( &freq );

    QueryPerformanceCounter( &count_start );



    while ( 1 )

    {

    QueryPerformanceCounter( &count_end );

    count_dif = count_end.QuadPart - count_start.QuadPart;

    if ( count_dif >= freq.QuadPart / ( 1000 / wMs ))

    {

    break;

    }

    }



    SetThreadPriority( hndl, THREAD_PRIORITY_NORMAL );

    }



    Идея вторая:



    void CAvi::StartMmTimer()

    {

    m_lCurTime = AVIStreamStartTime( m_pAviStream );



    pPlay = this;



    timeBeginPeriod( 1 );



    m_hMmTimer = timeSetEvent( m_wDelay,

    0,

    TimerCallback,

    0,

    TIME_PERIODIC );

    }



    void CALLBACK TimerCallback(UINT, UINT, DWORD, DWORD, DWORD)

    {

    CAvi::pPlay->PaintStuff();

    }



    Дело было четыре года назад, так что я точно не помню, чтобы описать всё в деталях. Но точно помню, что первое было проверено на осциллографе, и задержка была РОВНО 1 Мс. Второе тоже работало чётко в качестве mulimedia timer. Так что дерзай.



    Удачи
     
  4. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Avalonec



    Напиши, для каких целей это нужно. Решения для общего случая afaik не существует - виндос не является ОС реального времени.





    Sokol_2 >




    Странно, у меня получается точность намного лучше.

    Или это для мастая? (хотя и там у тоже точность лучше. дааже под VMWare)





    Мультимедиа таймер не поможет:
    Код (Text):
    1.  
    2. timeBeginPeriod
    3. The timeBeginPeriod function sets the minimum timer resolution for an application
    4.  or device driver.
    5.  
    6. MMRESULT timeBeginPeriod(
    7.   UINT uPeriod  
    8. );
    9. Parameters
    10. uPeriod
    11. [b]Minimum timer resolution, in milliseconds[/b], for the application
    12.  or device driver.


    timeGetDevCaps возвращает TIMECAPS.wPeriodMin = 1





    Если звуковая карта поддерживает аппаратное микширование, то можно поиграться со звуковым буффером, но это не является решением для 100% случаев :-(
     
  5. Avalonec

    Avalonec New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    111
    Адрес:
    Тула
    Чтобы не быть прерванным просто необходимо поставить у родительского процесса самый высокий приоритет и у треда TIME_CRITICAL, таким образом можно добиться гарантированно задержки в 1 мс, что точно для приотрета равного 31.



    Мне нужно работать в некоторых участках кода значительно быстрее, чем в других, но в медленных участках кода и так уже стоит Sleep, 1, хотелось бы этот предел отодвинуть. Один из таких случаев: я работаю со множеством sock-потоков (для этой цели у меня написан отдельный модуль) и на localhoste получается скорость значительно выше если обработчик крутиться в прямом цикле без Sleep, но это и так понятно, самое главное проц грузится на 99%, а вот это не хорошо.



    Можно сделать многотредовостью. Но вопрос: сколько жрет у системы сам тред?
     
  6. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    >




    что бы не быть прерванным, этого не достаточно - юзерлендный код всегда работает на уровне IRQL PASSIVE_LEVEL, так что его может прервать почти что угодно. А для задержки в 1 мс imho хватит и 15го приоритета (но во всяких мастдаях вроде не всё так хорошо)



    >




    То есть основная задача - снизить видимую загрузку на проц?

    Можно попробовать Sleep(0), возможно в цикле с выходом по условию (но только не с THREAD_PRIORITY_TIME_CRITICAL).



    >




    если у тебя всего один трэд - используй несколько, ресурсов процессора это не отнимает.
     
  7. Avalonec

    Avalonec New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    111
    Адрес:
    Тула
    IRQL PASSIVE_LEVEL

    Да, это ты прав.

    А для задержки в 1 мс imho хватит и 15го приоритета (но во всяких мастдаях вроде не всё так хорошо)

    Как показывает практика временные задержки в винде сильно "плавают". И подобного уровня приоретета у меня не хватает.



    Задача, крутиться в цикле проверок как можно чаще, не отнимая значимого времени у проца.



    Sleep, 0 жрет 99%. Она может прокатить когда тредов с такимже уровнем в системе будет достаточно много, но это не подходит у каждого пользователя запущено определенное число задач.



    если у тебя всего один трэд - используй несколько, ресурсов процессора это не отнимает.

    Не один (5), но увеличить думаю можно.

    Тред жрет время самой системы - переключение задач, нитей и т.д. Вопрос в том как много?
     
  8. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Ну, переключение всё равно постоянно происходит - кол-во твоих потоков на это не влияет.

    И время переключения контекстов тоже не зависит от того, на какой конкретно поток переключается...



    Время работы самого планировщика как-то будет зависить от количества потоков, но этим imho можно пренебречь.

    Вот с кэшем сложнее, это может как-то влиять, но не думаю, что сильно.



    Хотя, это конечно всё мои измышлизмы :)
     
  9. Avalonec

    Avalonec New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    111
    Адрес:
    Тула
    Время работы самого планировщика как-то будет зависить от количества потоков, но этим imho можно пренебречь.



    Если они правда не переваливает за сотню. :)
     
  10. flankerx

    flankerx New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2004
    Сообщения:
    423
    Адрес:
    Moscow, Russia




    за сотню оно переваливает почти всегда :)



    у меня сейчас: процессов 41, потоков 453...
     
  11. Sokol_2

    Sokol_2 New Member

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    23
    Адрес:
    South Africa
    2 S_T_A_S



    Вышеупомянутый код прогонялся на Windows NT. Именно тогда я и столкнулся с этой проблемой: звал Sleep( 1 ), но задержка была в несколько раз больше. Может, сейчас Мелкософт ету проблему как-то пофиксил. Но верить им... эх, сам знаешь...
     
  12. Avalonec

    Avalonec New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    111
    Адрес:
    Тула
    у меня сейчас: процессов 41, потоков 453...

    Ты в своей программе попробуй 100 создать и загрузить как-нить, в этом то и дело. Все эти потоки прозябают в бездействии.



    Вышеупомянутый код прогонялся на Windows NT. Именно тогда я и столкнулся с этой проблемой: звал Sleep( 1 ), но задержка была в несколько раз больше. Может, сейчас Мелкософт ету проблему как-то пофиксил. Но верить им... эх, сам знаешь...

    Она и сейчас минимум в 10 раз больше.
     
  13. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Код (Text):
    1. CPU AuthenticAMD at 1666 MHz
    2. running Windows NT 5.1.2600 Service Pack 2
    3. Sleep(1) time = 1943 microseconds
    4. Sleep(1) time = 1954 microseconds
    5. Sleep(1) time = 1952 microseconds
    6. Sleep(1) time = 1955 microseconds
    7. Sleep(1) time = 1954 microseconds
    8. Sleep(1) time = 1953 microseconds
    9. Sleep(1) time = 1954 microseconds
    10.  
    11. CPU AuthenticAMD at 1666 MHz
    12. running Windows 4.10.2222  A
    13. Sleep(1) time = 2571 microseconds
    14. Sleep(1) time = 957 microseconds
    15. Sleep(1) time = 1248 microseconds
    16. Sleep(1) time = 1123 microseconds
    17. Sleep(1) time = 1570 microseconds
    18. Sleep(1) time = 1008 microseconds
    19. Sleep(1) time = 886 microseconds
    20.  
    21. CPU AuthenticAMD at 1666 MHz
    22. running Windows 4.0.1111  B
    23. Sleep(1) time = 894 microseconds
    24. Sleep(1) time = 1003 microseconds
    25. Sleep(1) time = 1049 microseconds
    26. Sleep(1) time = 937 microseconds
    27. Sleep(1) time = 997 microseconds
    28. Sleep(1) time = 990 microseconds


    2 последних теста выполнены под VMWare, так что точность не слишком хорошая.

    Исходники и экзешник теста - в аттаче.



    Как вы получили
    ?! Аргументы вроде
    imho тоже самое, что "раньше был и метр больше, и килограм тяжелее" :derisive:

    [​IMG] _793401770__sleep_test.zip
     
  14. Avalonec

    Avalonec New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    111
    Адрес:
    Тула
    S_T_A_S_

    Действиельно, задержка больше примерно в два раза.

    Такая серьезная погрешность закралась в расчеты, как оказалось, из-за активного использования процедур винды.

    Дело в том, что в треде я сделал обработку объектов-точек, которые двигались по экрану, отрисовка делалась посылкой WM_PAIN.





    Может кому пригодится версия на masm'е - attach.

    [​IMG] _1711162765__Sleep_time.rar
     
  15. Oleg_SK

    Oleg_SK Guest

    Публикаций:
    0
    S_T_A_S_

    А на моей машине твоя программка показала такой результат.
     
  16. Oleg_SK

    Oleg_SK Guest

    Публикаций:
    0
  17. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Пришлось мне тоже установить какую-то виндос 2000, совсем без сервиспаков (судя по билду вроде не бета), результаты такие:



    CPU AuthenticAMD at 1666 MHz

    running Windows NT 5.0.2195

    Sleep(1) time = 15623 microseconds

    Sleep(1) time = 15625 microseconds

    Sleep(1) time = 15600 microseconds

    Sleep(1) time = 15633 microseconds

    Sleep(1) time = 15627 microseconds

    Sleep(1) time = 15631 microseconds

    Sleep(1) time = 15637 microseconds



    наверное, не зря микрософт сервиспаки делает :derisive:
     
  18. Maxi

    Maxi New Member

    Публикаций:
    0
    Регистрация:
    3 янв 2004
    Сообщения:
    23
    Адрес:
    Russia/Moscow
    Реальная 98SE без всяких там виртуалок на P3-1000CPU GenuineIntel at 1000 MHz

    running Windows 4.10.2222 A

    Sleep(1) time = 997 microseconds

    Sleep(1) time = 991 microseconds

    Sleep(1) time = 997 microseconds

    Sleep(1) time = 1001 microseconds

    Sleep(1) time = 1001 microseconds

    Sleep(1) time = 996 microseconds

    Sleep(1) time = 1003 microseconds

    Sleep(1) time = 996 microseconds

    Sleep(1) time = 998 microseconds

    Sleep(1) time = 997 microseconds

    Sleep(1) time = 1001 microseconds

    Sleep(1) time = 1003 microseconds

    Sleep(1) time = 985 microseconds

    Sleep(1) time = 1008 microseconds

    Sleep(1) time = 996 microseconds

    Sleep(1) time = 1003 microseconds

    Sleep(1) time = 987 microseconds

    Sleep(1) time = 997 microseconds

    Sleep(1) time = 1007 microseconds

    Sleep(1) time = 994 microseconds



    XP - хлам.
     
  19. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035




    По моему от сервиспака мало что зависит, это получено на реальной машине:

    CPU AuthenticAMD at 1206 MHz

    running Windows NT 5.1.2600 Service Pack 2

    Sleep(1) time = 15594 microseconds

    Sleep(1) time = 15620 microseconds

    Sleep(1) time = 15637 microseconds

    Sleep(1) time = 15630 microseconds

    Sleep(1) time = 15634 microseconds

    Sleep(1) time = 15637 microseconds
     
  20. TarasCo

    TarasCo New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2005
    Сообщения:
    106
    Тест не корректный. Все зависит от присутствия/остутсвия других активных тредов и их приоритетов. Если в системе есть другой активный тред, то при вызове Sleep(1) планировщик отдаст ему временной слайс, величина которого зависит от системы. Для серверов это может быть 50мс например.