<commit_before>pyinstrument
============

A Python profiler that records the call stack of the executing code, instead
of just the final function in it.

![Screenshot](screenshot.jpg)

It uses a **statistical profiler**, meaning the code samples the stack
periodically (every 1 ms). This is lower overhead than event-
based profiling (as done by `profile` and `cProfile`).

This module is still very young, so I'd love any feedback/bug reports/pull
requests!

Installation
------------

    pip install -e git+https://github.com/joerick/pyinstrument.git#egg=pyinstrument

Usage
-----

-   **Command-line**

    You can call pyinstrument directly from the command line.

        python -m pyinstrument myscript.py [args...]

    This will run `myscript.py` to completion or until you interrupt it, and 
    then output the call tree.

-   **Django**
    
    Add `pyinstrument.middleware.ProfilerMiddleware` to `MIDDLEWARE_CLASSES`.
    If you want to profile your middleware as well as your view (you probably
    do) then put it at the start of the list.

    Then add `?profile` to the end of the request URL to activate the
    profiler.

-   **Python**

        from pyinstrument import Profiler

        profiler = Profiler() # or Profiler(use_signal=False), see below
        profiler.start()

        # code you want to profile

        profiler.stop()

        print(profiler.output_text(unicode=True, color=True))

    You can omit the `unicode` and `color` flags if your output/terminal does
    not support them.

Signal or setprofile mode?
--------------------------

On Mac/Linux/Unix, pyinstrument can run in 'signal' mode. This uses OS-
provided signals to interrupt the process every 1ms and record the stack. This
gives much lower overhead (and thus accurate) readings than the standard
Python [`sys.setprofile`][setprofile] style profilers. **However, this can
only profile the main thread**.

On Windows and on multi-threaded applications, a `setprofile` mode is
available by passing `use_signal=False` to the Profiler constructor. It works
exactly the same as the signal mode, but has higher overhead. See the below
table for an example of the amount of overhead.

[setprofile]: https://docs.python.org/2/library/sys.html#sys.setprofile

                           | Django template render × 4000 | Overhead
---------------------------|------------------------------:|---------:
Base                       |                         1.46s | 
                           |                               |
pyinstrument (signal)      |                         1.84s |      26%
cProfile                   |                         2.18s |      49%
pyinstrument (setprofile)  |                         5.33s |     365%
profile                    |                        25.39s |    1739%<commit_msg>Fix README formatting<commit_after>pyinstrument
============

A Python profiler that records the call stack of the executing code, instead
of just the final function in it.

![Screenshot](screenshot.jpg)

It uses a **statistical profiler**, meaning the code samples the stack
periodically (every 1 ms). This is lower overhead than event-
based profiling (as done by `profile` and `cProfile`).

This module is still very young, so I'd love any feedback/bug reports/pull
requests!

Installation
------------

    pip install -e git+https://github.com/joerick/pyinstrument.git#egg=pyinstrument

Usage
-----

-   **Command-line**

    You can call pyinstrument directly from the command line.

        python -m pyinstrument myscript.py [args...]

    This will run `myscript.py` to completion or until you interrupt it, and 
    then output the call tree.

-   **Django**
    
    Add `pyinstrument.middleware.ProfilerMiddleware` to `MIDDLEWARE_CLASSES`.
    If you want to profile your middleware as well as your view (you probably
    do) then put it at the start of the list.

    Then add `?profile` to the end of the request URL to activate the
    profiler.

-   **Python**

    ```python
    from pyinstrument import Profiler

    profiler = Profiler() # or Profiler(use_signal=False), see below
    profiler.start()

    # code you want to profile

    profiler.stop()

    print(profiler.output_text(unicode=True, color=True))
    ```

    You can omit the `unicode` and `color` flags if your output/terminal does
    not support them.

Signal or setprofile mode?
--------------------------

On Mac/Linux/Unix, pyinstrument can run in 'signal' mode. This uses OS-
provided signals to interrupt the process every 1ms and record the stack. This
gives much lower overhead (and thus accurate) readings than the standard
Python [`sys.setprofile`][setprofile] style profilers. **However, this can
only profile the main thread**.

On Windows and on multi-threaded applications, a `setprofile` mode is
available by passing `use_signal=False` to the Profiler constructor. It works
exactly the same as the signal mode, but has higher overhead. See the below
table for an example of the amount of overhead.

[setprofile]: https://docs.python.org/2/library/sys.html#sys.setprofile

                           | Django template render × 4000 | Overhead
---------------------------|------------------------------:|---------:
Base                       |                         1.46s | 
                           |                               |
pyinstrument (signal)      |                         1.84s |      26%
cProfile                   |                         2.18s |      49%
pyinstrument (setprofile)  |                         5.33s |     365%
profile                    |                        25.39s |    1739%
{'fraction_non_alphanumeric': 0.11399147727272728, 'fraction_numerical': 0.012073863636363636, 'mean_word_length': 2.0933552992861064, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2158988', 'n_tokens_mistral': 1556, 'n_tokens_neox': 1456, 'n_words': 598}