Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Жизнь по таймеру. Win Fight

7.1K
27 апреля 2005 года
miXme
44 / / 10.04.2005
Как я уже писал здесь, работаю с таймером ядра win nt.
И вот, уже совершенно отчаявшись достичь заветных 20 мс периода срабатывания таймера на стендовом компе, я узрел, что частота аппаратного (100нс-го) таймера равна не 1, а 3.5 МГц (раньше, во время преобразования тиков в секунды, я делил разность времён входа в процедуру обработки от таймера на жестко вбитое число - 1193182(1МГц)). Решив узнать какая частота аппаратного таймера у моего офисного компа, я с удивлением обнаружил, что и там 3.5 МГц. После исправления, решил запустить на офисном компьютере тестовую прогу и...о чудо !!!! Период в 20 мс стабильно отрабатывался.
Ну после этого конечно бааазар вокзал, всеобщее вау.... В общем, до стендового компа я добрел тока на следующий день. Каково же было мое разочарование, когда этот стервец :)(компутер) выдал мне прежние 31 мс, вместо 20. Я был в ШОКЕ.......

...Немного придя в себя, решил провести у нас на фирме тестирование на нескольких разных машинах, запостив соответствующую тему в местной рассылке. В итоге из 10 тестеров 8 прошли тест на 5 балов, а 2 его не прошли, В ТОЧНОСТИ ПОВТОРИВ результаты времени срабатывания таймера стендового компа. А именно.
Задано - 30мс, отрабатывает 31мс. Задано 20 мс - отрабатывает 31мс, задано 10мс - отрабатывает 15 мс. Интересно то, что хотя время срабатывания не верное, однако оно держится СТАБИЛЬНО и НЕ СКАЧИТ!
В общем сделал кучу логов. Если кто заинтересуется, залью.

Фууу. Сори за обилие невнятного текста, однако я не писатель шоб краси ВО! :)

Теперь собственно вопросЫ:

1. Необходимо определить сущность проблемы. Аппаратура (неаккуратный таймер, мамка, чипсет...) или ПО (оська, ее дрова, службы..).

2. Если нет 100% предположений :) , то надо хотя бы идею, где рыть, чего сравнивать? Может у кого такая шняга была.

3. Если у вас были какие либо проблемы вообще с Waitable Timer - пишите, может чего надумаем вместе.

З.Ы. Прилогаю архив тестовой программы, пишушей в лог результаты отработки таймера на разных интервалах. Может кто рискнет затестить, буду благодарен за помощь.
10
27 апреля 2005 года
Freeman
3.2K / / 06.03.2004
Цитата:
Originally posted by miXme
что частота аппаратного (100нс-го) таймера равна не 1, а 3.5 МГц (раньше, во время преобразования тиков в секунды


Гм, у меня тоже. :)

А вообще твои тесты чертовщиной попахивают, наверняка что-то неправильно делаешь.

7.1K
28 апреля 2005 года
miXme
44 / / 10.04.2005
Цитата:
Originally posted by Freeman
Гм, у меня тоже. :)

А вообще твои тесты чертовщиной попахивают, наверняка что-то неправильно делаешь.



Понимаешь, если бы я и писал и тестировал в одиночку, тогда ясно. Однако, в этот раз учавствовали 10 бэта тестеров. Их результаты показывают, что таймер может держать 20 мс в определенной конфигурации (аппаратной или программной - пока не знаю).

Программа для теста СПЕЦИАЛЬНО взята из MSDN (Using a Waitable Timer with an Asynchronous Procedure Call) и дополнена куском кода для замера времени срабатывания таймера.

Чтобы не быть голословным, сегодня вечером выложу исходник...

292
28 апреля 2005 года
Matush
726 / / 14.01.2004
у меня вышло
для 30 среднее 30.30 ms +- 0.05 (на глаз)
для 20 среднее 20.50 ms +- 0.05 (на глаз)
для 10 среднее 10.73 ms +- 0.02 (на глаз)

OS: WinXP Prof Sp2
CPU: P-IV 1,5 GHz
7.1K
28 апреля 2005 года
miXme
44 / / 10.04.2005
Цитата:
Originally posted by Matush
у меня вышло
для 30 среднее 30.30 ms +- 0.05 (на глаз)
для 20 среднее 20.50 ms +- 0.05 (на глаз)
для 10 среднее 10.73 ms +- 0.02 (на глаз)

OS: WinXP Prof Sp2
CPU: P-IV 1,5 GHz



Спасибо за участие!
Кстати, у тебя тест прошел успешно.

Вот исходник этой проги (немного дополненный пример из МСДН - см. мой пост выше):

***************************************

// wtimer.c by miXme, 2005

#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <stdio.h>

#define _SECOND 10000000

char list[ 1024000 ];
char txt[ 1024 ];
LARGE_INTEGER qFreq;
LARGE_INTEGER t0, t1;

VOID CALLBACK TimerAPCProc(
LPVOID lpArg, // Data value
DWORD dwTimerLowValue, // Timer low value
DWORD dwTimerHighValue ) // Timer high value

{
// some job
}

void main( int argc, char * argv[] )
{
HANDLE hTimer;
BOOL bSuccess;
__int64 qwDueTime;
LARGE_INTEGER liDueTime;
TCHAR szError[255];
int id;
int pTime;
int loopLim;
__int64 dif_counts;
float dif_ms;

// Parse command line
switch( argc )
{
case 1:
pTime = 1000;
loopLim = 10;
break;

case 2:
pTime = atoi( argv[ 1 ] );
loopLim = 10;
break;

case 3:
pTime = atoi( argv[ 1 ] );
loopLim = atoi( argv[ 2 ] );
break;
}

printf( "\nSet timer interval to < %d > ms...", pTime );
memset( list, 0, sizeof( list ) );
memset( txt, 0, sizeof( txt ) );

if( QueryPerformanceFrequency( &qFreq ) )
{
printf( "\nFrequency in counts is: %ld", qFreq.QuadPart );
}
else
{
printf( "\nYour hardware not supported high-resolution performance counter !" );
return;
}
t0.QuadPart = 0;
t1.QuadPart = 0;

if ( hTimer = CreateWaitableTimer(
NULL, // Default security attributes
FALSE, // Create auto-reset timer
NULL ) ) // Name of waitable timer
{
__try
{
// Create an integer that will be used to signal the timer
// 2 seconds from now.
qwDueTime = -2 * _SECOND;

// Copy the relative time into a LARGE_INTEGER.
liDueTime.LowPart = (DWORD) ( qwDueTime & 0xFFFFFFFF );
liDueTime.HighPart = (LONG) ( qwDueTime >> 32 );

bSuccess = SetWaitableTimer(
hTimer, // Handle to the timer object
&liDueTime, // When timer will become signaled
pTime, // Periodic timer interval of 2 seconds
TimerAPCProc, // Completion routine
NULL, // Argument to the completion routine
FALSE ); // Do not restore a suspended system

if ( bSuccess )
{
printf( "\nProccesing" );
for ( id = 0 ; id < loopLim ; id++ )
{
SleepEx(
INFINITE, // Wait forever
TRUE ); // Put thread in an alertable state

printf( "." );
if( QueryPerformanceCounter( &t1 ) )
{
dif_counts = t1.QuadPart - t0.QuadPart;
dif_ms = (float) dif_counts / (qFreq.QuadPart / 1000 );
sprintf( txt, "\n---\n%d. elapsed %ld counts", id, dif_counts );
strcat( list, txt );
sprintf( txt, " or %.4f ms", dif_ms );
strcat( list, txt );
t0.QuadPart = t1.QuadPart;
}
else
{
sprintf( txt, "\nQueryPerformanceCounter FAIL !!!" );
strcat( list, txt );
}

}
printf( "\n%s\n", list );
}
else
{
wsprintf( szError, "SetWaitableTimer failed with Error %d.", GetLastError() );
MessageBox( NULL, szError, "Error", MB_ICONEXCLAMATION );
}

}
__finally
{
CloseHandle( hTimer );
}
}
else
{
wsprintf( szError, "CreateWaitableTimer failed with Error %d.", GetLastError() );
MessageBox( NULL, szError, "Error", MB_ICONEXCLAMATION );
}
}

