Кто-нибудь может подсказать как замерить время выполнения кода, никак не могу найти подходящей функции...
GetTickCount а вообще, на васме была даже отдельная тема, где показывали мануалы с картинками, в которых написано как с точностью до тиков посчитать
я пытаюсь подключить winbase.h и компилятор выдает море ошибок(free command line tools от borland). для этого заголовочного файла нужно еще какие то библиотеки?
а если сделать так: Код (Text): start = clock(); for(i = 0; i < max; i++) testFunc(); time = clock() - start; то такой способ будет точен, если я хочу определить какая функция будет быстрее работать? вначале подставив первую функцию, а затем вместо нее другую
Ну можно профилирование заюзать, хотя тоже слишком медленно и напрямую апик читать - он тоже медленно работает.
По идее, для чистоты эксперимента, неплохо было бы исключить влияния диспетчеризации процессов, хотя ,конечно, эту погрешность можно попытаться задавить очень большим числом итераций. Если чисто, то надо в драйвере повысить IRQL до DISPATCH_LEVEL и там уже посчитать имхо время выполнения цикла. Кстати, над самим циклом тоже можно подумать еще, так как в зависимости от проца (устройство конвейера, время выполнения инструкций) он может выполняться за весьма разное число тактов.
function TargetFuncTickTest(nIter : DWORD; Func : Pointer; ARG : Pointer) : LONGLONG; stdcall; assembler; var CurrentThread, CurrentProcess : THandle; ThreadPriority : Integer; PriorityClass : DWORD; asm //push ESI //push EDI //push ECX pushad mov EBX, ARG //push EBX call GetCurrentThread mov CurrentThread, EAX push EAX call GetThreadPriority mov ThreadPriority, EAX call GetCurrentProcess mov CurrentProcess, EAX push EAX call GetPriorityClass mov PriorityClass, EAX push THREAD_PRIORITY_TIME_CRITICAL push CurrentThread call SetThreadPriority push REALTIME_PRIORITY_CLASS push CurrentProcess call SetPriorityClass //pop EBX mov dword ptr [Result], 0 mov dword ptr [Result + 4], 0 FNINIT mov ECX, nIter @loop: db 00Fh, 031h // rdtsc push EAX push EDX push EBX call Func db 00Fh, 031h // rdtsc pop EDI pop ESI sub EAX, ESI sbb EDX, EDI add dword ptr [Result], EAX adc dword ptr [Result + 4], EDX FSTP ST loop @loop FILD Result FIDIV nIter FISTP Result push ThreadPriority push CurrentThread call SetThreadPriority push PriorityClass push CurrentProcess call SetPriorityClass popad //pop ECX //pop EDI //pop ESI end { TargetFuncTickTest }; в тиках выдаёт среднее значение, правда данные успевают закэшироваться; чтобы максимальное время замерить можно изменить эту function GetCPUFreq() : LONGLONG; stdcall; assembler; asm push ECX push EBX db 00Fh, 031h // rdtsc push EAX push EDX push 1000 call Sleep db 00Fh, 031h pop ECX pop EBX sub EAX, EBX sbb EDX, ECX pop EBX pop ECX end { GetCPUFreq };
в продолжение темы. как-то писал апликуху, чтобы можно было замерять время выполнения кода между точками останова. прога запрашивает время активности указанного потока каждую секунду, и выводит результат. при отладке под VC получилась такая странность: - если поставить бряк и запустить код на выполнение, то после срабатывания бряка апликуха показывает результат (вполне ожидаемый) - если же выполнять код пошагово, то время выполнения не изменяется, т.е. поток просто-напросто спит. неужто студия выполняет отлаживаемый код в отдельном потоке?
Ес-но, мгновенно выполняет один шаг и засыпет. А время не тикает, т.к. не хватает разрешающей спсобности системного таймера. Это все равно, что "накапайте мне стаканчик" - можно из кранчика по капельке целое ведерко или бочечку набрать, а счетчик воды при этом ни на копейку не изменится Отладчик и отлаживаемый код это разные процессы и ес-но разные потоки - когда один работает второй ждет\спит
по поводу первого я также думал сначала, пока не сделал подвисание в цикле на несколько секунд, типа Код (Text): void func() { for (int i = 1; i; i ++) for (int j = 1; j; j ++) __asm nop; } ... eip -> func(); по поводу второго я не понял вашей мысли. хотя, может быть я неправильно выразился. меня смущает то, что время активности отлаживаемого пошагово студией потока не меняется. т.е., стоит указатель команды, например, на линии 3; я нажимаю F10 => указатель переместился на линию 4, а время активности отлаживаемого потока не изменилось.
leo Потоки разные, но вот выполняться могут в контексте одного процесса. Чисто теоретически, ядро вначале доставляет сообщение на отладочный порт, затем если не обработано на порт исключений. Последний может быть установлен посредством ProcessExceptionPort, но только в случае если прежде порт установлен не был. А его устанавливает csrss при инициализации процесса(CsrCreateProcess()). Тоесть необходимо создать процесс без нотификации подсистемы, этот процесс должен быть нативным. В нём создать тред, который будет обрабатывать сепшены в текущем процессе.