Рваное время в вин 11

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Рваное время в вин 11

Сообщение Сквозняк » 16.08.2025 07:55:03

В десятке скорее всего тоже самое, потому что глюки у программы те же самые - замедление некоторых действий, зависимых от времени в миллесекундах. Предполагаю, что из-за ниже описанной "фичи" где-то происходит рассинхронизация способов учёта времени. Слепил тестовый код:
Код: Выделить всё
Uses sysutils;

Var
Q64,W64: INT64;
Q2,W2: LONGINT;

LABEL
1,2;

FUNCTION DSF: INT64;
VAR
MS : Comp;
BEGIN
MS:=TimeStampToMSecs(DateTimeToTimeStamp(Now));
DSF:=TRUNC(MS);
END;
       

Begin
Q64:=DSF;
Q2:=0;
1:
W64:=DSF;
IF Q64<>W64 THEN BEGIN
   WRITELN(W64);
   Q64:=W64;
   INC(Q2);
   IF Q2>1000 THEN GOTO 2;
                 END;
GOTO 1;
2:
End.

В линуксе результат нормальный, все числа увеличиваются строго на единицу, а в 11 (пока протестировал только из под vmware чтобы не перезагружаться) имеем такой разброс в выхлопе:
Код: Выделить всё
63891009454648
63891009454651
63891009454652
63891009454655
63891009454657
63891009454660
63891009454661
63891009454663
63891009454665
63891009454666
63891009454669
63891009454670
63891009454672
63891009454673
63891009454676
63891009454677
63891009454678
63891009454680
63891009454683
63891009454685
63891009454688
63891009454689
63891009454691
63891009454692


Вроде бы приложение в винде это как-то может сделать как в линуксе.

Добавлено спустя 11 часов 29 минут 21 секунду:
Как оказалось эта фича торможения программ ради нескольких, которые умеют с этим бороться (интересный метод разделения ресурсов компа - как винда, так и несчастье), обнаружилась ещё в десятке - чистой, без отключения дряни, просто без интернета :mrgreen: Там разброс чисел был 15-16. Нашёл что нужно в программе подкручивать, чтобы программа работала нормально и в новых виндах, и рваное время не складывалось. Цитата исправленая для fpc:
Что такое точность Sleep?

Функция Sleep в Windows задерживает выполнение потока на указанное количество миллисекунд. Однако на практике точность задержки может быть не идеальной из-за того, что Windows использует таймеры с фиксированной разрешением по умолчанию. Это может привести к тому, что задержка окажется больше или меньше ожидаемой. Виртуальные машины (VM) могут усугубить эту проблему, так как их таймеры могут быть ещё менее точными.
Использование TimeBeginPeriod

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

Пример использования TimeBeginPeriod:

Код: Выделить всё
uses
Windows, mmsystem;

TimeBeginPeriod(1); // Устанавливаем разрешение таймера на 1 миллисекунду

TimeEndPeriod(1); // Возвращаем разрешение таймера по умолчанию


Не всё протестировал, но польза от этого кода есть.
Сквозняк
энтузиаст
 
Сообщения: 1136
Зарегистрирован: 29.06.2006 22:08:32

Re: Рваное время в вин 11

Сообщение Снег Север » 17.08.2025 07:10:53

Не понимаю, в чём претензия. Да, это так работает и об этом всех честно предупреждают. Если топикстартер ожидал чего-то другого, то это - его личные проблемы. В играх используют специальный мультимедиа-таймер с высокой точностью. Никто не запрещает его использовать в других приложениях вместо того, что предъявлять какие-то нелепые претензии.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 3058
Зарегистрирован: 27.11.2007 16:14:47

Re: Рваное время в вин 11

Сообщение WAYFARER » 17.08.2025 14:57:01

Снег Север, с одной стороны да. С другой стороны все же к реализации есть вопросы.

Сквозняк, если нужна точность, то начиная с Win 10 появился High-Resolution Waitable Timer.

В приложении готовый класс на паскале. Использование:


Код: Выделить всё

uses
  SysUtils, Windows, HiResTimer;

var
  Timer: THiResTimer;

// Эта процедура будет вызываться по таймеру
procedure OnTick(Sender: TObject);
var
  t: SYSTEMTIME;
begin
  GetLocalTime(t);

  Writeln(Format('%0.2d:%0.2d:%0.2d.%0.3d',
    [t.wHour, t.wMinute, t.wSecond, t.wMilliseconds]));
end;

begin
  Timer := THiResTimer.Create;
  try
    // Устанавливаем частоту срабатывания в Герцах
    // Например, 2 Гц = 2 раза в секунду = период 500 мс
    Timer.FrequencyHz := 2.0;

    // Можно также использовать:
    // Timer.PeriodMillis := 500;   // то же самое
    // Timer.PeriodSeconds := 0.5;  // тоже самое
    // Короткий "спин" перед дедлайном для уменьшения джиттера
    Timer.SpinMicros := 150;

    // Если это GUI-программа — ставим True, чтобы OnTick выполнялся в главном потоке
    Timer.SynchronizeToMainThread := False;

    // Назначаем обработчик
    Timer.OnTick := @OnTick;

    // Запускаем таймер
    Timer.Start;
    Writeln('Таймер запущен с частотой 2 Гц . Нажмите Enter для остановки.');

    Readln;

    // Останавливаем
    Timer.Stop;
  finally
    Timer.Free;
  end;
end.


Кратко о преимуществах:
Использует High-Resolution Waitable Timer (Win10 1803+), разрешение суб-мс.
Не меняет глобальную резолюцию ОС (в отличие от timeBeginPeriod), поэтому не повышает расход энергии всей системы, значительно меньше влияет на производительность (если аккуратно, так как при увеличении частоты нагрузка на CPU все равно будет расти)
Каждый тик рассчитывается от базового времени через QPC, потому нет накопления дрейфа.
Можно задавать период в микросекундах, миллисекундах, секундах или частоту в Герцах.
Событие OnTick можно получать в рабочем потоке или через Synchronize в главном потоке.

Добавлено спустя 15 минут 29 секунд:
Снег Север писал(а):В играх используют специальный мультимедиа-таймер с высокой точностью

Имхо, плохая идея, колбэки приходят из другого потока (WinMM) и у тебя будет постоянный context switch, а ещё, чтобы мультимедиа-таймер работал точно, нужно вызвать timeBeginPeriod(1), а
это заставляет всю систему тикать с шагом 1 мс, а это рост общей нагрузки и энергопотребления. А самое неприятно то, что даже если ты явно запросил 1мс, то никто тебе не гарантирует такую точность, она будет прыгать в пределах 2-3мс как минимум.

Добавлено спустя 52 минуты 14 секунд:
Сквозняк писал(а):В линуксе результат нормальный, все числа увеличиваются строго на единицу


Там это реализовано иначе, в Linux таймеры используют аппаратные источники и точность ограничена аппаратным таймером и планировщиком, а не глобальным системным тиком.
nanosleep(1 ms) реально лаёт 1 мс, и никак не влияет на всю систему. К слову, в совсем старых ядрах таймеры работали как в Windows, но еще в начале 00-х проблему решили, а MS ее решила только в 2018.

Снег Север писал(а):Да, это так работает и об этом всех честно предупреждают.

Вроде бы да, справедливо, но это доставляет гору проблем в кроссплатформенной разработке. Настолько, что один и тот же софт превращается в 2 продукта каждый со своей кодовой базой. Чего только стоят такие "особенности" сетевого стэка Windows, например TCP/IP с теми же самыми таймерами с глобальным системным тиком.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 544
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Рваное время в вин 11

Сообщение sts » 17.08.2025 18:19:04

WAYFARER писал(а):С другой стороны все же к реализации есть вопросы.

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

в данном случае надо просто делать алгоритм независимым от стабильности дельты между тиками, лет тридцать так делают уже
sts
постоялец
 
Сообщения: 474
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Re: Рваное время в вин 11

Сообщение WAYFARER » 17.08.2025 19:09:13

sts писал(а):нет никаких вопросов, эти таймеры не должны быть точными, за точными таймерами надо идти в операционные системы реального времени, их, буквально, специально для этого проектируют

"Для этого" это для чего? На вскидку - серверы, игры, VoIP, мультимедия и так далее, здесь точность очень важна.
В *nix системах таймеры дают задержку в районе 1 микросекунды, в windows 15 миллисекунд (1 мс с timeBeginPeriod(1), но тут будут другие проблемы и по большому счету проблемы не решает).
Начиная с Windows 10 проблема решена, теперь таймеры дают такую же задержку.

sts писал(а):в данном случае надо просто делать алгоритм независимым от стабильности дельты между тиками, лет тридцать так делают уже

Делают как? При наличии полного сетевого стека, не имеют возможности его использовать и берут UPD и пишут свой транспорт с контролем потерь? QueryPerformanceCounter в цикле при разработке игр с загрузкой проца на 100%? А о мультимедийных таймерах я выше писал уже.
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 544
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Рваное время в вин 11

Сообщение Сквозняк » 18.08.2025 09:09:44

Снег Север писал(а):Не понимаю, в чём претензия. Да, это так работает и об этом всех честно предупреждают. Если топикстартер ожидал чего-то другого, то это - его личные проблемы. В играх используют специальный мультимедиа-таймер с высокой точностью. Никто не запрещает его использовать в других приложениях вместо того, что предъявлять какие-то нелепые претензии.


Ага, прямо около дороги стоит плакат, на котором предупреждают. На хрюше и семёрке рванины особо заметно не было и потому на вопрос клался болт, а на вин 10-11 внезапно вылезли тормоза, а как называется хреновина, которую нужно подкрутить, за давностью лет забылось, а поисковикам нужен точный запрос и может быть тогда они выдадут не мусор. Сам подход к экономии процессорных ресурсов путём организации глюков, это что-то прикольное и похожее на маскировку активности шпионских процессов. Ещё не тестировал, лень было, как несколько программ регулирующих таймер взаимодействуют друг с другом, там тоже могут быть приколы, зависящие от версии винды. Общий принцип такой: если программа затормозила, то перезагружай её, а если не помогло, то перезагружай ОС, авось поможет.

Добавлено спустя 19 минут 42 секунды:
sts писал(а):
WAYFARER писал(а):С другой стороны все же к реализации есть вопросы.

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

в данном случае надо просто делать алгоритм независимым от стабильности дельты между тиками, лет тридцать так делают уже


А я проблему заметил и как раз не в высокой точности, а переделка алгоритма, это писец лютый. Хорошо когда алгоритм просто отключает бетономешалку - не пролила бетон и ладно, а как она работает внутри, никого не колышит. А когда нужно выводить в картинку действия нескольких потоков, каждый из которых выполняется за несколько их внутренних "оборотов", то визуально получается замедленное кино. Можно в потоках делать расчёты за один оборот, но тогда вылезает проблема обработки слишком большого количества асинхронных событий, в которых возможность ошибок запланирована, но должна быть редкой. Грубо говоря, нужно пересчитывать что было первым: сел человек покакать или он штаны снял, а если промашка вышла, то чья она - человека или окружающий мир ему снятые штаны обратно надел, а снял когда он их обгадил :mrgreen: Также нужно расширять каналы для передачи событий, чтобы все влезли.
Сквозняк
энтузиаст
 
Сообщения: 1136
Зарегистрирован: 29.06.2006 22:08:32

Re: Рваное время в вин 11

Сообщение sts » 18.08.2025 11:14:21

Сквозняк писал(а):А я проблему заметил и как раз не в высокой точности, а переделка алгоритма, это писец лютый.

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

Добавлено спустя 29 секунд:
WAYFARER писал(а):"Для этого" это для чего?

для точного тайминга

Добавлено спустя 1 минуту 25 секунд:
WAYFARER писал(а):Делают как?

как угодно, в том числе как написали, и это правильно
sts
постоялец
 
Сообщения: 474
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Re: Рваное время в вин 11

Сообщение Сквозняк » 18.08.2025 20:20:03

sts писал(а):а что делать? алгоритм получается очень далеким от наивной реализации, это как квиксорт супротив сортировки пузырьком, только в сотню раз запутанней.
да, в сетевых играх сделано через механизм проигрывания событий


Это не для сетевой игры, а для локальной, в которой последовательный алгоритм проигрывания событий надоел так, что играть в него уже не хочется. В сетевой хоть игроки и жадные админы вносят разнообразие, когда подкручивают выпадение лута в соответствии с поддержанием дефицита на рынке и препятствованию получения всего нужного здесь и сейчас самостоятельно. Если одного повышения точности таймера при старте графики будет мало, то можно повышать каждые 2 минуты. Всё уже работает, просто на вин 11 наконец протестировал и обнаружил тормоза в заметных местах, а на десятке мало тестировал, наверно потому и не заметил.
Сквозняк
энтузиаст
 
Сообщения: 1136
Зарегистрирован: 29.06.2006 22:08:32


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru