If you are running your program with help of "twistd", then it has an option "--profile" which can help you with profiling twisted code.
twistd "other options" --profile=statsfile --profiler=cProfile --savestats
And to view the stats:
import pstats
stats = pstats.Stats('statsfile')
stats.sort_stats('time').print_stats()
Callbacks are executed immediately after the deferreds are fired. But immediately means that each callback in the deferred chain has to be executed and they would have their own execution time. Also various pieces of code will have their own slice of time for execution including the reactor loop.
So to say the word - immediately is to say as soon as possible.
Consider the following bad example :
from twisted.internet import reactor, defer
import time
def timeit(func):
def wrapper(*arg):
t1 = time.time()
res = func(*arg)
t2 = time.time()
print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0)
return res
return wrapper
d = defer.Deferred()
@timeit
def callfunc1(result):
print 'XXXXX'
@timeit
def callfunc2(result):
print 'YYYYY'
d.addCallback(callfunc1)
d.addCallback(callfunc2)
t1 = time.time()
d.callback(True)
t2 = time.time()
print '%0.3f ms' % ((t2-t1)*1000.0)
Output:
XXXXX
callfunc1 took 0.039 ms
YYYYY
callfunc2 took 0.005 ms
0.108 ms
Now if we tweak the above code to include a reactor and callLater