A way that I often use is to compare the execution against a hardware timer.
The example below works for an '8720 running at 20Mhz. You will have to modify accordingly if you use a different processor or XTAL.
-----------------------------------------------------------------------


DEFINE OSC 20

DEFINE NO_CLRWDT 1 ' Don't waste cycles clearing WDT
DEFINE _18F8720 1
DEFINE HSER_RCSTA 90H
DEFINE HSER_TXSTA 20H
DEFINE HSER_BAUD 9600
DEFINE HSER_CLROERR 1
DEFINE LOADER_USED 1
Define USE_LFSR 1

TRISC = %10111111 ' Hardware serial port on PORTC.7,PORTC.6

PSPCON = %00000000 ' No PSP
MEMCON = %10000000 ' No External Memory
CMCON = %00000111 ' No Comparator used, turn it off

T0CON = %10001000 ' No Prescaler,16 bit


TimerValue VAR WORD
RealTime VAR WORD

TestArray VAR BYTE[3600]

DummyVal VAR Byte

Restart:
Intcon.2 = 0
TMR0H =0
TMR0L =0

'Put code to be timed here





'----------------------------------------

TimerValue.LowByte = TMR0L
TimerValue.Highbyte = TMR0H

IF INTCON.2 = 1 THEN
HSEROUT ["OVERFLOW - User different prescaler value",13,10]
ENDIF



HSEROUT ["Execution Time = ",#TimerValue, " Cycles, ",#TimerValue/5," Microseconds",13,10,10]


HSEROUT ["Press any key to restart",13,10]

HSERIN [DummyVal]
GOTO Restart

END