Skip to main content

Estimate Asymptotic Runtime Complexity from Bytecode executions

Project description

The Python Performance Analysis Library (py-pal) is a profiling tool for the Python programming language. Further details can be found in the documentation at https://py-pal.readthedocs.io.

Installation

Requirements

Install py-pal via pip by running:

This project requires CPython and a C compiler to run. Install CPython >= 3.7, then install py-pal by running:

pip install py-pal

or

python -m pip install py-pal

Development Environment

To set up an environment for developing the py-pal module, the requirements mentioned in the section Installation must be met. Then

  1. Clone this repository locally with git

  2. Navigate to the cloned repository

  3. Create a virtual environment

    python -m venv .venv

  4. Activate the virtual environment

    On Microsoft Windows run: .venv\Scripts\activate.bat On Linux run: source venv/bin/activate

  5. Install the dependencies for the development environment

    pip install -r dev-requirements.txt

    or

    python -m pip install -r dev-requirements

Building the py-pal module

python setup.py develop

With this command, the C extensions are compiled using Cython. Also, it packages all necessary files together and installs them in the current virtual environment.

Note, any change to a cython file (.pyx) requires recompilation, i.e. the above command must be executed again.

Attention, if it is not possible to install Cython by this command, the cython files (.pyx) are not taken into account. This results in the circumstance that the corresponding C/C++ files are not generated and thus, the old C/C++ files get used to build the C extensions. Directly speaking, changes to the cython files will have no effect because they are not processed!

Run all regular tests from the command line

pytest tests

Run all Cython tests from the command line

pytest tests_cython

Run all regular and Cython tests together from the command line

pytest

Command line usage of the py-pal module

python -m py_pal <target-module/file>

or

py-pal <target-module/file>

There are multiple aliases to the same command: py-pal, py_pal and pypal

See the help message:

py-pal -h

Programmatic usage of the py-pal module

The profile decorator:

from py_pal.core import profile

@profile
def test():
    pass

By using the profile decorator, it is possible to annotate Python functions such that only the annotated Python functions will be profiled. It acts similar to a whitelist filter.

Another possibility is to use the context manager protocol:

from py_pal.estimator import AllArgumentEstimator
from py_pal.tracer import Tracer

with Tracer() as t:
    pass

estimator = AllArgumentEstimator(t)
res = estimator.export()

# Do something with the resulting DataFrame
print(res)

The most verbose way to use the py-pal API:

from py_pal.estimator import AllArgumentEstimator
from py_pal.tracer import Tracer


t = Tracer()
t.trace()

# Your function
pass

t.stop()
estimator = AllArgumentEstimator(t)
res = estimator.export()

# Do something with the resulting DataFrame
print(res)

All examples instantiate a tracer object that is responsible for collecting the data. After execution, the collected data is passed to the analysis module. Finally, an estimate of the asymptotic runtime of the functions contained in the code is obtained.

Modes

In the current version py-pal offers only the profiling mode. Although py_pal.datagen offers some functions for generating inputs, py-pal must be combined with appropriate test cases to realize a performance testing mode. An automatic detection and generation of appropriate test inputs does not exist at the moment.

Limitations

The profiling approach implemented by the py-pal modules does not distinguish between different threads executing a Python function. Actually it is a major problem to profile a Python script which makes use of threads. The bytecode counting strategy will increase all counters of Python functions on the current call stack no matter what threads is executing it. Thus, the data points will not be accurate to what really happened during the profiled execution of the script.

Licensing Notes

This work integrates some code from the big_O project. More specifically, most code in py_pal.complexity, py_pal.datagen and py_pal.estimator.Estimator.infer_complexity is adapted from bigO.

What’s New in Py-PAL 1.0.0

  • More thorough testing from different combinations of requirements and Python versions.

  • Bug fixes

What’s New in Py-PAL 0.2.1

Refactoring

The estimator module was refactored which introduces a slight change to the API. Classes inheriting from Estimator now only specify how to transform the collected data with respect to the arguments of the function.

Instead of ComplexityEstimator you should use the AllArgumentEstimator class. Additionally there is the SeparateArgumentEstimator which is experimental.

What’s New in Py-PAL 0.1.6

More accurate Data Collection

The Tracer is enhanced by measuring builtin function calls with AdvancedOpcodeMetric.

Opcodes resembling a function call .e.g FUNCTION_CALL are filtered for built in function calls. If the called function is found in the complexity mapping a synthetic Opcode weight gets assigned. A builtin function call is evaluated using its argument and a pre-defined runtime complexity e.g. O(n log n) for sort().

  • The feature is enabled by default

  • The calculation produces a performance overhead and can be disabled by providing a OpcodeMetric instance to the Tracer

  • The AdvancedOpcodeMetric instance assigned to the Tracer provides statistics about how many builtin function calls were observed and how many were found in the complexity map

Bugfixes

  • Cleaning data after normalization introduced wrong data points

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py-pal-1.0.2.tar.gz (174.0 kB view hashes)

Uploaded Source

Built Distributions

py_pal-1.0.2-cp39-cp39-manylinux2014_x86_64.whl (744.5 kB view hashes)

Uploaded CPython 3.9

py_pal-1.0.2-cp39-cp39-manylinux2010_x86_64.whl (746.9 kB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.12+ x86-64

py_pal-1.0.2-cp39-cp39-manylinux1_x86_64.whl (746.9 kB view hashes)

Uploaded CPython 3.9

py_pal-1.0.2-cp38-cp38-manylinux2014_x86_64.whl (779.4 kB view hashes)

Uploaded CPython 3.8

py_pal-1.0.2-cp38-cp38-manylinux2010_x86_64.whl (778.2 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.12+ x86-64

py_pal-1.0.2-cp38-cp38-manylinux1_x86_64.whl (778.2 kB view hashes)

Uploaded CPython 3.8

py_pal-1.0.2-cp37-cp37m-manylinux2014_x86_64.whl (697.5 kB view hashes)

Uploaded CPython 3.7m

py_pal-1.0.2-cp37-cp37m-manylinux2010_x86_64.whl (689.0 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.12+ x86-64

py_pal-1.0.2-cp37-cp37m-manylinux1_x86_64.whl (689.0 kB view hashes)

Uploaded CPython 3.7m

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page