Как стать автором
Обновить

Комментарии 25

Была "виндовс" tickless, а стала "совсем tickless" — теперь никто не знает как она тикает ;)

несколько месяцев программное обеспечение плохо работало по непонятной причине.

То есть вы вместо нормальной функциональности использовали недокументированный побочный эффект, а теперь удивляетесь что «внезапно» все сломалось?
Я бы сказал, что эта вещь «недо-документирована».
Windows uses the lowest value (that is, highest resolution) requested by any process

Использует наименьшее значение — для какого процесса? До текущих изменений это следовало читать как «Windows использует для любого процесса наименьшее значение...», а теперь следует читать как «Windows использует для вызвавшего timeBeginPeriod процесса наименьшее значение...».

Недостаточная точность формулировок порождает разные трактования и ошибки типа «в главном процессе повысили точность, рассчитывали, что повысится и в дочерних, проверили — работает. Ой, перестало!» вполне возможны.
Там есть еще предложение в начале, внимательной прочитайте:
This function affects a global Windows setting.


В целом читается однозначно: используется меньшее, влияет на всю систему.
Претензия о том, что кто-то там что-то недокументированное использовал и поэтому заслуженно страдает — бред.
Ну, «affects a global Windows setting», и что. Если я в реестре ключ какой-нибудь поправлю — это тоже формально будет изменение «global Windows settings», однако влиять это может как на все процессы, так и только на какой-то один (а может и вообще ни ни кого).

Кроме того, если принять Вашу точку зрения, что
читается однозначно: используется меньшее, влияет на всю систему


тогда получается, что это неверно документированное поведение, поскольку теперь не влияет на всю систему.
неверно документированное

Это да. Но она не менялось. Так что она либо была неправльная, либо сейчас неправильная. Обвинение разработчикам софта всё равно мимо.
Кстати доки майкрософтовские сейчас удобно можно править пул-реквестами на гитхабе. Я за последнее время исправил несколько моментов по аудио-стеку винды — приняли очень быстро, благодарили.
В идеале при вызове Sleep(1) процессор переходит в спящий режим.

Вот оторвать бы руки тем, кто так пишет.


Sleep() это не "отправь процессор в сон", а "текущий поток (thread) хочет подождать". То есть Sleep() передаёт управление ОС и уже она решает, что там дальше делать. В большинстве случаев — квоту исполнения на текущем ядре просто получит другой поток (возможно даже этого же процесса). А отправка какого-либо ядра процессора в энергосберегающий режим — происходит только когда пул задач полностью исчерпан. И это (отправка в сон) совсем не подразумевается командой Sleep().

Ну справедливости ради, изначально «когда процессоры были большими, а память маленькой», а об многопоточности никто и не думал, sleep() именно что отправлял процессор в сон. Это потом уже, «ради обратной совместимости» решили что «усыпать» будет только поток.
А был ли режим сна у процессоров в те времена, когда о многопоточности никто не думал?
(Почитал про историю HLT, оказывается она действительно была в 8086, но включаемый ей режим пониженного энергопотребления появился только в 80486 DX4)

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

Собственно до выпуска Pentium проблема перегрева процессора и не была особо актуальной.
Существовала программа waterfall.exe, после её запуска Pentium-166 становился ощутимо холоднее — в Windows 95 в простое крутился пустой цикл NOP, из-за чего процессор мог перегреваться, а waterfall ЕМНИП как раз выполняла HLT.
Я использовал CPUIdle в те времена
в Windows 95 в простое крутился пустой цикл NOP

И сделано это, кстати, было спецально.
Можно было добавить в систему чёрный список моделей/производителей ноутбуков, где HLT нельзя применять. Если всё было совсем плохо — сделать белый список, где HLT применять можно. Или в те времена с детектом железа всё было совсем плохо и возможностей узнать, на чём тебя запустили не было?

В том же Linux и сейчас есть всякие таблицы совместимости, которые могут отключить какую-то новую технологию на конкретном железе, потому что известно, что она на нём на самом деле не работает, несмотря на документацию.
Любой список по определению будет неполным. И неполнота черного списка сильно вылезет боком, когда новая система начнет виснуть на дорогих ноутах (учитывая время, дешевых ноутбуков, способных потянуть win95, нет как класса). А интернета для быстрой рассылки обновлений еще по факту нет. Так что не вариант.

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

И, кстати, win98 уже умела работать с ACPI, и при наличии совместимой платы могла управлять питанием гораздо эффективнее, чем это позволяет команда HLT.
Т.е. из-за пары несовместимых моделей пренебрегли возможностью дать процессору отдохнуть? Гениально. Тогда Windows 10 должна ориентироваться на минимально поддерживаемый процессор — никаких виртуализаций, векторных расширений и прочих прелестей. Только одно ядро. Так же проще, чем тестировать совместимость со всем этим безобразием и строит воркэраунды?

Кстати, который раз убеждаюсь, что русскую раскладку клавиатуры таки наши люди делали — искал в тексте по Вашей ссылке NOP, набрал в русской раскладке ТЩЗ — ну так и есть, ТаЩаЗ.
Гениально

Тогда это было гораздо менее актуально, чем сейчас. Первая половина девяностых. Типичный процессор в «неплохом» десктопе — 486, без активного охлаждения. Народ вовсю под DOS сидит. Ни о каком энергосбережении в компьютере никто еще не говорит. Только редкие производители ноутбуков тихо стонут.

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

Тогда Windows 10 должна ориентироваться на минимально поддерживаемый процессор

Отчасти так и есть в любой системе, кроме совсем безбашенно-опенсорных, типа gentoo. Системные бинарники не используют очень многое из новых процессоров, чтобы продолжать запускаться на чем-то минимально-допустимом, возрастом лет эдак 15-20.
Написано же — "в идеале..." — и это, в общем, правда. В идеале, на какой-нибудь голой винде, с отключенными левыми сервисами и ровно одним однопоточным приложением, вызвавшем Sleep() — вполне вероятно, что процессор уйдёт спать. В общем случае, конечно, не уйдёт, но автор не писал об общем случе, он писал об идеальном.
Для тредов одного процесса интервал точно будет меняться?
Тот случай, когда утверждение о том, что явное лучше неявного — это правда.

А как это устроено в линуксах?

Насколько я знаю, там разрешение таймера всегда 1 миллисекунда (можно изменить при сборке кастомного ядра). Однако ядро учитывает, что если ближайший поток должен проснуться через 500 миллисекунд, то совсем не обязательно молотить вхолостую 500 прерываний, а можно настроить таймер так, чтобы он сработал через эти самые 500 миллисекунд. То есть каждый раз, когда не остаётся активных потоков и ОС должна усыпить процессор, Linux вычисляет самое близкое время пробуждения какого-либо потока и настраивает таймер на это время (разумеется, есть технические ограничения минимальной частоты системного таймера, тогда выбора нет и придётся проснуться раньше и уснуть снова).

В Windows реализован костыль, чтобы бесконечный цикл с Sleep(1) жрал меньше электроэнергии ценой введения неявного поведения «мы знаем лучше, чем программист, сколько его Sleep должен длиться». Подобные циклы встречаются не очень часто (как верно замечено в статье). А если уж встречаются, то скорее всего программиста вполне устраивало повышенное энергопотребление (например, он воспроизводит 60fps анимацию).

Кстати, разработчикам Windows достаточно было бы сделать влияние настройки разрешения системного таймера локальным. То есть реальный системный таймер гонять на частоте наибольшего общего делителя от всех запрошенных разрешений, а доставлять реальные сигналы пробуждения потокам округляя их время пробуждения исходя из их настроек (то есть Sleep(N) транслируется в Sleep((N + 1) / РазрешениеТаймера * РазрешениеТаймера), где все операции целочисленные, а разрешение таймера хранится отдельно для каждого процесса, исходя из его обращений к функции изменения разрешения таймера). Тогда бы никаких глюков не было. Кроме того, что «ускорители таймера» перестали бы влиять на другие программы (а их задача как раз в том, чтобы чинить программы, которые ломаются от слишком медленного таймера). Однако изменение описанное в статье точно также их ломает, так что не вижу причин, почему нельзя всё было сделать по-нормальному.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.