DeFi

Почему в C++ есть std::chrono::high_resolution_clock, но нет low_resolution_clock: что нужно знать разработчикам

DeFi
There is std:chrono:high_resolution_clock, but no low_resolution_clock

Обзор возможностей таймеров в C++, разбор причин отсутствия std::chrono::low_resolution_clock и практические рекомендации по выбору подходящих часов для высокоточных и менее критичных по скорости задач.

В современной разработке на C++ управление временем и точность измерения интервалов играют ключевую роль. Особенно это важно при создании многопоточных приложений, работе с таймингом и планировщиками задач, где от качественного отсчёта времени зависит корректность всей системы. В стандартной библиотеке C++17 и выше для этой цели предусмотрен набор классов в пространстве имён std::chrono, среди которых существует std::chrono::high_resolution_clock — часы с максимально возможной точностью, предоставляемые конкретной реализацией платформы. Однако, несмотря на распространённость высокоточных часов, многие разработчики задаются вопросом: почему в стандарте отсутствует аналог low_resolution_clock, который бы предоставлял часы с низкой точностью, но меньшими затратами на вычисление времени? Рассмотрим эту дилемму подробнее, обсудим технические аспекты и узнаем, каким образом можно эффективно решать подобные задачи в реальных условиях. Для начала важно понять, что std::chrono::high_resolution_clock — это тип часов, который предоставляет таймер с наименьшим периодом тика на данной платформе.

Это означает максимально мелкие временные шаги, аж вплоть до наносекунд, если это поддерживается аппаратной частью и операционной системой. Такие часы удобны для измерения коротких временных интервалов, профилирования кода, или задач, где критична точность. Но с повышением точности приходит и ценник — время получения текущего значения часов может вырасти, ведь аппаратно-программный механизм может требовать затрат на системные вызовы, чтение специальных регистров, синхронизацию и т.п. В некоторых случаях, особенно когда высокий уровень детализации не нужен, использование высокоточных часов — это просто излишняя трата ресурсов.

К тому же, нередко разработчики хотят измерять большие интервалы времени с «грубой» точностью, например, с шагом миллисекунд, десятков миллисекунд или больше. Для таких задач не обязательно заморачиваться слишком точным счётчиком. Тогда и возникает логичный вопрос — зачем нет встроенного low_resolution_clock, который бы отдавал текущее время максимально быстро, пусть с меньшей точностью? Ответ частично кроется в философии стандарта C++. Стандарт стремится предоставить разработчикам надёжные и максимально общие средства, которые одинаково хорошо работают во всех системах. Концепция low resolution clock весьма относительна — «низкая точность» зависит от конкретного случая, устройства и ОС.

Например, на Windows есть функция GetTickCount64, которая возвращает время в миллисекундах с относительно небольшой частотой обновления, порядка 10-16 миллисекунд. На Linux можно использовать CLOCK_MONOTONIC_COARSE, дающий сглаженные усреднённые показания с приблизительной точностью в миллисекунды. Но в разных системах и процессорах детали будут различаться. Принципиально, стандарт не захотел вводить новый тип часов с неопределённым поведением или критично низкой точностью без чёткого контракта. Поэтому оставил разработчикам право самим решать эту задачу, используя платформенно-специфичные средства, когда это необходимо.

Железо и ОС предоставляют нужные интерфейсы, но стандартизованные средства — только высокоточечные и системные часы. Однако, разработчики часто нуждаются именно в быстром и достаточно стабильном и основанном на steady-clock, но при этом «дешёвом» решении. В своем блоге Рэймонд Чен, известный сотрудник Microsoft, рассказал о практическом подходе к решению этой проблемы. Он предложил создать собственный тип cheap_steady_clock, который бы обеспечивал достаточно приемлемую пунктуальность (steadiness) и при этом был бы максимально лёгким по стоимости. Для Windows в качестве источника времени использовалась именно GetTickCount64: он предоставляет значение в миллисекундах, обновляется примерно раз в 10-16 мс, что вполне достаточно для планирования спящих интервалов и менее критичных по времени задач.

Сами часы cheap_steady_clock реализованы так, чтобы поддерживать типы и интерфейсы, совместимые с std::chrono, включая duration и time_point. Это позволяет интегрировать их напрямую с остальным кодом, не меняя логику работы, при этом снизив накладные расходы на получение времени. Аналогично, в Linux предложено использовать CLOCK_MONOTONIC_COARSE через вызов clock_gettime — эта возможность доступна в современных ядрах. Он обеспечивает монотонность и разрешение в районе 1-4 миллисекунд, что приемлемо для большинства сценарием, где точность в наносекундах не требуется, а главное — ускорено чтение таймера. При этом нестандартная ситуация с необходимостью бросать исключение в noexcept методе now, если считывание времени не удалось, подчёркивает серьёзность подхода — подчеркивается, что при невозможности получить время происходит аварийное завершение программы, поскольку невозможно продолжать корректную работу.

Это отражает баланс между простотой API и реальными ограничениями низкоуровневых вызовов. Еще один момент, который стоит учитывать — стабильность (steadiness) часов. В C++ steady_clock гарантирует, что время не снизится, а только растет с течением процесса или системы. Использовать системные часы, которые могут прыгать или синхронизироваться, во многих задачах нежелательно. Предложенный cheap_steady_clock соответствуют этому требованию, что позволяет избежать неожиданных откатов времени из-за синхронизации часов или изменений в системных настройках.

Разумеется, высокоточные часы не всегда и не всем нужны. В системах реального времени или при профилировании кода важно измерять время до наиболее точных единиц, однако если задача — просто приостановить поток на одну секунду или отследить приблизительное время, достаточно millisecond accuracy, что позволит сэкономить ресурсы и упростить логику. С технической точки зрения, если говорить про существующие стандартные часы, в C++ их три основных типа: system_clock, steady_clock и high_resolution_clock. При этом high_resolution_clock может быть синонимом любого из двух предыдущих в зависимости от реализации. Но none делает явного low_resolution_clock.

Поэтому, если нужно именно «низкозатратные» часы с гарантированной устойчивостью, стоит реализовать собственные, опираясь на стандарты и методы операционной системы. В целом отсутствие std::chrono::low_resolution_clock отражает компромисс между универсальностью, переносимостью кода и потребностями большинства разработчиков. Производители ОС предоставляют разные таймеры с разными характеристиками, а стандарт C++ универсален и не может просто выбрать один «низкозатратный» таймер без риска потери переносимости и возникновения путаницы. Из практики можно порекомендовать при написании кроссплатформенного кода для сервисов и приложений, где время измеряется достаточно примерно, задумываться именно о cheap_steady_clock или аналоге, полностью контролируемом внутри приложения. Такая реализация даёт возможность подстроиться под возможности конкретной ОС и выполнить баланс точности и стоимости получения времени.

Особенно это актуально для систем с ограниченными ресурсами, встроенных приложений и многопоточных задач, где частое получение времени может стать узким местом производительности. В заключение стоит напомнить, что при выборе часов для своего проекта важно понимать требования к точности и нагрузке. Не всегда максимальная точность — залог успеха. Иногда лучше сделать систему предсказуемой и эффективной, пожертвовав несколькими наносекундами. Отсутствие low_resolution_clock — не проблема, а возможность гибко ориентироваться на особенности платформы, создавая для каждой задачи оптимальное решение.

Такой подход, продемонстрированный на примере cheap_steady_clock от Рэймонда Чена, показывает, как можно обойти ограничения стандарта и при этом получить максимально удобный и эффективный инструмент. Благодаря этому разработчики получают шанс строить продуктивные приложения, правильно выбирая между высокоточной синхронизацией времени и лёгкими, дешёвыми таймерами для менее требовательных сценариев. Таким образом, понимание различий между различными видами часов и умение реализовывать собственные адаптированные решения позволяет более эффективно использовать ресурсы системы и писать качественный, оптимизированный код. Важно следить за возникающими нововведениями стандарта C++ и новыми возможностями ОС, поскольку область тайминга — одна из динамично развивающихся, и инструменты постоянно совершенствуются.

Автоматическая торговля на криптовалютных биржах Покупайте и продавайте криптовалюты по лучшим курсам Privatejetfinder.com (RU)

Далее
Claude Code Has Gone from Game-Changer to Garbage
Среда, 22 Октябрь 2025 Падение Claude Code: как революционный ИИ превратился в разочарование

Путь Claude Code от технологического прорыва до обесцененного и неэффективного инструмента в сфере искусственного интеллекта. Анализ причин упадка и перспектив будущего развития.

Show HN: Simulating Autonomous Drone Formations
Среда, 22 Октябрь 2025 Симуляция Автономных Формирований Дронов: Новый Взгляд на Управление Беспилотниками

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

Analysis of TTFF (Time to First Failure) in CI Processes (2024)
Среда, 22 Октябрь 2025 Анализ времени до первого сбоя (TTFF) в процессах непрерывной интеграции в 2024 году

Подробное исследование показателя времени до первого сбоя (TTFF) в процессах непрерывной интеграции на примере OP Labs с использованием современных методов анализа данных и статистики. Рассмотрены ключевые тенденции, влияние оптимизаций и рекомендации по улучшению производительности CI.

Show HN: Recursive Intelligence – Theory and Artifact (600 Downloads on Zenodo)
Среда, 22 Октябрь 2025 Рекурсивный интеллект: революция в искусственном интеллекте и когнитивных науках

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

Why Shares of Wells Fargo Are Sinking Today
Среда, 22 Октябрь 2025 Почему Сегодня Акции Wells Fargo Значительно Понижаются: Анализ Ситуации и Перспективы

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

Polymarket Probe Ended by DOJ in Win for Crypto Bets Under Trump
Среда, 22 Октябрь 2025 Завершение расследования Polymarket: выигрыш для криптовалютных ставок при администрации Трампа

После долгого расследования Министерство юстиции США завершило проверку платформы предсказательных рынков Polymarket, что стало значимым событием для индустрии криптовалютных ставок и открыло новые перспективы для регулирования таких сервисов в Соединенных Штатах.

Kazakhstan Set To Launch Pioneering National Crypto Reserve
Среда, 22 Октябрь 2025 Казахстан создаёт национальный крипторезерв: новый шаг в цифровой экономике

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