scope-timer


Namescope-timer JSON
Version 0.1.1 PyPI version JSON
download
home_pageNone
SummaryA lightweight profiler to measure execution time with a rich and colorful hierarchical report.
upload_time2025-08-03 16:23:20
maintainerNone
docs_urlNone
authorskst328
requires_python>=3.10
licenseMIT License
keywords performance profiler rich scope timer timing
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![CI](https://github.com/skst328/scope-timer/actions/workflows/ci.yml/badge.svg)


# scope-timer

A lightweight profiler to measure execution time with a rich and colorful hierarchical report.

`scope-timer` makes it easy to find performance bottlenecks in your Python code by timing specific sections and presenting the results in a beautiful, hierarchical tree. It's designed to be simple to use and have minimal overhead.

## Key Features

* **Simple and Intuitive API**: Use decorators (`@ScopeTimer.profile(...)`) or context managers (`with ScopeTimer.profile(...)`) to profile code blocks effortlessly.
* **Hierarchical Reports**: Understand performance bottlenecks in nested function calls and scopes.
* **Multiple Outputs**: View reports directly in the console, or save them as plain text or interactive HTML files.
* **Rich & Colorful**: Powered by the `rich` library for beautiful and readable terminal output.
* **Lightweight & Predictable**: Low memory overhead and linear performance scaling, suitable for complex applications.
* **Thread-Safe**: Profile multi-threaded applications without interference between threads.

## Installation

```bash
pip install scope-timer
```

## Usage

You can easily profile functions and code blocks. Here is a simple example of a multi-stage pipeline:

```python
from scope_timer import ScopeTimer
import time

@ScopeTimer.profile("preprocess")
def preprocess():
    with ScopeTimer.profile("load_data"):
        time.sleep(0.01)
    with ScopeTimer.profile("clean_data"):
        time.sleep(0.015)

@ScopeTimer.profile("compute")
def compute():
    for _ in range(10):
        with ScopeTimer.profile("matmul"):
            time.sleep(0.001)
        with ScopeTimer.profile("activation"):
            time.sleep(0.0005)

@ScopeTimer.profile("postprocess")
def postprocess():
    with ScopeTimer.profile("save_results"):
        time.sleep(0.005)

# Profile the entire pipeline
with ScopeTimer.profile("pipeline"):
    preprocess()
    compute()
    postprocess()

# Print the summary to the console
ScopeTimer.summarize(verbose=True)

# You can also save the report to a file
ScopeTimer.save_html("timer_report.html")
```

## Example Output

The following console output shows a structured report with elapsed time, number of calls, and percentage of parent scope.

<p align="center">
  <img src="https://raw.githubusercontent.com/skst328/scope-timer/main/images/screenshot.png" alt="ScopeTimer Console Output" width="400">
</p>

## Limitations

Currently, `scope-timer` does **not support** `asyncio`.

This is because timer state is tracked **per thread**, but `asyncio` runs multiple tasks **within a single thread**, frequently switching execution contexts using `await`. As a result:

- Profiling an `async def` function with `@ScopeTimer.profile` may produce **incorrect timing** or even raise `ValueError`.
- Using `ScopeTimer.profile(...)` across an `await` boundary is **not safe**.

> For now, `scope-timer` is intended for synchronous or multi-threaded code only.

Support for async contexts (e.g., `contextvars`) may be considered in a future release.

## Performance

`scope-timer` is designed to be lightweight with predictable performance.
The following graphs show the memory usage and report generation time when profiling a realistic, multi-stage pipeline.

<p align="center"> <img src="https://raw.githubusercontent.com/skst328/scope-timer/main/images/scope_timer_performance.png" alt="ScopeTimer Performance Graph" width="90%"> </p>

This benchmark simulates a typical pipeline structure consisting of the following:

* `preprocess`: stage with 2 sub-tasks
* `compute`: stage with 1 sub-task and 20 repeated prediction scopes
* `postprocess`: stage with a result-saving scope

The full pipeline is executed multiple times (10–1000 iterations), and ScopeTimer.summarize() is called once at the end.

As shown:

* Memory usage increases linearly and remains well under 3MB for 1000 pipeline runs.
* Execution time for summarize() stays under 10ms for large workloads.

This ensures stable and low overhead behavior even in performance-critical applications.



## API Overview

All methods are static and can be called directly from the `ScopeTimer` class.

### Core Profiling Methods


* `ScopeTimer.profile(name: str)`

  The recommended way to profile a block of code. It can be used as a context manager (`with`) or a decorator (`@`). It automatically handles starting and stopping the timer.

  Parameters:
  - `name (str)`: The identifier for the scope.

* `ScopeTimer.begin(name: str)`

  Manually starts a timer scope. This is useful in situations where a context manager or decorator cannot be used. Each `begin()` call must be paired with a corresponding `end()` call.

  Parameters:
  - `name (str)`: The identifier for the scope to start.

* `ScopeTimer.end(name: str)`

  Manually stops the currently active timer scope.

  Parameters:
  - `name (str)`: The identifier for the scope to end. Must match the name of the currently active scope.

### Reporting Methods

* `ScopeTimer.summarize(time_unit="auto", precision="auto", divider="rule", verbose=False)`

  Prints a formatted summary of timing results to the console.

  Parameters:
  - `time_unit (str)`: The display unit for time. Can be `'auto'`, `'s'`, `'ms'`, or `'us'`. Defaults to `'auto'`.
  - `precision (int | str)`: The number of decimal places for time values. Defaults to `'auto'`.
  - `divider (str)`: The style of the separator between root scopes. Can be `'rule'` or `'blank'`. Defaults to `'rule'`.
  - `verbose (bool)`: If True, displays detailed statistics (min, max, avg, var). Defaults to `False`.

* `ScopeTimer.save_txt(file_path, **kwargs)`

  Saves a summary of timing results as a plain text file.

  Parameters:
  - `file_path (str | Path)`: The path to the output file.
  - `**kwargs`: Accepts the same arguments as `summarize()` (`time_unit`, `precision`, `verbose`).

* `ScopeTimer.save_html(file_path, **kwargs)`

  Saves a summary of timing results as a themed HTML file.

  Parameters:
  - `file_path (str | Path)`: The path to the output file.
  - `**kwargs`: Accepts the same arguments as `summarize()` (`time_unit`, `precision`, `verbose`).

### Utility Methods

* `ScopeTimer.reset()`

  Resets all recorded timer data, clearing all scopes and measurements. Use this to start a fresh set of measurements within the same process.


## License

This project is licensed under the MIT License.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "scope-timer",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "performance, profiler, rich, scope, timer, timing",
    "author": "skst328",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/46/a7/107a20f00ed7ff2efe09e17abdbf16ce50f3c9b26ca8c51f29e68c8ae867/scope_timer-0.1.1.tar.gz",
    "platform": null,
    "description": "[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n![CI](https://github.com/skst328/scope-timer/actions/workflows/ci.yml/badge.svg)\n\n\n# scope-timer\n\nA lightweight profiler to measure execution time with a rich and colorful hierarchical report.\n\n`scope-timer` makes it easy to find performance bottlenecks in your Python code by timing specific sections and presenting the results in a beautiful, hierarchical tree. It's designed to be simple to use and have minimal overhead.\n\n## Key Features\n\n* **Simple and Intuitive API**: Use decorators (`@ScopeTimer.profile(...)`) or context managers (`with ScopeTimer.profile(...)`) to profile code blocks effortlessly.\n* **Hierarchical Reports**: Understand performance bottlenecks in nested function calls and scopes.\n* **Multiple Outputs**: View reports directly in the console, or save them as plain text or interactive HTML files.\n* **Rich & Colorful**: Powered by the `rich` library for beautiful and readable terminal output.\n* **Lightweight & Predictable**: Low memory overhead and linear performance scaling, suitable for complex applications.\n* **Thread-Safe**: Profile multi-threaded applications without interference between threads.\n\n## Installation\n\n```bash\npip install scope-timer\n```\n\n## Usage\n\nYou can easily profile functions and code blocks. Here is a simple example of a multi-stage pipeline:\n\n```python\nfrom scope_timer import ScopeTimer\nimport time\n\n@ScopeTimer.profile(\"preprocess\")\ndef preprocess():\n    with ScopeTimer.profile(\"load_data\"):\n        time.sleep(0.01)\n    with ScopeTimer.profile(\"clean_data\"):\n        time.sleep(0.015)\n\n@ScopeTimer.profile(\"compute\")\ndef compute():\n    for _ in range(10):\n        with ScopeTimer.profile(\"matmul\"):\n            time.sleep(0.001)\n        with ScopeTimer.profile(\"activation\"):\n            time.sleep(0.0005)\n\n@ScopeTimer.profile(\"postprocess\")\ndef postprocess():\n    with ScopeTimer.profile(\"save_results\"):\n        time.sleep(0.005)\n\n# Profile the entire pipeline\nwith ScopeTimer.profile(\"pipeline\"):\n    preprocess()\n    compute()\n    postprocess()\n\n# Print the summary to the console\nScopeTimer.summarize(verbose=True)\n\n# You can also save the report to a file\nScopeTimer.save_html(\"timer_report.html\")\n```\n\n## Example Output\n\nThe following console output shows a structured report with elapsed time, number of calls, and percentage of parent scope.\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/skst328/scope-timer/main/images/screenshot.png\" alt=\"ScopeTimer Console Output\" width=\"400\">\n</p>\n\n## Limitations\n\nCurrently, `scope-timer` does **not support** `asyncio`.\n\nThis is because timer state is tracked **per thread**, but `asyncio` runs multiple tasks **within a single thread**, frequently switching execution contexts using `await`. As a result:\n\n- Profiling an `async def` function with `@ScopeTimer.profile` may produce **incorrect timing** or even raise `ValueError`.\n- Using `ScopeTimer.profile(...)` across an `await` boundary is **not safe**.\n\n> For now, `scope-timer` is intended for synchronous or multi-threaded code only.\n\nSupport for async contexts (e.g., `contextvars`) may be considered in a future release.\n\n## Performance\n\n`scope-timer` is designed to be lightweight with predictable performance.\nThe following graphs show the memory usage and report generation time when profiling a realistic, multi-stage pipeline.\n\n<p align=\"center\"> <img src=\"https://raw.githubusercontent.com/skst328/scope-timer/main/images/scope_timer_performance.png\" alt=\"ScopeTimer Performance Graph\" width=\"90%\"> </p>\n\nThis benchmark simulates a typical pipeline structure consisting of the following:\n\n* `preprocess`: stage with 2 sub-tasks\n* `compute`: stage with 1 sub-task and 20 repeated prediction scopes\n* `postprocess`: stage with a result-saving scope\n\nThe full pipeline is executed multiple times (10\u20131000 iterations), and ScopeTimer.summarize() is called once at the end.\n\nAs shown:\n\n* Memory usage increases linearly and remains well under 3MB for 1000 pipeline runs.\n* Execution time for summarize() stays under 10ms for large workloads.\n\nThis ensures stable and low overhead behavior even in performance-critical applications.\n\n\n\n## API Overview\n\nAll methods are static and can be called directly from the `ScopeTimer` class.\n\n### Core Profiling Methods\n\n\n* `ScopeTimer.profile(name: str)`\n\n  The recommended way to profile a block of code. It can be used as a context manager (`with`) or a decorator (`@`). It automatically handles starting and stopping the timer.\n\n  Parameters:\n  - `name (str)`: The identifier for the scope.\n\n* `ScopeTimer.begin(name: str)`\n\n  Manually starts a timer scope. This is useful in situations where a context manager or decorator cannot be used. Each `begin()` call must be paired with a corresponding `end()` call.\n\n  Parameters:\n  - `name (str)`: The identifier for the scope to start.\n\n* `ScopeTimer.end(name: str)`\n\n  Manually stops the currently active timer scope.\n\n  Parameters:\n  - `name (str)`: The identifier for the scope to end. Must match the name of the currently active scope.\n\n### Reporting Methods\n\n* `ScopeTimer.summarize(time_unit=\"auto\", precision=\"auto\", divider=\"rule\", verbose=False)`\n\n  Prints a formatted summary of timing results to the console.\n\n  Parameters:\n  - `time_unit (str)`: The display unit for time. Can be `'auto'`, `'s'`, `'ms'`, or `'us'`. Defaults to `'auto'`.\n  - `precision (int | str)`: The number of decimal places for time values. Defaults to `'auto'`.\n  - `divider (str)`: The style of the separator between root scopes. Can be `'rule'` or `'blank'`. Defaults to `'rule'`.\n  - `verbose (bool)`: If True, displays detailed statistics (min, max, avg, var). Defaults to `False`.\n\n* `ScopeTimer.save_txt(file_path, **kwargs)`\n\n  Saves a summary of timing results as a plain text file.\n\n  Parameters:\n  - `file_path (str | Path)`: The path to the output file.\n  - `**kwargs`: Accepts the same arguments as `summarize()` (`time_unit`, `precision`, `verbose`).\n\n* `ScopeTimer.save_html(file_path, **kwargs)`\n\n  Saves a summary of timing results as a themed HTML file.\n\n  Parameters:\n  - `file_path (str | Path)`: The path to the output file.\n  - `**kwargs`: Accepts the same arguments as `summarize()` (`time_unit`, `precision`, `verbose`).\n\n### Utility Methods\n\n* `ScopeTimer.reset()`\n\n  Resets all recorded timer data, clearing all scopes and measurements. Use this to start a fresh set of measurements within the same process.\n\n\n## License\n\nThis project is licensed under the MIT License.\n",
    "bugtrack_url": null,
    "license": "MIT License",
    "summary": "A lightweight profiler to measure execution time with a rich and colorful hierarchical report.",
    "version": "0.1.1",
    "project_urls": {
        "Bug Tracker": "https://github.com/skst328/scope-timer/issues",
        "Homepage": "https://github.com/skst328/scope-timer"
    },
    "split_keywords": [
        "performance",
        " profiler",
        " rich",
        " scope",
        " timer",
        " timing"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "ae02d95ecddecd5c367bee64c465aa2ea8f428f855035bc463c3a653424284c3",
                "md5": "b018a9b216402ffb8845381df9736e8e",
                "sha256": "715540b40213d702bef6700ec1b0598347c987c2fa5c9f0e242363682f6212f6"
            },
            "downloads": -1,
            "filename": "scope_timer-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "b018a9b216402ffb8845381df9736e8e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 10615,
            "upload_time": "2025-08-03T16:23:19",
            "upload_time_iso_8601": "2025-08-03T16:23:19.717800Z",
            "url": "https://files.pythonhosted.org/packages/ae/02/d95ecddecd5c367bee64c465aa2ea8f428f855035bc463c3a653424284c3/scope_timer-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "46a7107a20f00ed7ff2efe09e17abdbf16ce50f3c9b26ca8c51f29e68c8ae867",
                "md5": "95049371b206a746187e5be6e74f5c30",
                "sha256": "80a9e91daefa36795361c2c14161a62e1da61d72cdb3659376b62c85f9649c55"
            },
            "downloads": -1,
            "filename": "scope_timer-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "95049371b206a746187e5be6e74f5c30",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 152606,
            "upload_time": "2025-08-03T16:23:20",
            "upload_time_iso_8601": "2025-08-03T16:23:20.488220Z",
            "url": "https://files.pythonhosted.org/packages/46/a7/107a20f00ed7ff2efe09e17abdbf16ce50f3c9b26ca8c51f29e68c8ae867/scope_timer-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-03 16:23:20",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "skst328",
    "github_project": "scope-timer",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "scope-timer"
}
        
Elapsed time: 2.57664s