Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Yet Another Python Profiler, but this time multithreading, asyncio and gevent aware.

License

NotificationsYou must be signed in to change notification settings

sumerc/yappi

Repository files navigation

yappi

Yappi

A tracing profiler that ismultithreading, asyncio and gevent aware.

FreePalestine.Dev

From the river to the sea, Palestine will be free

Highlights

  • Fast: Yappi is fast. It is completely written in C and lots of love and care went into making it fast.
  • Unique: Yappi supports multithreaded,asyncio andgevent profiling. Tagging/filtering multiple profiler results has interestinguse cases.
  • Intuitive: Profiler can be started/stopped and results can be obtained from any time and any thread.
  • Standards Compliant: Profiler results can be saved in callgrind or pstat formats.
  • Rich in Feature set: Profiler results can show eitherWall Time or actualCPU Time and can be aggregated from different sessions. Various flags are defined for filtering and sorting profiler results.
  • Robust: Yappi has been around for years.

Motivation

CPython standard distribution comes with three deterministic profilers.cProfile,Profile andhotshot.cProfile is implemented as a C module based onlsprof,Profile is in pure Python andhotshot can be seen as a small subset of a cProfile. The major issue is that all of these profilers lack support for multi-threaded programs and CPU time.

If you want to profile a multi-threaded application, you must give an entry point to these profilers and then maybe merge the outputs. None of these profilers are designed to work on long-running multi-threaded applications. It is also not possible to profile an application that start/stop/retrieve traces on the fly with these profilers.

Now fast forwarding to 2019: With the latest improvements onasyncio library and asynchronous frameworks, most of the current profilers lacks the ability to show correct wall/cpu time or even call count information per-coroutine. Thus we need a different kind of approach to profile asynchronous code. Yappi, with v1.2 introduces the concept ofcoroutine profiling. Withcoroutine-profiling, you should be able to profile correct wall/cpu time and call count of your coroutine. (including the time spent in context switches, too). You can see detailshere.

Installation

Can be installed via PyPI

$ pip install yappi

OR from the source directly.

$ pip install git+https://github.com/sumerc/yappi#egg=yappi

Examples

A simple example:

importyappidefa():for_inrange(10000000):# do something CPU heavypassyappi.set_clock_type("cpu")# Use set_clock_type("wall") for wall timeyappi.start()a()yappi.get_func_stats().print_all()yappi.get_thread_stats().print_all()'''Clock type: CPUOrdered by: totaltime, descname                                  ncall  tsub      ttot      tavgdoc.py:5 a                            1      0.117907  0.117907  0.117907name           id     tid              ttot      scnt_MainThread    0      139867147315008  0.118297  1'''

Profile a multithreaded application:

You can profile a multithreaded application via Yappi and can easily retrieveper-thread profile information by filtering onctx_id withget_func_stats API.

importyappiimporttimeimportthreading_NTHREAD=3def_work(n):time.sleep(n*0.1)yappi.start()threads= []# generate _NTHREAD threadsforiinrange(_NTHREAD):t=threading.Thread(target=_work,args=(i+1, ))t.start()threads.append(t)# wait all threads to finishfortinthreads:t.join()yappi.stop()# retrieve thread stats by their thread id (given by yappi)threads=yappi.get_thread_stats()forthreadinthreads:print("Function stats for (%s) (%d)"% (thread.name,thread.id)    )# it is the Thread.__class__.__name__yappi.get_func_stats(ctx_id=thread.id).print_all()'''Function stats for (Thread) (3)name                                  ncall  tsub      ttot      tavg..hon3.7/threading.py:859 Thread.run  1      0.000017  0.000062  0.000062doc3.py:8 _work                       1      0.000012  0.000045  0.000045Function stats for (Thread) (2)name                                  ncall  tsub      ttot      tavg..hon3.7/threading.py:859 Thread.run  1      0.000017  0.000065  0.000065doc3.py:8 _work                       1      0.000010  0.000048  0.000048Function stats for (Thread) (1)name                                  ncall  tsub      ttot      tavg..hon3.7/threading.py:859 Thread.run  1      0.000010  0.000043  0.000043doc3.py:8 _work                       1      0.000006  0.000033  0.000033'''

Different ways to filter/sort stats:

You can usefilter_callback onget_func_stats API to filter on functions, modulesor whatever available inYFuncStat object.

importpackage_aimportyappiimportsysdefa():passdefb():passyappi.start()a()b()package_a.a()yappi.stop()# filter by module objectcurrent_module=sys.modules[__name__]stats=yappi.get_func_stats(filter_callback=lambdax:yappi.module_matches(x, [current_module]))# x is a yappi.YFuncStat objectstats.sort("name","desc").print_all()'''Clock type: CPUOrdered by: name, descname                                  ncall  tsub      ttot      tavgdoc2.py:10 b                          1      0.000001  0.000001  0.000001doc2.py:6 a                           1      0.000001  0.000001  0.000001'''# filter by function objectstats=yappi.get_func_stats(filter_callback=lambdax:yappi.func_matches(x, [a,b])).print_all()'''name                                  ncall  tsub      ttot      tavgdoc2.py:6 a                           1      0.000001  0.000001  0.000001doc2.py:10 b                          1      0.000001  0.000001  0.000001'''# filter by module namestats=yappi.get_func_stats(filter_callback=lambdax:'package_a'inx.module                             ).print_all()'''name                                  ncall  tsub      ttot      tavgpackage_a/__init__.py:1 a             1      0.000001  0.000001  0.000001'''# filter by function namestats=yappi.get_func_stats(filter_callback=lambdax:'a'inx.name                             ).print_all()'''name                                  ncall  tsub      ttot      tavgdoc2.py:6 a                           1      0.000001  0.000001  0.000001package_a/__init__.py:1 a             1      0.000001  0.000001  0.000001'''

Profile an asyncio application:

You can see that coroutine wall-time's are correctly profiled.

importasyncioimportyappiasyncdeffoo():awaitasyncio.sleep(1.0)awaitbaz()awaitasyncio.sleep(0.5)asyncdefbar():awaitasyncio.sleep(2.0)asyncdefbaz():awaitasyncio.sleep(1.0)yappi.set_clock_type("WALL")withyappi.run():asyncio.run(foo())asyncio.run(bar())yappi.get_func_stats().print_all()'''Clock type: WALLOrdered by: totaltime, descname                                  ncall  tsub      ttot      tavgdoc4.py:5 foo                         1      0.000030  2.503808  2.503808doc4.py:11 bar                        1      0.000012  2.002492  2.002492doc4.py:15 baz                        1      0.000013  1.001397  1.001397'''

Profile a gevent application:

You can use yappi to profile greenlet applications now!

importyappifromgreenletimportgreenletimporttimeclassGreenletA(greenlet):defrun(self):time.sleep(1)yappi.set_context_backend("greenlet")yappi.set_clock_type("wall")yappi.start(builtins=True)a=GreenletA()a.switch()yappi.stop()yappi.get_func_stats().print_all()'''name                                  ncall  tsub      ttot      tavgtests/test_random.py:6 GreenletA.run  1      0.000007  1.000494  1.000494time.sleep                            1      1.000487  1.000487  1.000487'''

Documentation

Related Talks

Special thanks to A.Jesse Jiryu Davis:

PyCharm Integration

Yappi is the default profiler inPyCharm. If you have Yappi installed,PyCharm will use it. Seethe official documentation for more details.


[8]ページ先頭

©2009-2025 Movatter.jp