Точное решение для траты времени

0

Учитывая следующие фрагменты кода

class time implement Runnable{
 long t=0L;
 public void run(){
  try{while(true){Thread.sleep(1000);t++;/*show the time*/}}catch(Throwable t){}
 }
}

////

long long t=0L;
void* time(void* a){//pthread thread start
sleep(1);t++;//show the time
}

В каком-то учебнике я читал, что в Java Thread.sleep(1000) не ровно 1 секунда, и может быть больше, если система занята в то время, а затем OS переключается на поток поздно.

Вопросов:
Действительно ли это дело вообще или нет?
Является ли этот сценарий таким же для родных (C/C++) кодов?
Каков точный способ подсчета секунд в приложении?

  • 0
    Даже если вы не спите и просто опрашиваете System.nanoTime() вы увидите много дрожания до миллисекунд на тихой машине. vanillajava.blogspot.co.uk/2013/07/...
Теги:
multithreading
pthreads

6 ответов

2
Лучший ответ

Другие ответили на вопрос о точности времени. К сожалению, нет никакого ГАРАНТИРОВАННОГО способа спать в течение Х промежутка времени и просыпаться ровно через X.00000 секунд (или миллисекунды, наносекунды и т.д.).

Для отображения времени в секундах вы можете просто опустить время ожидания, скажем, полсекунды. Тогда время от времени у вас не будет времени на переход на две секунды, потому что полсекунды не будут расширены более чем на одну секунду (если только ОС и система, на которой вы работаете, абсолютно перегружены, и ничего не запускается когда это необходимо - и в этом случае вы должны исправить эту проблему [получить более быстрый процессор, больше памяти или что-то еще, что требуется), не возиться с временем вашего приложения). Это хорошо работает для "относительно длительных периодов времени", таких как одна секунда или 1/10 секунды. Для более высокой точности это не будет работать, так как мы сейчас входим в зону "джиттер планирования".

Если вам нужна очень точная синхронизация, вам, вероятно, понадобится использовать оперативную ОС или, по крайней мере, ОС с включенными "расширениями реального времени", что позволит ОС быть более строгими во времени (за счет "простота использования" у программиста и, возможно, также менее эффективная в нем обработка процессов, поскольку она "переключается чаще, чем нужно", по сравнению с более "ленивым" временным подходом).

Обратите внимание также, что "может занять больше времени" в незанятой системе в основном "округление таймера" (если тик системы происходит каждые 10 мс или 1 мс, таймер устанавливается на 1000 мс + все, что осталось от текущего таймера, например, может составлять 1009.999 мс, или 1000.75 мс). Другие накладные расходы, возникающие из планирования и общих накладных расходов ОС, должны быть в диапазоне микросекунд, если не наносекунды в любой современной системе - в конце концов, операционная система может выполнять довольно много работы в микросекундах - современный процессор x86 будет выполнять три цикла за часы, а часы работают на 0,3 нс. Это 10 инструкций на наносекунду (конечно, промахи в кеше и тому подобное резко ухудшат). Если ОС имеет более нескольких тысяч инструкций для перехода от одного процесса к другому (тем не менее для потоков), то там что-то не так. Несколько тысяч инструкций @10 инструкций на наносекунду = несколько сотен наносекунд. Определенно меньше, чем микросекунда. Сравните это с 1 мс или 10 мс "дрожанием" запуска таймера сразу после того, как в последний раз таймер отключился.

Естественно, если CPU занят другими задачами, это другое - тогда время, оставшееся до запуска на других процессах, также повлияет на время, необходимое для пробуждения процесса.

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

  • 0
    Отлично, спасибо, Дон Петерссон, да, я использовал вместо этого system_current_time , но меня интересовало другое более простое решение. Спасибо большое.
  • 0
    * Матс Петерссон
2

Чтобы ответить на два первых вопроса: Да, это правда, и да.

Прежде всего, время между истечением тайм-аута и временем, когда ОС замечает его, тогда настало время, чтобы ОС перепланировала ваш процесс, и, наконец, время от процесса "проснулось", пока не наступит его очередь запустить. Сколько времени это займет? Нет никакого способа сказать.

И, как все это делается на уровне ОС, на самом деле не важно, на каком языке вы программируете.

Что касается более точного пути? Здесь ничего нет. Вы можете использовать более высокоточные таймеры, но нет способа избежать описанного выше отставания.

1

Это правда. Каждая реализация sleep на любом языке (C тоже) не сможет подождать ровно 1 секунду. Он должен иметь дело с вашим планировщиком ОС, продолжительность сна - это только намек: the minimum sleep duration чтобы быть точным, но фактическая разница зависит от гигациллий факторов.

Попытка выяснить отклонение сложно, если вы хотите очень высокие часы. В большинстве случаев у вас будет примерно 1 ~ 5 мс (примерно).

Дело в том, что порядок величины будет одинаковым независимо от продолжительности сна. Если вы хотите что-то "точное", вы можете разделить ваше приложение времени и ждать более длительного периода. Например, когда вы ориентируетесь, вы предпочтете этот тип реализации, потому что дельта-время будет увеличиваться, уменьшая неопределенность:

// get t0
// process n times
// get t1    
// compute average time : (t1-t0)/n
1

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

1

Сон вызова сообщает системе о прекращении выполнения потока в течение как минимум периода времени, указанного в качестве аргумента. После этого система возобновит выполнение потока, если у него есть шанс (на самом деле это зависит от многих факторов, таких как аппаратное обеспечение, приоритеты потоков и т.д.). Чтобы более или менее точно измерить время, в которое вы можете сохранить время в начале выполнения, а затем вычислить дельта времени каждый раз, когда это необходимо.

1

Да, это правда, что это не точно.
То же самое для простых функций сна в C/C++ и почти во всем остальном.
В зависимости от вашей системы могут быть доступны более доступные функции,
но:

Каков точный способ

Совершенно точного пути не существует.
Unles у вас есть действительно дорогой специальный компьютер с включенными атомными часами.
(и никакой обычной ОС тоже. И даже тогда мы могли бы утверждать, что означает "точный")

Если ожидание ожидания (высокая загрузка процессора) приемлемо, посмотрите на nanoTime или native usleep, HighPerformanceCounter или что-то, что применимо для вашей системы

Ещё вопросы

Сообщество Overcoder
Наверх
Меню