Как сделать активный сон? - PullRequest
1 голос
/ 14 июля 2009

Я провожу некоторые тесты профилирования, и usleep - полезная функция. Но пока моя программа спит, это время не отображается в профиле.

например. если у меня есть функция как:

void f1() {
    for (i = 0; i < 1000; i++)
        usleep(1000);
}

При использовании инструментов профиля, таких как gprof, f1, похоже, не тратит время.

То, что я ищу, - это метод лучше, чем пустой цикл while для активного сна, например:

while (1) {
    if (gettime()  == whatiwant)
        break;
}

Ответы [ 7 ]

2 голосов
/ 14 июля 2009

Какая у вас система? В UNIX-подобных системах вы можете использовать setitimer () для отправки сигнала процессу через определенный промежуток времени. Это средство, которое вам понадобится для реализации типа «активного сна», который вы ищете.

Установите таймер, затем выполните петлю, пока не получите сигнал.

2 голосов
/ 14 июля 2009

Я предполагаю, что вы хотите узнать общее количество времени (время настенных часов, реальное время, время, которое вы сидите, наблюдая за запуском вашего приложения), которое занимает f1 (), а не время процессора. Я бы поинтересовался, может ли gprof дать вам время настенных часов вместо времени обработки.

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

2 голосов
/ 14 июля 2009

Потому что, когда вы звоните usleep, процессор включается на что-то еще на 1 секунду. Таким образом, текущий поток не использует ресурсы процессора, и это очень умная вещь.

Активный сон - это то, чего абсолютно следует избегать, потому что это пустая трата ресурсов (в конечном итоге наносит ущерб окружающей среде, превращая электричество в тепло;)).

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

for (i = 0; i < 1000; i++)
    time(NULL);
1 голос
/ 14 июля 2009
for (int i = i; i < SOME_BIG_NUMBER; ++i);

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

То, что вы спрашиваете, не имеет смысла. Вы не можете спать в своем приложении, но все еще работаете.

0 голосов
/ 14 июля 2009

Это путаница, которую вы получаете с gprof, так как вас волнует время настенных часов. Я использую это .

0 голосов
/ 14 июля 2009

Вот почему при профилировании важно смотреть на время "Switched Out%". В принципе, в то время как эксклюзивное время вашей функции может быть небольшим, если оно выполняет, например, Ввод-вывод, БД и т. Д., Ожидающие внешних ресурсов, а затем «Switched Out%» - показатель, который нужно отслеживать.

0 голосов
/ 14 июля 2009

AFAIK единственный вариант - сделать цикл while. Операционная система обычно предполагает, что если вы хотите подождать некоторое время, которое вы хотите уступить операционной системе.

Возможность получить точный микросекундный таймер также является потенциальной проблемой. AFAIK нет кроссплатформенного способа определения времени (пожалуйста, кто-нибудь поправит меня, потому что я бы хотел кроссплатформенный субмикросекундный таймер!: D). Под Win32 вы можете окружить цикл несколькими вызовами QueryPerformanceCounter, чтобы сработать, когда вы провели достаточно времени в цикле, а затем выйти.

* 1005 например *

void USleepEatCycles( __int64 uSecs )
{
    __int64 frequency;
    QueryPerformanceFrequency( (LARGE_INTEGER*)&frequency );
    __int64 counter;
    QueryPerformanceCounter( (LARGE_INTEGER*)&counter );

    double dStart = (double)counter / (double)frequency;
    double dEnd   = dStart;
    while( (dEnd - dStart) < uSecs )
    {
        QueryPerformanceCounter( (LARGE_INTEGER*)&counter );
        dEnd = (double)counter / (double)frequency;
    }
}
...