Skip to main content

optimize-later Build Status Coverage PyPI PyPI - Format PyPI - Django Version

Premature optimization is the root of all evil (or at least most of it) in programming.

-- Donald Knuth

Wouldn't it be nice to have something to tell you when optimization is really necessary?

Enter optimize-later.

Instead of trying to guess what code ought to be optimized, optimize-later times potentially slow blocks of code for you, and calls a user-specified function when it exceeds the specified time limit. This way, you only have to optimize code when speed becomes a problem, saving you from both the evils of premature optimization, and the evils of slow code.

Usage

from optimize_later import optimize_later, register_callback

### Basic usage.
with optimize_later('test_block', 0.2):
    # potentially slow block of code...
    time.sleep(1)

@register_callback
def my_report_function(report):
    # Short one line description.
    print(report.short())

    # Long description with breakdown based on blocks.
    print(report.long())

    # Details available in:
    #   - report.name: block name
    #   - report.limit: time limit
    #   - report.delta: time consumed
    #   - report.blocks: breakdown by blocks
    #   - report.start, report.end: start and end time with an unspecified timer:
    #     useful for building a relative timeline with blocks.

### More advanced uses.
# Automatic block names from file and source line (slightly slow).
with optimize_later(0.2):
    # potentially slow block of code...
    time.sleep(1)

# Always warn. Good for exceptional cases that you suspect should not happen.
with optimize_later():
    # potentially slow block of code...
    time.sleep(1)

# Also available as a decorator.
@optimize_later('bad-function', 0.2)
def function_name():
    # potentially slow function...
    time.sleep(1)

# Will use module:function as block name, if you do not specify a name.
# There is no performance penalty this way, as the function name can be easily detected.
@optimize_later(0.2)
def function_name():
    # potentially slow function...
    time.sleep(1)

### Blocks.
with optimize_later() as o:
    with o.block('block 1'):
        # When the time limit of whole block is exceeded, your report will contain
        # a detailed breakdown by sub-blocks executed. This allows you to pinpoint
        # which exact block is the culprit.
        time.sleep(1)

    # optimize-later will automatically generate a block name for you from file and
    # line number, with a slightly performance penalty.
    with o.block() as b:
        # You can also nest blocks.
        with b.block():
            pass

### Callbacks deregistration and contexts.
from optimize_later import deregister_callback, optimize_context

deregister_callback(my_report_function)

with optimize_context():
    # Register a callback here.
    register_callback(my_report_function)
# Callback is not available here.

@optimize_context
def function():
    # This callback will be available for the duration of this function.
    register_callback(my_report_function)

# Remove global callbacks for this block.
with optimize_context(renew=True):
    pass
# or...
@optimize_context(renew=True)
def function():
    pass

# Shortcut registration syntax.
with optimize_context(my_report_function):
    pass

@optimize_context(my_report_function, renew=True)
def function():
    pass

A sample short report:

Block 'tests.py@152' took 0.011565s (+0.011565s over limit)

A sample long report:

Block 'tests.py@152' took 0.011565s (+0.011565s over limit), children:
  - Block 'tests.py@153' took 0.006662s, children:
      - Block 'tests.py@154' took 0.000002s
      - Block 'tests.py@156' took 0.000002s
  - Block 'tests.py@159' took 0.000001s

Installation

Install the module with:

$ pip install optimize-later

Or if you want the latest bleeding edge version:

$ pip install -e git://github.com/quantum5/optimize-later.git

That's it!

Django

If you are using Django, you might want to configure optimize-later in settings.py instead of adding callbacks directly.

You have to add 'optimize_later' to INSTALLED_APPS.

Then, the list of callbacks as dot-separated import paths can be specified in 'OPTIMIZE_LATER_CALLBACKS' in settings.py. For example:

OPTIMIZE_LATER_CALLBACKS = [
    'myapp.optimize.report',
    'otherapp.optimize.report',
]

Metadata

Release files for optimize-later 0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for optimize-later 0.3
File Size Uploaded Provenance Actions
optimize-later-0.3.tar.gz 8.1 kB Without provenance Details for optimize-later-0.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for optimize-later 0.3
File Interpreter ABI Platform Actions
optimize_later-0.3-py3-none-any.whl Python 3 none any Details for optimize_later-0.3-py3-none-any.whl

Total release size: 18.1 kB

Release files / optimize-later-0.3.tar.gz

Download URL optimize-later-0.3.tar.gz
Size 8.1 kB
Tags Source
SHA-256 checksum
How to use checksums
623c3f8cafa645d12e2d6b8b6223a902a01ff173c284219ccd2fdfeddfb28e36
BLAKE2b-256 checksum
How to use checksums
1292fc9ba2adf53f793d6ce815ab17b065bf99d5beb4dac1646f1d4ed0e810a4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.4.2 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.3

Release files / optimize_later-0.3-py3-none-any.whl

Download URL optimize_later-0.3-py3-none-any.whl
Size 10.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4f6e18a430c63372af20cb51861bf1c15a542174002286d75e1fd5464ffa6ad3
BLAKE2b-256 checksum
How to use checksums
1aeeb1c297ee61123dc0b747bc1dd1edd6f8009d903f508b51d9c1f3c82517c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.4.2 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.3

Security for optimize-later 0.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page