***************************************

Делаю bcc32 wtimer.c
Получаю исполняемый файл wtimer.exe

Офисный ПК: Win2k+SP4, Celeron 1.3 GHz
Запускаю wtimer 20 20
Получаю...
Set timer interval to < 20 > ms...
Frequency in counts is: 3579545
Proccesing....................

---
elapsed -993756366 counts or 27323412.000000 ms
---
elapsed 73387 counts or 20.504890 ms
---
elapsed 73395 counts or 20.507124 ms
---
elapsed 73391 counts or 20.506008 ms
---
elapsed 73399 counts or 20.508242 ms
---
elapsed 73415 counts or 20.512712 ms
---
elapsed 73411 counts or 20.511595 ms
---
elapsed 73393 counts or 20.506567 ms
---
elapsed 73403 counts or 20.509359 ms
---
elapsed 73416 counts or 20.512993 ms
---
elapsed 73392 counts or 20.506287 ms
---
elapsed 73416 counts or 20.512993 ms
---
elapsed 73425 counts or 20.515507 ms
---
elapsed 73401 counts or 20.508801 ms
---
elapsed 73403 counts or 20.509359 ms
---
elapsed 73414 counts or 20.512434 ms
---
elapsed 73396 counts or 20.507404 ms
---
elapsed 73387 counts or 20.504890 ms
---
elapsed 73423 counts or 20.514948 ms
---
elapsed 73397 counts or 20.507683 ms

Стендовый ПК: Win2k+SP4, Celeron 1.7 GHz
Делаю wtimer 20 20
Получаю...
Set timer interval to < 20 > ms...
Frequency in counts is: 3579545
Proccesing....................

---
elapsed -28174630 counts or 27593202.000000 ms
---
elapsed 111929 counts or 31.273819 ms
---
elapsed 111750 counts or 31.223806 ms
---
elapsed 111861 counts or 31.254820 ms
---
elapsed 111862 counts or 31.255098 ms
---
elapsed 113155 counts or 31.616373 ms
---
elapsed 110556 counts or 30.890192 ms
---
elapsed 111856 counts or 31.253424 ms
---
elapsed 111946 counts or 31.278570 ms
---
elapsed 111772 counts or 31.229952 ms
---
elapsed 111887 counts or 31.262085 ms
---
elapsed 111830 counts or 31.246159 ms
---
elapsed 111859 counts or 31.254261 ms
---
elapsed 111857 counts or 31.253702 ms
---
elapsed 111870 counts or 31.257334 ms
---
elapsed 111985 counts or 31.289467 ms
---
elapsed 111722 counts or 31.215982 ms
---
elapsed 111855 counts or 31.253143 ms
---
elapsed 111858 counts or 31.253981 ms
---
elapsed 111985 counts or 31.289467 ms

////////////////////////////////////////////////

В итоге на офисном тест проходит успешно, а на стендовом нет!

P.S. Уже подумываю написать в поддержку Microsoft (на оську есть лицензия)....$-)

7.1K
28 апреля 2005 года
miXme
44 / / 10.04.2005
Сори, помоему исходник стал не читаемым, выкладываю отдельно...
253
10 мая 2005 года
Proger_XP
1.5K / / 07.08.2004
Цитата:
Originally posted by miXme
Уже думаю писать в поддержку Microsoft


MicroSoft тут не причем
Я недавно читал, что старые(~1300MHz и меньше) процессоры делают что-то со своей частотой и частотой шины
Новые же процы считают количество циклов
Из-за этого еще старые игры, которые юзают таймера, на новых работают намного быстрее
Суть в том, что новый метод повышает точность таймера и не зависит от частоты

