4203 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
1

Как узнать, сколько прошло времени с момента предыдущего вызова функции?

13.06.2012, 13:49. Показов 2153. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Функция отвечает, в том числе, за управление персонажем. Не желательно, чтоб у него от тормозов компа падала скорость, пусть лучше начинает двигаться чуть рывками. Или от большого числа сообщений окнам программы. Или просто то того, что много лишнего софта загружено и занимается какой нибудь реально-бесполезной работой. Нужен интервал времени с предыдущего вызова функции.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.06.2012, 13:49
Ответы с готовыми решениями:

Требуется узнать сколько времени прошло с момента завершения работы приложения
Моей программе необходимо при запуске знать, сколько времени прошло с последнего запуска. Есть ли...

Сколько прошло времени с заданного момента
Ребят помогите сделать такую штуку. Мне нужно чтобы я задавал время в таком виде: год, месяц,...

Сколько времени прошло с момента рождения
Нужно написать, чтобы после ввода даты и времени выдавал, что то типа: С момента рождения прошло 25...

Как узнать сколько прошло времени?
Приветствую всех:) Сразу к делу. Нужно реализовать такое: 1. Пользователь допустим жмет на...

5
106 / 106 / 11
Регистрация: 17.10.2010
Сообщений: 283
13.06.2012, 14:44 2
Прямого способа в OpenGL нет. Я обычно использую функции QueryPerformanceCounter и QueryPerformanceFrequency. Они позволяют написать достаточно точный таймер. Но можно попробовать и GetTickCount.
0
4203 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
13.06.2012, 14:55  [ТС] 3
QueryPerformanceCounter - бомба замедленного действия

Все примеры написаны с использованием библиотеки QT

Введение

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

Системные функции, которые непосредственно используются для получения времени/даты привязаны к часам Windows. Сообщение WM_TIMER не гарантирует точности, ядро может пропускать или объединять сообщения, если процессор перегружен.

Тут я вспомнил про чудесные функции QueryPerformanceCounter & QueryPerformanceFrequency. Эта пара считает временные интервалы по тактам процессора.

Требования к моей программе допускали небольшую неточность - часы могли отставать на пару секунд в сутки. А при частоте процессора в пару ГГц не было и речи о том, что часы будут идти неверно. В общем, эта пара API функций с лихвой перекрывала мои потребности. Кроме того, они сами по себе работают очень быстро, и, как утверждает Microsoft - они работают даже на многопроцессорных/многоядерных системах без ошибок. Желающие могут сами посчитать погрешность измерений.

Реализация

Реализация часов очень простая. При старте программы мы получаем "базовое время". В самом простом случае можно просто взять текущее время системы. Я загружал точное время с сервера через сеть. Одновременно с этим мы запоминаем значение счетчика тактов, который получаем вызовом QueryPerformanceCounter.

Когда нам надо считать текущее значение наших часов, мы опять считываем счетчик тактов процессора, переводим его в секунды или миллисекунды и добавляем к базовому времени.

QDateTime m_tmZerroTime = QDateTime::currentDateTime();
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
m_tmQP = li.QuadPart;

:.
QDateTime tmCurrent = QDateTime::currentDateTime();
LARGE_INTEGER _TC, _TF;
QueryPerformanceCounter(&_TC);
QueryPerformanceFrequency(&_TF);
QDateTime tmQC = m_tmZerroTime.addMSecs( 1000 * (_TC.QuadPart - m_tmQP) / _TF.QuadPart );
//tmQC Содержит значение наших часов
Очень просто, не правда ли? Значит продолжим.

Эти часы исправно проработали больше 3-х месяцев в готовой программе, а потом начались необъяснимые глюки. Некоторые пользователи стали жаловаться, что часы в программе отстают от часов в системе. Программа содержала огромное количество бизнес логики и поиски ошибки затянулись. Потом случайно заметили, что наши часы начинают врать на ноутбуках, когда их переводят на питание от батарейки. Тогда закралось подозрение на QueryPerformanceХХХ, хотя горячо любимый Майкрософт в МСДН утверждает, что частота тиков не меняется после старта системы.

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

До этого момента я считал, что это самый точный таймер, который есть в Windows. Вы можете скачать тестовое приложение здесь и проверить свою систему.

Ребята из MS не отрицают существование этой проблемы, хотя об этом нет не единого слова в документации на QueryPerformanceCounter & QueryPerformanceFrequency. По их мнению, счетчик тиков съезжает скачками (что видно в тестовом приложении) из-за багов (!?) в некоторых чипсетах. Мое мнение, что счетчик работает неверно, потому что современные процессоры могут менять свою частоту на лету, чтобы экономить энергию. Особенно это актуально для ноутбуков.
Может ли это проявляться в игре?
Одно из возможных решений проблемы - это использование GetTickCount(), чтобы обнаружить скачкообразное изменение счетчика и сделать коррекцию. Но тогда теряется вся идея точного измерения временных интервалов.

В моем случае я решил проблему очень просто. Я заменил QueryPerformanceXXXX на GetTickCount(). Последняя функция обеспечивает достаточную точность для моих целей, не подвержена скачкам и не привязана к системным часам. Получилось даже проще, чем было:

QDateTime m_tmZerroTime = QDateTime::currentDateTime();
DWORD m_tmTC = GetTickCount();

...

//tmTC содержит значение наших часов.
QDateTime tmTC = m_tmZerroTime.addMSecs( GetTickCount() - m_tmTC );
PS/ Вместо GetTickCount можно попробовать использовать функцию timeGetTime() - она более точная и на первый взгляд более стабильная.
Каково реальное разрешение GetTickCount? То есть может ли он считать интервалы меньше восемнадцатой доли секунды? Как часто он обновляется? Можно ведь раз в минуту давать приращение сразу на 60000.
0
106 / 106 / 11
Регистрация: 17.10.2010
Сообщений: 283
13.06.2012, 21:19 4
По первому пункту - может, но при аппаратной просадке тактовой частоты. В любом случае, точнее интервалы получить не удастся. Для моих задач (в том числе и игра была) эти таймера всегда работали прилично.
По второму пункту - GetTickCount сравнительно неточный. Но, опять-таки, при 20-30 fps мне его хватало. Кстати, timeGetTime - тоже вполне приличный вариант.
0
4203 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
14.06.2012, 07:00  [ТС] 5
Каково разрешение? GetTickCount и timeGetTime? Если он буден уходить 50 миллисекунд за тысячелетие, но обновляться 18 200 раз каждые 1000 секунд, то не годен. Даже функция, уходящая на секунду на минуту, но обновляемая каждые 10 миллисекунд лучше. Какова точность QueryPerformanceCounter и QueryPerformanceFrequency? Если уходят на секунду в час, то этого уже более, чем достаточно, а для положения Солнца будут отдельные часы, заглядывающие в системное время и синхронизируемые по интернету.
0
3245 / 1434 / 234
Регистрация: 26.02.2009
Сообщений: 7,463
Записей в блоге: 5
14.06.2012, 09:51 6
GetTickCount - не точный( 16мс в лучшем случае )
я за timeGetTime. Можно при старте приложения вызвать timeBeginPeriod(1); а при выходе timeEndPeriod(1); У меня хорошо работало.
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.06.2012, 09:51
Помогаю со студенческими работами здесь

Сколько времени прошло с момента выключения вентилятора до полной остановки
Вентилятор вращается с частотой 900 об/мин.После выключения вентилятор, вращаясь равнозамедленно,...

Как узнать сколько времени прошло между событиями
group.DataChanged += new Opc.Da.DataChangedEventHandler(group_DataChanged); Не могу сообразить...

Как узнать сколько времени прошло с последнего нажатия на клавишу
Какая функция в API (по-моемому) определяет сколько времени прошло с последнего нажатия клавиши на...

Сколько времени ( в секундах ) прошло с момента начала передачи данных из пункта А до их полного получения в пункте B?
Данные объёмом 50 Мбайт передаются из пункта А в пункта Б по каналу связи, обеспечивающему скорость...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru