mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 09:17:30 +03:00
85be37794d
Summary: Previously, traceprof hashes frames using their raw memory addresses, which causes a same frame (same traceback) being recorded multiple times because of memory address change. That's for low overhead because hashing all the way back to the top frame is slow. This patch implements slow frame hashing and de-duplication so the output could look tidier in some cases. The slow de-duplication runs after profiling ends so it won't affect profiling accuracy. Test Plan: Trace IPython, before: ``` 6211 \ run posix.py:50 6152 \ call_inputhook (10 times) inputhook.py:60 .... 6147 \ select_fds (10 times) select.py:194 6 \ select select.py:85 6 | select select.py:179 501 \ select select.py:85 * 501 | select select.py:179 3775 \ select select.py:85 * 3775 | select select.py:179 * 627 \ select (2 times) select.py:85 736 \ select (3 times) select.py:85 * 736 | select (6 times) select.py:179 501 \ select select.py:85 * 501 | select (2 times) select.py:179 ``` After: ``` 4397 \ run posix.py:50 4350 \ call_inputhook (4 times) inputhook.py:60 4349 | select_fds (4 times) select.py:194 4348 | select (4 times) select.py:85 * 4348 | select (8 times) select.py:179 ``` Reviewers: #mercurial, rmcelroy Reviewed By: rmcelroy Subscribers: mjpieters Differential Revision: https://phabricator.intern.facebook.com/D5112561 Signature: t1:5112561:1495562165:bf86c3283156d3b67918706dc875e6d3e28eac18
68 lines
1.7 KiB
Cython
68 lines
1.7 KiB
Cython
# distutils: language = c++
|
|
|
|
# traceprof.pyx - C++ to Python bridge for the traceprof Mercurial extension
|
|
#
|
|
# Copyright 2017 Facebook, Inc.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
"""accurate callgraph profiling
|
|
|
|
lsprof's high precision, plus statprof's intuitive output format.
|
|
|
|
Config::
|
|
|
|
[traceprof]
|
|
# whether to disable Python GC before profiling
|
|
disablegc = no
|
|
|
|
# minimal microseconds to show a function
|
|
timethreshold = 2000
|
|
|
|
# minimal call count to show "(N times)"
|
|
countthreshold = 2
|
|
|
|
# frame de-duplication (slower to print outputs)
|
|
framededup = yes
|
|
"""
|
|
|
|
from libc.stdio cimport FILE
|
|
from cpython.object cimport PyObject
|
|
|
|
import contextlib
|
|
import gc
|
|
|
|
cdef extern from "traceprofimpl.cpp":
|
|
void enable()
|
|
void disable()
|
|
void report(FILE *)
|
|
void settimethreshold(double)
|
|
void setcountthreshold(size_t)
|
|
void setdedup(int)
|
|
void clear()
|
|
|
|
cdef extern from "Python.h":
|
|
FILE* PyFile_AsFile(PyObject *p)
|
|
|
|
@contextlib.contextmanager
|
|
def profile(ui, fp):
|
|
if ui is not None:
|
|
if ui.configbool('traceprof', 'disablegc'):
|
|
gc.disable() # slightly more predictable
|
|
microseconds = ui.configint('traceprof', 'timethreshold')
|
|
if microseconds is not None:
|
|
settimethreshold((<double>microseconds) / 1000.0)
|
|
count = ui.configint('traceprof', 'countthreshold')
|
|
if count is not None:
|
|
setcountthreshold(count)
|
|
dedup = ui.configbool('traceprof', 'framededup', True)
|
|
setdedup(<int>dedup)
|
|
enable()
|
|
try:
|
|
yield
|
|
finally:
|
|
disable()
|
|
report(PyFile_AsFile(<PyObject *>fp))
|
|
clear()
|