tag:blogger.com,1999:blog-3940972473404160061.post7743805893471535403..comments2023-02-12T04:29:48.804-08:00Comments on Programming DIY / Программирование — это просто!: Миллисекундный таймер для Windows и UNIXАлександрhttp://www.blogger.com/profile/03980297457924475954noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-3940972473404160061.post-74417539554414011812010-06-14T16:21:01.556-07:002010-06-14T16:21:01.556-07:00QueryPerformanceFrequency глючит на многоядерных с...QueryPerformanceFrequency глючит на многоядерных системах и компах с активным энергосбережением. Первое решается с помощью SetThreadAffinityMask, второе похоже никак. Во втором случае PerformanceFrequency не является константой и может плавать в широких пределах.Unknownhttps://www.blogger.com/profile/01465090207432421404noreply@blogger.comtag:blogger.com,1999:blog-3940972473404160061.post-84175676643450586032009-04-06T14:20:00.000-07:002009-04-06T14:20:00.000-07:00Да, можно, некоторые юниксовые сигналы можно проиг...Да, можно, некоторые юниксовые сигналы можно проигнорировать, например, сигнал от сокета (SIGPIPE), а некоторые нельзя, например, SIGKILL. Особо прикольно, когда своего обработчика на SIGPIPE нет, и сигнал не проигнорирован. В этом случае при использовании сокетов программа будет падать, убитая SIGPIPE'ом. Поэтому в мире юникса принято внимательно относиться к сигналам.<BR/><BR/>Если взять просто ситуацию без контекста, то можно в таймере запретить какие-то сигналы. Но в большой программе лучше делать единую систему обработки сигналов.Александрhttps://www.blogger.com/profile/03980297457924475954noreply@blogger.comtag:blogger.com,1999:blog-3940972473404160061.post-20512430615704116872009-04-06T11:36:00.000-07:002009-04-06T11:36:00.000-07:00> В UNIX дело обстоит еще интереснее -- sleep()...> В UNIX дело обстоит еще интереснее -- sleep()<BR/>> может быть прерван сигналом<BR/>А блокировать сигнал от сокета нельзя?<BR/>Самое смешное, что я уже где-то года полтора читаю мануал по glibc.<BR/>Linux сдох, FreeBSD где-то установлена, но я на ней не сижу. Везде бардак. Поэтому всё как-то очень печально затормозилось.<BR/>И сейчас у меня открыта там "Обработка Сигнала", которую я так и не дочитал.<BR/><BR/>Сразу возник вопрос.<BR/>Т.е. "аппаратные" сигналы, не могут быть блокированы, как SIGKILL?<BR/>Или просто некорректно будет блокировать<BR/>сигналы в классе таймера?NULLhttps://www.blogger.com/profile/11100602326365775561noreply@blogger.comtag:blogger.com,1999:blog-3940972473404160061.post-16993104231549727912009-04-06T04:38:00.000-07:002009-04-06T04:38:00.000-07:00Даже если все тут кроссплатформенное, виндовая час...Даже если все тут кроссплатформенное, виндовая часть реализована по виндовым правилам, и если проблема с SetThreadAffinityMask существует, ее надо будет исправить.<BR/><BR/>По поводу Sleep() все верно. Параметр задает только минимальное время. В UNIX дело обстоит еще интереснее -- sleep() может быть прерван сигналом, например, от сокета, который получил новые данные. В этом случае время сна может быть меньше, чем задана параметром.Александрhttps://www.blogger.com/profile/03980297457924475954noreply@blogger.comtag:blogger.com,1999:blog-3940972473404160061.post-55621712851030164732009-04-06T04:09:00.000-07:002009-04-06T04:09:00.000-07:00Там, где// detect and compensate for performance c...Там, где<BR/>// detect and compensate for performance counter leaps<BR/><BR/>начинается метод получения миллисекунд.NULLhttps://www.blogger.com/profile/11100602326365775561noreply@blogger.comtag:blogger.com,1999:blog-3940972473404160061.post-49497602325281118852009-04-06T04:04:00.000-07:002009-04-06T04:04:00.000-07:00Фу, переглючило слегка. У вас же он кроссплатформе...Фу, переглючило слегка. У вас же он кроссплатформенный. Извиняюсь.<BR/><BR/>Но то, что конкретно к винде относится.<BR/>Сбоя может и не быть, но неточности.<BR/>Как насчёт Unix не знаю.<BR/><BR/>Как меня запарили эти таймеры!<BR/><BR/>Ещё, товарищи, написавшие OGRE, в том месте, где они выдают значение миллисекунд, делают какую-то хитрую проверку. Чтобы учесть некие "утечки производительности". Пока не разобрался что такое.<BR/><BR/>newTicks - число миллисекунд, полученное, почти аналогично вашей функции PreciseTimer::millisec().<BR/><BR/>Это при сбросе-запуске таймера:<BR/>// Query the timer<BR/>QueryPerformanceCounter(&mStartTime);<BR/>mStartTick = GetTickCount();<BR/><BR/>// detect and compensate for performance counter leaps<BR/>// (surprisingly common, see Microsoft KB: Q274323)<BR/>unsigned long check = GetTickCount() - mStartTick;<BR/>signed long msecOff = (signed long)(newTicks - check);<BR/>if (msecOff < -100 || msecOff > 100)<BR/>{<BR/> // We must keep the timer running forward :)<BR/> LONGLONG adjust = (std::min)(msecOff * mFrequency.QuadPart / 1000, newTime - mLastTime);<BR/> mStartTime.QuadPart += adjust;<BR/> newTime -= adjust;<BR/><BR/> // Re-calculate milliseconds<BR/> newTicks = (unsigned long) (1000 * newTime / mFrequency.QuadPart);<BR/>}<BR/><BR/>Да, и насчёт Sleep.<BR/><BR/>Из Рихтера:<BR/>'Система прекращает выделять потоку процессорное время на период, примерно равный заданному. Все верно: если Вы укажете остановить поток на 100 мс, приблизительно на столько он и "заснет", хотя не исключено, что его сон продлится на несколько секунд или даже минут болыше. Вспомните, Windows не является системой реального времени. Ваш поток может возобновиться в за данный момент, но это зависит от того, какая ситуация сложится в системе к тому времени.'<BR/><BR/>Ну, здесь это, видимо, некритично.NULLhttps://www.blogger.com/profile/11100602326365775561noreply@blogger.comtag:blogger.com,1999:blog-3940972473404160061.post-64975160318971604752009-04-06T03:12:00.000-07:002009-04-06T03:12:00.000-07:00NULL: Пока я не видел сбоя тестов на многопроцессо...<B>NULL</B>: Пока я не видел сбоя тестов на многопроцессорных и многоядерных системах. Надо будет погонять еще.<BR/><BR/>Спасибо за замечание.Александрhttps://www.blogger.com/profile/03980297457924475954noreply@blogger.comtag:blogger.com,1999:blog-3940972473404160061.post-18807953148015289472009-04-06T01:37:00.000-07:002009-04-06T01:37:00.000-07:00А как насчёт SetThreadAffinityMask?На многопроцесс...А как насчёт SetThreadAffinityMask?<BR/>На многопроцессорных и многоядерных системах как это будет выполняться?<BR/><BR/>Вот кусок из таймера OGRE:<BR/><BR/>unsigned long Timer::getMilliseconds()<BR/>{<BR/> LARGE_INTEGER curTime;<BR/><BR/> HANDLE thread = GetCurrentThread();<BR/><BR/> // Set affinity to the first core<BR/> DWORD oldMask = SetThreadAffinityMask(thread, mTimerMask);<BR/><BR/> // Query the timer<BR/> QueryPerformanceCounter(&curTime);<BR/><BR/> // Reset affinity<BR/> SetThreadAffinityMask(thread, oldMask);NULLhttps://www.blogger.com/profile/11100602326365775561noreply@blogger.comtag:blogger.com,1999:blog-3940972473404160061.post-13727107291081993212009-03-27T03:12:00.000-07:002009-03-27T03:12:00.000-07:00Здорово! Значит главный message был доставлен по н...Здорово! Значит главный message был доставлен по назначению.Александрhttps://www.blogger.com/profile/03980297457924475954noreply@blogger.comtag:blogger.com,1999:blog-3940972473404160061.post-89906775513602125382009-03-26T14:32:00.000-07:002009-03-26T14:32:00.000-07:00Спасибо, пригодился класс для программы, тестирующ...Спасибо, пригодился класс для программы, тестирующей алгоритмы сортировки.<BR/>Взял с вас привычку любить gTestAnonymoushttps://www.blogger.com/profile/17582465250811067980noreply@blogger.com