Похоже, тебе придется определять частоту проца и на старых юзать ~15 Ms, а на новых 20 Ms ))

7.1K
12 мая 2005 года
miXme
44 / / 10.04.2005
Цитата:
Originally posted by Proger_XP
MicroSoft тут не причем



Все так говорят ;), пока не начнут писать системные проги, тесно завязанные на возможностях оси...

Цитата:

Я недавно читал, что старые(~1300MHz и меньше) процессоры делают что-то со своей частотой и частотой шины



Подкинь плиз ссылочку если можешь...

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

...В общем чувствую тема огромна и потому ее надо закрывать или переводить в новый пост (может на выходных), и вот по чему...
После долгих мытаврств, удалось связать периодичность работы таймера с квантом времени, выделяемым планировщиком оси для потока выполнения. Однако результаты тестов пока не полны и не однозначны. Думаю позже подниму эту тему в новой формулировке.

Мораль. Чтобы зарОбатывать мНого денех (при этом имея среднии познания в системе, шоб не напрягаться :) ) - НЕ надо писать 100% корректно работающие программы!!! На своем (теперь уже личном :) ) опыте убедился, что для написания оптимизированных и действительно корректно работающих программ нужно ОЧЕНЬ много времени уделять системе и программированию в ней. А поскольку все мы живые люди (надо же когда-то и коньячку попить с любимой девушкой) такое можно осуществить только работая узким специалистом. Такую работу довольно трудно найти, всем нужны полиглоты программизма :).

З.Ы. На последок хочется сказать людям, которые попытаются оспорить мое мнение (я не не против других мнений, вдруг чего не знаю о жизне программера - поделитесь!), говоря что все прекрасно работает и при этом не надо париться по 10 ч в день за компом. Ребята, меньше знаешь - лучше спишь :) ...

253
13 мая 2005 года
Proger_XP
1.5K / / 07.08.2004
Цитата:
Originally posted by miXme
Подкинь плиз ссылочку если можешь....


Книга Пирогов "Asm в Windows"
Или еще чхя-та книга тоже про "Asm"(16-бит)

5.5K
13 мая 2005 года
Ded pendos
40 / / 13.05.2005
А, я чет не совсем понял тебе нужен минимальный показатель таймера или просто, чтоб он срабатовал на 20 мсек
7.1K
15 мая 2005 года
miXme
44 / / 10.04.2005
Цитата:
Originally posted by Ded pendos
А, я чет не совсем понял тебе нужен минимальный показатель таймера или просто, чтоб он срабатовал на 20 мсек



Необходимо, что бы Waitable Timer срабатывал СТАБИЛЬНО каждые 20 мс.

З.Ы. Как я уже не раз подчеркивал. Не на всех машинах такое прокатывает... см посты выше...

2.4K
17 мая 2005 года
nihil
56 / / 28.02.2004
Если тебе интересно...
Машина - Duron 1100, WinXP pro sp2

Set timer interval to < 20 > ms...
Frequency in counts is: 3579545
Proccesing....................

---
0. elapsed -79281940 counts or 35979252.0000 ms
---
1. elapsed 73393 counts or 20.5066 ms
---
2. elapsed 73403 counts or 20.5094 ms
---
3. elapsed 73380 counts or 20.5029 ms
---
4. elapsed 73393 counts or 20.5066 ms
---
5. elapsed 73406 counts or 20.5102 ms
---
6. elapsed 73879 counts or 20.6424 ms
---
7. elapsed 72901 counts or 20.3691 ms
---
8. elapsed 73410 counts or 20.5113 ms
---
9. elapsed 73411 counts or 20.5116 ms
---
10. elapsed 73407 counts or 20.5105 ms
---
11. elapsed 73355 counts or 20.4959 ms
---
12. elapsed 73400 counts or 20.5085 ms
---
13. elapsed 73392 counts or 20.5063 ms
---
14. elapsed 73392 counts or 20.5063 ms
---
15. elapsed 73403 counts or 20.5094 ms
---
16. elapsed 73416 counts or 20.5130 ms
---
17. elapsed 73375 counts or 20.5015 ms
---
18. elapsed 73401 counts or 20.5088 ms
---
19. elapsed 73377 counts or 20.5021 ms
253
17 мая 2005 года
Proger_XP
1.5K / / 07.08.2004
Цитата:
Originally posted by nihil
Если тебе интересно...
Машина - Duron 1100, WinXP pro sp2


А на моей - AMD Duron 2000+ (1350 Mhz), но с WindowsXP SP1 - 25 Ms

MiXMe , похоже дело в SP1 и SP2
P.S.: Ты юзаешь API или ASM?

2.4K
17 мая 2005 года
nihil
56 / / 28.02.2004
[QUOTE]Originally posted by Proger_XP
А на моей - AMD Duron 2000+ (1350 Mhz), но с WindowsXP SP1 - 25 Ms

Так ты думаешь, все же что дело в оси?.. хм... Но miXme ж тестил на разных тачанах, но с одинаковой оской %)
2.4K
17 мая 2005 года
nihil
56 / / 28.02.2004
Цитата:
Originally posted by Proger_XP
А на моей - AMD Duron 2000+ (1350 Mhz), но с WindowsXP SP1 - 25 Ms
MiXMe, похоже дело в SP1 и SP2...



Proger_XP, так ты все же думаешь, что дело в оси?.. хм... не знаю... miXme ж тестил на разных машинах, но с одинаковой оской %)

253
19 мая 2005 года
Proger_XP
1.5K / / 07.08.2004
Цитата:
Originally posted by nihil
Proger_XP, так ты все же думаешь, что дело в оси?.. хм... не знаю... miXme ж тестил на разных машинах, но с одинаковой оской %)


Похоже в SP2 что-то исправлено с таймером
Вообще, для таких целей нужно юзать асм, он даст намного большую скорость и точность

356
24 мая 2005 года
molnij
159 / / 20.06.2000
хм, немного в сторону вопрос.
а использование Waitable-таймера чем-то определено?
просто мультимедиа-таймер исправно тикает через нужный интервал(5,20,30 с погрешностью ~0.5 мс), при этом Waitable-таймер работает некорректно(тоесть 31 вместо 20, а точнее по ~15,5мс шагу)
машина 3200Barton, WinXP (без паков)
253
25 мая 2005 года
Proger_XP
1.5K / / 07.08.2004
Цитата:
Originally posted by molnij
машина 3200Barton, WinXP (без паков)


Опять же: частота разная, а SP2 нет - и появляются глюки

7.1K
31 июля 2006 года
miXme
44 / / 10.04.2005
В коем-то веке забрел на ентот форум...ща уже под Винды не програмлю , а програмлю под qnx/ там меня таймер устраивает :-)
Ну да ладно...по теме. Разобрался я значит с этой хренью в итоге. И решил ситуацию так (для вин приложения). В основном потоке меняю его приоритет на НИЖЕ_НОРМАЛЬНОГО или еще ниже. После чего создаю второй поток, которому присваиваю приоритет ТАЙМ_КРИТИКАЛ .Второй поток состоит из цикла, в котором по WaitSingleObject жду срабатывания Waitable taimer/ Причем задаю срабатывание каждую итерацию, тоесть не пользуюсь создание APC обработчика.
Оська живет в дискретном тике времени и поэтому у меня получались вышеуказанные значения. Какой устаналивается минимум для тика зависит от ХАЛа (как его установить - до этого я не дошел, но как понял ...и такое возможно ;-) ), который настраивается при установке оси на комп.
Есть пример реализации Waitable Timer, если кому нужон пишите на osdrummer собаченцыя cheerful точка com.
Удачи!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог