Open Roman-Koshelev opened 3 years ago
@Roman-Koshelev
В стандарте C++ не прописываются реализации методов, только их поведение. Это решает две проблемы:
vDSO.
.Поэтому стандарт опирается на предположение, что разработчики компиляторов и стандартных библиотек будут делать самую эффективную реализацию. Это предположение называется Quality of Implementation
или QoI
Не у всех всегда получается с первого раза сделать идеальную имплементацию. При этом разработчики с радостью принимают патчи и фиксы.
Я проверил для своей системы. В libstdc++ есть код https://github.com/gcc-mirror/gcc/blob/16e2427f50c208dfe07d07f18009969502c25dc8/libstdc%2B%2B-v3/src/c%2B%2B11/chrono.cc#L85-L89 , соответственно если не определён макрос _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL
то вызов должен идти в vDSO версию функции в glibc https://github.com/lattera/glibc/blob/master/sysdeps/unix/sysv/linux/clock_gettime.c
Локальная сборка libstdc++ макрос _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL
не определяет:
grep -r '_GLIBCXX_USE_CLOCK_GETTIME_SYSCALL' /data/gcc_build/
/data/gcc_build/stage1-x86_64-pc-linux-gnu/32/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/c++config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/stage1-x86_64-pc-linux-gnu/32/libstdc++-v3/config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/stage1-x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/c++config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/stage1-x86_64-pc-linux-gnu/libstdc++-v3/config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/x86_64-pc-linux-gnu/32/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/c++config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/x86_64-pc-linux-gnu/32/libstdc++-v3/config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/c++config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/x86_64-pc-linux-gnu/libstdc++-v3/config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/prev-x86_64-pc-linux-gnu/32/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/c++config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/prev-x86_64-pc-linux-gnu/32/libstdc++-v3/config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/prev-x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/c++config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
/data/gcc_build/prev-x86_64-pc-linux-gnu/libstdc++-v3/config.h:/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */
Какая именно у вас платформа (версия C++ библиотеки, ядра ОС, версия C библиотеки)? Заведу им багрепорты, если можно поправить.
По идее, точность можно достать из std::chrono::*_clock::period
http://eel.is/c++draft/time#clock.req
Она на вашей платформе показывает истину?
Тут всё чудаковато на разных платформах и процессорах http://gcc.1065356.n8.nabble.com/PATCH-v5-2-8-libstdc-futex-Use-FUTEX-CLOCK-REALTIME-for-wait-tp1692640p1788061.html
Если знаете как улучшить ситуацию - пожалуйста пишите и прикладывайте бенчмарки, оформим фиксы в стандартные библиотеки. Бенчмарки можно набросать на коленке вот тут https://quick-bench.com/
Большое спасибо за подробный ответ. По vDSO согласен (не обязательно оно, но хотелось бы чтобы самым оптимальным доступным способом). Про "Точность" мой недосмотр (там все хорошо). Остается только добавить более быстрые версии часов (если они доступны на платформе), чтобы можно было получить самые быстрые часы с разрешением не менее ... . sleep_* поисследую
Попробовал разные функции. Вот результаты nanosleep mean duration 1641857ns realtime_clock_nanosleep mean duration 1065419ns monotonic_clock_nanosleep mean duration 2373212ns realtime_abs_clock_nanosleep mean duration 1155873ns monotonic_abs_clock_nanosleep mean duration 1715776ns sleep_for mean duration 1687494ns
Пока не понял чем сон в абсолютном времени хуже. И почему вообще функции абсолютного сна имеют право переходить на относительный? Это же значит что по-любому придется писать свою реализацию sleep_unit, если хочешь кода независимого от реализации стандартной библиотеки
Bench - https://yadi.sk/d/PJASVaEtqgZkwg
"Какая именно у вас платформа (версия C++ библиотеки, ядра ОС, версия C библиотеки)? Заведу им багрепорты, если можно поправить."
ldd (GNU libc) 2.28 uname -r 4.18.0-193.19.1.el8_2.x86_64 gcc version 7.1.0 x86_64-redhat-linux
_COARSE часы быстрее более чем в 100 раз https://quick-bench.com/q/IAaixmnh5wW5_Qe0CdMm4CCV_Pw
Боюсь это предложение я сам не напишу)
Боюсь это предложение я сам не напишу)
Главное начните, а как поймёте что застряли - говорите и скидывайте результат. Это как правило сильно упрощает мне дальнейшую задачу по доработке... а порой и дорабатывать не надо ;-)
@apolukhin "По идее, точность можно достать из std::chrono::*_clock::period http://eel.is/c++draft/time#clock.req Она на вашей платформе показывает истину?" Нет не показывает. В Microsoft STL std::steady_clock::period == std::nano, хотя на самом деле для получения времени там используются функции _Query_perf_frequency() (говорит сколько тиков в секунде, везде где я проверил это 10^7. Гарантирует что результат постоянен с момента загрузки ПК и до выключения) и _Query_perf_counter() (возвращает те самые тики). Получается что разрешение часов у монотонных часов как и у системных 100ns а не 1 ns
В windows тоже возможна реализация быстрых часов. Например std::time (которая возвращает секунды) в windows, работает со скоростью COARSE часов в linux (примечательно то что glibc не использует вызовы gettimeofday и time которые сильно быстрее, а просто обрезает время взятое из clock_gettime до нужной точности)
В С++20 сильно расширили зоопарк часов, но так и не сделали то чего хотелось бы.
Проблемма 1.
Сейчас (до с++20 по крайней мере) есть трое часов (system_clock, steady_clock, high_resolution_clock). system_clock - часы реального времени с разрешением ??? В Windows это 100ns, на linux в libc++ 1us (наносекунды обрезаются) а в libstdc++ 1ns steady_clock - монотонные часы с разрешением обычно 1ns high_resolution_clock - непонятные часы которые steady_clock в Microsoft STL и libc++, и system_clock в libstdc++. Как и для чего их можно использовать абсолютно не ясно.
Проблемы:
Чего хочется:
Проблемма 2.
Для того чтобы заснуть с++ предоставляет 2 функции (sleep_for и sleep_until). Обе работают интересным образом. В Microsoft STL функция sleep_for прибавляет к переданному времени clock::now() и делает sleep_until. libc++ и libstdc++ делают наоборот. sleep_until отнимает от переданного времени clock::now() и вызывает sleep_for
Проблемы Microsoft STL:
Проблемы libc++ и libstdc++:
Чего хочется: