o ]Lb@sdZddlmZmZmZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlmZddlmZmZejZejZgdZhdZd d ZGd d d eZeZGd ddeZGdddeZddZe ZddZ ddZ!da"dDddZ#ddZ$ddZ%dd Z&dEd!d"Z'ed#d$Z(Gd%d&d&eZ)Gd'd(d(Z*dFd*d+Z+d,d-Z,d.d/Z-dEd0d1Z.dGd3d4Z/dHd5d6Z0iZ1d7d8Z2d9d:Z3dId=d>Z4d?d@Z5dEdAdBZ6e7dCkre 8e6dSdS)Ja statprof is intended to be a fairly simple statistical profiler for python. It was ported directly from a statistical profiler for guile, also named statprof, available from guile-lib [0]. [0] http://wingolog.org/software/guile-lib/statprof/ To start profiling, call statprof.start(): >>> start() Then run whatever it is that you want to profile, for example: >>> import test.pystone; test.pystone.pystones() Then stop the profiling and print out the results: >>> stop() >>> display() % cumulative self time seconds seconds name 26.72 1.40 0.37 pystone.py:79:Proc0 13.79 0.56 0.19 pystone.py:133:Proc1 13.79 0.19 0.19 pystone.py:208:Proc8 10.34 0.16 0.14 pystone.py:229:Func2 6.90 0.10 0.10 pystone.py:45:__init__ 4.31 0.16 0.06 pystone.py:53:copy ... All of the numerical data is statistically approximate. In the following column descriptions, and in all of statprof, "time" refers to execution time (both user and system), not wall clock time. % time The percent of the time spent inside the procedure itself (not counting children). cumulative seconds The total number of seconds spent in the procedure, including children. self seconds The total number of seconds spent in the procedure itself (not counting children). name The name of the procedure. By default statprof keeps the data collected from previous runs. If you want to clear the collected data, call reset(): >>> reset() reset() can also be used to change the sampling frequency from the default of 1000 Hz. For example, to tell statprof to sample 50 times a second: >>> reset(50) This means that statprof will sample the call stack after every 1/50 of a second of user + system time spent running on behalf of the python process. When your process is idle (for example, blocking in a read(), as is the case at the listener), the clock does not advance. For this reason statprof is not currently not suitable for profiling io-bound operations. The profiler uses the hash of the code object itself to identify the procedures, so it won't confuse different procedures with the same name. They will show up as two different rows in the output. Right now the profiler is quite simplistic. I cannot provide call-graphs or other higher level information. What you see in the table is pretty much all there is. Patches are welcome :-) Threading --------- Because signals only get delivered to the main thread in Python, statprof only profiles the main thread. However because the time reporting function uses per-process timers, the results can be significantly off if other threads' work patterns are not similar to the main thread's work patterns. )absolute_importdivisionprint_functionN)open)encodingpycompat)sstartsstopsresetsdisplaysprofile> util.py:checkhg.py:dispatch.py:runpager.py:pagecmdcolor.py:colorcmddispatch.py:dispatch.py:dispatchdispatch.py:_dispatchdispatch.py:_runcatchdispatch.py:checkargsextensions.py:closuredispatch.py:runcommanddispatch.py:_runcommandevolve.py:warnobserrorscCs t}|d|d|dfS)Nrr)ostimes)rr4/usr/lib/python3/dist-packages/mercurial/statprof.pyclocksrc@s<eZdZd ddZd ddZddZdd Zed d ZdS) ProfileStateNcCs||d|_dS)Ncpu)resettrackself frequencyrrr__init__s  zProfileState.__init__cCsHd|_d|_|rd||_n t|dsd|_n d|_d|_g|_dS)N)r%g?sample_intervalMbP?r)accumulated_timelast_start_timer&rhasattrremaining_prof_time profile_levelsamplesr!rrrrs   zProfileState.resetcCsN|d|jd|d|jdf}|jd|d|jd|df|_dSNrr)r)r()r" stop_time incrementrrraccumulate_times  zProfileState.accumulate_timecCs|j|jt|jSN)r(timeidxlenr-r"rrrseconds_per_sampleszProfileState.seconds_per_samplecCs|jdkrdSdS)Nsrealrr)r r5rrrr3s zProfileState.timeidxr2) __name__ __module__ __qualname__r$rr1r6propertyr3rrrrrs   rc@sPeZdZiZdZddZddZddZedd Z d d Z d d Z ddZ dS)CodeSite)pathlinenofunctionsourcecCs8t|tsJ||_||_t|tsJ||_d|_dSr2) isinstancebytesr<r=r>r?)r"r<r=r>rrrr$s  zCodeSite.__init__cCs(z |j|jko |j|jkWSYdS)NF)r=r<)r"otherrrr__eq__szCodeSite.__eq__cCst|j|jfSr2)hashr=r<r5rrr__hash__szCodeSite.__hash__cCsB||f}z|j|WSty ||||}||j|<|YSwr2)cacheKeyError)clsr<r=r>kvrrrgets    z CodeSite.getcCs|jdurC|jd}z,t|jd}t|D]\}}||kr%||_nqWdn1s0wYWnY|jdurCd|_|j}t||krV|d|dd}|S)Nrrbs...)r?r=rr< enumeratestripr4)r"lengthr=fpiliner?rrr getsources(     zCodeSite.getsourcecCstj|jSr2)rr<basenamer5rrrfilenamezCodeSite.filenamecCsd||jfS)Nz%s:%srWr>r5rrrskipnamezCodeSite.skipnameN) r7r8r9rF __slots__r$rCrE classmethodrKrUrWrZrrrrr;s   r;c@s$eZdZdZddZeddZdS)SamplestacktimecCs||_||_dSr2r_)r"r`rarrrr$ s zSample.__init__c CsFg}|r|tt|jj|jt|jj|j }|st ||Sr2) appendr;rKrsysbytesf_code co_filenamef_linenoco_namef_backr^)rHframerar`rrr from_frames   zSample.from_frameN)r7r8r9r\r$r]rjrrrrr^s r^cCsZtjdkr+t}t|tjtj}tjt ||t t j tj d|t_dSdS)Nrr%)stater,rr1r(r3r-rbr^rjsignal setitimer ITIMER_PROFr&r))signumrinow timestamprrrprofile_signal_handler$s    rrcCsjts/t}t|t|}tjtj}tj t |||t_ ttjtrtdSr2) stopthreadis_setrrkr1sys_current_framesr(r3r-rbr^rjr)rasleepr&clear)tidrprirqrrr samplerthread3s     rzcCs tjdkSNr)rkr,rrrr is_activeGs r|threadrcs|t_tjd7_tjdkr[tt_tj}dt_|a|dkr3ttjt t tj |p.tj ddS|dkr]t fddtDd}tjt|fd d t_tjdSdSdS) z:Install the profiling signal handler, and start profiling.rNsignalr%r}csg|] \}}|kr|qSrr).0rIfrirr aszstart..rrz)targetargsname)rkr r,rr)r+ lastmechanismrlSIGPROFrrrmrnr&inspect currentframerurvitems threadingThreadrzthreadstart) mechanismr rptryrrrrNs*  rcCstjd8_tjdkrHtdkr&ttjdd}ttjtj|dt_n tdkr3t tj t tdt_tjd}|rHt|tS)z;Stop profiling, and uninstall the profiling signal handler.rrr~r%r}Ns STATPROF_DEST)rkr,rrlrmrnrSIG_IGNr+rssetrjoinr1rr)renvironrK save_data)r statprofpathrrrstophs     rc Cs~t|d0}|dtjtjD]}|j}|j}dd|D}|d|d|fqWddS1s8wYdS)Nw+s%f %f cSs&g|]}d|jd|j|jgqS)s%d)rr<r=r>rsrrrrszsave_data..s%d%s )rwriterkr(r-rar`r)r<filesamplerar`sitesrrrr}s  "rc Cst|d}dd|dDt_gt_|ddD]:}|d}t|d}|dd}g}|D]}|d}|t |dt |d|dq5tjt ||qdS) NrLcSsg|]}t|qSr)float)rvaluerrrrszload_data..rrrr) rread splitlinessplitrkr(r-rrbr;rKintr^) r<linesrTpartsrarawsitesrrawsite sitepartsrrr load_datas    rcCs*tjdks Jdtjt|dS)zClear out the state of the profiler. Do not call while the profiler is running. The optional frequency argument specifies the number of samples to collect per second.rs'Can't reset() while statprof is runningN)rkr,r;rFrxr)r#rrrrs rccs0tz dVWttdSttwr2)rrdisplayrrrrprofiles rc@sPeZdZddZddZddZddZd d Zd d Zd dZ e ddZ dS) SiteStatscCs||_d|_d|_dSr{)site selfcount totalcountr"rrrrr$ zSiteStats.__init__cC|jd7_dSNr)rr5rrraddselfr[zSiteStats.addselfcCrr)rr5rrraddtotalr[zSiteStats.addtotalcC|jttjdSNd)rr4rkr-r5rrr selfpercentzSiteStats.selfpercentcCrr)rr4rkr-r5rrr totalpercentrzSiteStats.totalpercentcC|jtSr2)rrkr6r5rrr selfsecondsrXzSiteStats.selfsecondscCrr2)rrkr6r5rrr totalsecondsrXzSiteStats.totalsecondscCsli}|D]'}t|jD]\}}||}|st|}|||<||dkr*|q qddt|DS)NrcSsg|]}|qSrrrrrrrsz(SiteStats.buildstats..)rOr`rKrrrr itervalues)rHr-statsrrSrsitestatrrr buildstatss  zSiteStats.buildstatsN) r7r8r9r$rrrrrrr]rrrrrrsrc@s(eZdZdZdZdZdZdZdZdZ dS) DisplayFormatsrrrrNrN) r7r8r9ByLineByMethod AboutMethodHotpath FlameGraphJsonChromerrrrrsrrNcKsJ|durt}|durddlm}|j}t|jdkr!|ddS|tjkr,t ||nV|tj kr7t ||nK|tj krFt ||fi|n<|tjkrUt||fi|n-|tjkrdt||fi|n|tjkrot||n|tjkr~t||fi|ntd|tjtjfvr|d|dt|j|d |jdSdS) zz!display_by_line..reversekey%5.5s %10.10s %7.7s %-8.8s s% s cumulativesselfrM%5.5s %9.9s %8.8s %-8.8s stimesecondsrsnames%s:%d:%s%6.2f %9.2f %9.2f %s N) rrr-sortrrrWr=r>rrr)rrRrstatr sitelabelrrrrs2 rc Cs|dd|ddt|j}tt}|D]}||jd|jj |qg}t |D]+\}}d}d} d} |D]}|| 7}| | 7} | |7} q@| ||| | |fq4|jddd d |D]]} | d d krtqk|d | d | d| d| df| djddd d | dD]1}|dkr|jd} tjjd krt| tst | } || |jj| f} |d| qqkdS)zPrint the profiler data with each sample function represented as one row in a table. Important lines within that function are output as nested rows. Sorted by self-time per line.rrrr:rTcS|dS)NrrrrrrrOrz#display_by_method..rrN皙?rrrrcSrr2r)rSrrrr^rs%33.0f%% %6.2f line %d: %s N)rrrr- defaultdictlistrrWr>rbr iteritemsrrrrrUru version_infomajorr@rAbytestrr=)rrRrgroupedr functiondatafname sitestats total_cum_sectotal_self_sec total_percentr>r? stattuplerrrr,sp "        rc sHdurtdddvrd\d}i}i}|jD]O}t|jD]G\}} | jkrlr6| krl|d7}|t|jdkr[|j|d} | |vrW|| d|| <nd|| <| |vrh|| d|| <q%d|| <q%qddt |D}|j ddd d |D]$\} } | d | |d t | t | j| jt | d fqt|j} fdd| D} d} d}d}d}| D]}| |7} ||7}||7}||7}q| dt pdt | |||fddt |D}|j ddd d |D]\}} | d| |d |jt |d fqdS)NzInvalid functionrrrcSg|]\}}||fqSrr)rparentcountrrrrz(display_about_method..TcSrrrrrrrrrz&display_about_method..rs%6.2f%% %s:%s line %s: %s r2cs.g|]}|jjkrr|jkr|qSr)rr>rWrrYrrrs sA %s:%s Total: %0.2fs (%0.2f%%) Self: %0.2fs (%0.2f%%) s___cSrrr)rchildrrrrrrcSrrrrrrrrrs %6.2f%% line %s: %s )rrr-rOr`r>rWr4rrrrfsencodercr=rUrrrrrr)rrRr>rrelevant_samplesparentschildrenrrSrrrrrrtotal_self_percenttotal_cum_percentrrrrYrrrs               rrc sGfdddtd|jdj}|jD]}|jddd|j||j}q|ddfddjdkrIdd dSdS) Ncs eZdZddZfddZdS)z display_hotpath..HotNodecSs||_d|_i|_dSr{)rrr rrrrr$rz)display_hotpath..HotNode.__init__cs|j|7_|d}|j|}|s|}||j|<t|dkrXd}|t|krD||tvrD|d7}|t|krD||tvs2|t|krV|||d|dSdS|j|7_dSr.)rr rKr4rZskipsadd)r"r`rarrrSHotNoderrrs    z$display_hotpath..HotNode.addN)r7r8r9r$rrrrrrsrrshowtimeTc s|j}fddt|jD}|r|dd}|dd}|j}d||r-dnd d r8d |jndd }||jjd ||f} tddt | } d} | dkr[d} d} | | d | |j dtddt t |j | df} | | }tddt|jD}|j|djkrd|d}n |j|dkrd|d}|d|}t |dks|r|d7}|jdddd|D] }||t |dkqdS)Ncs g|] }|jjkr|qSrrrc)limitrootrrrs z3display_hotpath.._write..rrrrM\|s %4.1f%%s %5.2fss %s %srr7s, s %s%s %d: %s%sslinercSg|]}|jqSrrrrrrrg?sss TcSs|jSr2rrrrrr"sz1display_hotpath.._write..r)rrrr rWljustr>rmaxr4rjustr=strrUsumrr)nodedepthmultiple_siblingsrvisiblechildrenindentrWr> listpattern liststring spacing_lenprefix codepattern codestring finalstringchildrensamplesnewdepthr)_writerRrrrrrr5sf     zdisplay_hotpath.._writeF)objectr-rarr`rKr)rrRrrlasttimerr)rr5rRrrrrrs    <rc Ks|dur tjdd}tj|s|d||ddSi}|jD]$}dd|jD}|d |}||vrD||d||<q$d||<q$t \} } t | d } t |D] \}} | d || fqZWdn1srwY|dur}d }td | |f|d |dS)NsHOMEs/flamegraph.plserror: missing %s s8get it here: https://github.com/brendangregg/FlameGraph cSrr)r>rrrrr4r z"write_to_flame..;rrs%s %d s~/flamegraph.svgsperl ~/flamegraph.pl %s > %ssWritten to %s )rrrr<existsrr-r`rrrmkstemprrsystem) rrR scriptpath outputfilerrrrrTfdr<rrrrrr*s0       rcCsj|tvrt|Stjtjdd}|gtjD]}|tj}||r.|t |d}nq|t|<|S)zAttempt to make the path to a Python module easier to read by removing whatever part of the Python search path it was found on.rrN) _pathcacher__file__rsplitrseprur< startswithr4)r<hgpathpr/rrr simplifypathLs  rFc Cs~g}|jD]#}g}|jD]}|t|j|jt|jfq ||j|fqt |}t |t s8| d}||dS)Nutf-8)r-r`rbrsysstrr<r=r>rajsondumpsr@rAencoder)rrRr-rr`rirrrr]s       r{Gzt?+?c sgtti g fdd dt|jdj|jdj}|t| f dd}|jD]rtdd jD}t|}|krYqCry|ryd|dkry|ry|ryd|dkser|s{t |D]+} jt f ||\} } t}  t d | | jd | dd qt|qCr|sfd dtD} tdd tD} tjt | | ddd}t|ts|d}|||ddS)Ncsv|sdS|vr |S|dd}t}||<t|ddd|dd|dur9dj|d|S)Nrrz%s %s)categoryrr)r)r4rbdictupdate)r`rmyid)id2stackstack2idstackidrrrTs"z write_to_chrome..stackidr'rrc st}\}}\}}j|}|kr!kr.poplastcss6|]}dtt|j|jft|jfVqdS)z%s:%dN)rFrrHr<r=r>)rrirrr s  z"write_to_chrome..BrV)rWrrXrZrYr[csg|] \}}|vr|qSrr)ridxr)rerrrsz#write_to_chrome..css |] \}}t||fVqdSr2)r%)rrIrJrrrrls ) traceEvents stackFramesr)r+rGr!) collectionsdequerr-rar#r\r`popreversed appendleftr4rbrOrO OrderedDictrIrJr@rArKr)rrRrjri totaltimerkr`qstackrr<rsideventsframesr) rerfrRrgrhrirjrr-rSrTrrust            rcCs tddS)Na The statprof command line allows you to inspect the last profile's results in the following forms: usage: hotpath [-l --limit percent] Shows a graph of calls with the percent of time each takes. Red calls take over 10%% of the total time themselves. lines Shows the actual sampled lines. functions Shows the samples grouped by function. function [filename:]functionname Shows the callers and callees of a particular function. flame [-s --script-path] [-o --output-file path] Writes out a flamegraph to output-file (defaults to ~/flamegraph.svg) Requires that ~/flamegraph.pl exist. (Specify alternate script path with --script-path.))printrrrr printusagesr}c Cs|durtj}t|dkrtdSi}d}d|d<|ddkr&tj|d<n=|ddkr2tj|d<n1|ddkr>tj|d<n%|dd krRtj|d<|d|d<d }n|dd kr^tj |d<ntdSzt tj|dd gd \}}Wnt j y}zt|tWYd}~dSd}~wwd|d<d}|D]7\}}|dvrt||d<q|dvr|}q|dvr||d<q|dvr||d<q|dvrtdSJd||stddSt|dtdit |dS)Nrrrsfunctionhotpathsformatr functionsr>rNflames hl:f:o:p:)shelpslimit=sfile=s output-file=s script-path=rslimit)z-lz--limit)z-fz--file)z-oz --output-files outputfile)z-pz --script-paths scriptpath)z-hhelpFzunhandled option %szmust specify --file to load)r<r)ruargvr4r}rrrrrrrgetoptbgetopterrorr|rrr strkwargs) r displayargsoptstartoptsrmsgr<orrrrmainsn                   r__main__)r}rr2)NrNN)r)NN)rLrM)9__doc__ __future__rrrrq contextlibrrrIrrlrurrarrrrcontextmanager__all__rrr6rrkr;r^rrEventrsrzr|rrrrrrrrrrrrrrrr?rFrrr}rr7exitrrrrshP  -:     + $ F W a x D