0

Is there any way to do "conditional profiling" with cProfile? I have a method, let's call it readPackets(), which is supposed to take only a few milliseconds at most, but every once in a while it takes 0.5 second or more. (The issue involves multithreaded Python access... I assume something else has the GIL or is competing for some lock, but I don't know what.)

What I want to do is profile it only when it takes a long time -- I can already do something like this:

pr = cProfile.Profile()

class MyEngine(object):
    def run(self):
        while self.alive:
            # in main event loop
            pr.enable()
            self.readPackets()
            pr.disable()
            ...
            # other stuff

and that gets me a nice profile of what's running inside readPackets in general, but these slowdowns are somewhat rare, and it's really hard to tell what's going on in that one instance.

What I really want is something like this:

pr = cProfile.Profile()

class MyEngine(object):
    def run(self):
        while self.alive:
            # in main event loop
            transaction = pr.beginTransaction()
            t0 = time.time()
            pr.enable()
            self.readPackets()
            pr.disable()
            t1 = time.time()
            if (t1 - t0) > 0.5:
                transaction.commit()  # Found a slow execution!
            else:
                transaction.rollback() # it's fast, ignore it
            ...
            # other stuff

or this:

class MyEngine(object):
    def run(self):
        while self.alive:
            # in main event loop
            t0 = time.time()
            pr.enable()
            self.readPackets()
            pr.disable()
            t1 = time.time()
            if (t1 - t0) < 0.5:
                pr.clear()            # get rid of this iteration, we don't care
            else:
                sys.exit()            # got a slow iteration                ...
            # other stuff

Is there any way to profile a single call to a method, but only keep the results if it's slow?

Jason S
  • 184,598
  • 164
  • 608
  • 970
  • If you're going to go to that detail (without having to invent time travel), it might be simpler to just manually instrument your function and log the the results when they are outliers. You'd probably want to use `time.perf_counter()` or `time.clock()`. – pvg Nov 08 '17 at 23:36
  • But I don't know the slow cases until *after* the slow stuff has occurred (something with thread blocking that shouldn't block) – Jason S Nov 09 '17 at 14:35
  • Right. So you add the instrumentation and only store the results when they are slow. You also never mentioned threading or other details about your actual problem. That might be a better avenue for questions with which you can get concrete help. – pvg Nov 09 '17 at 15:05
  • "and only store the results when they are slow" -- how to do that? "You also never mentioned threading or other details about your actual problem. That might be a better avenue for questions with which you can get concrete help." -- but I don't know what's causing the issue; I don't want to add distracting details that may or may not be related to the issue. I'll mention threading. – Jason S Nov 09 '17 at 17:48

0 Answers0