simple-profile


Namesimple-profile JSON
Version 1.1.2 PyPI version JSON
download
home_pagehttps://github.com/JoaoBrlt/simple-profile
SummarySimple profile decorators to monitor execution time and memory usage.
upload_time2022-12-15 17:44:33
maintainer
docs_urlNone
authorJoão Brilhante
requires_python>=3.11,<4.0
licenseGPL-3.0-only
keywords profiler profiling timer timing timeit tracemalloc memory execution decorator
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # simple-profile

Simple decorators to profile the memory usage and execution time.

## Installation

```bash
pip install simple-profile
```

## Decorators

| Decorator           | Description                                                                  |
|---------------------|------------------------------------------------------------------------------|
| `@simple_profile()` | Profiles the peak memory usage and the average execution time of a function. |
| `@memory_profile()` | Profiles only the peak memory usage of a function.                           |
| `@time_profile()`   | Profiles only the average execution time of a function.                      |

## Usage

### 1. Profile a function

The `@simple_profile()` decorator allows to log the peak memory usage and the average execution time of each function call.\
By default, memory usage and execution time are logged in the most suitable units, but it is possible to change the units.

```python
from simple_profile import simple_profile

@simple_profile()
def my_function():
    return [2 * i for i in range(10)]

my_function()
```

Output: 

```
my_function | 432 B | 445.2 ns
```

### 2. Profile only the memory usage of a function

The `@memory_profile()` decorator allows to log the peak memory usage of each function call.\
This is done using the `tracemalloc` module provided by Python.

```python
from simple_profile import memory_profile

@memory_profile()
def my_function():
    return [2 * i for i in range(10)]

my_function()
```

Output: 

```
my_function | 432 B
```

### 3. Profile only the execution time of a function

The `@time_profile()` decorator allows to log the average execution time of each function call.\
This is done using the `timeit` module provided by Python.\
By default, each function call is repeated `1,000,000` times to get a reliable measurement, but it is possible to change this value.

```python
from simple_profile import time_profile

@time_profile()
def my_function():
    return [2 * i for i in range(10)]

my_function()
```

Output: 

```
my_function | 439.3 ns
```

### 4. Change the number of iterations

It is possible to change the number of times a function call is repeated when profiling the execution time.\
To do this, you can set the `iterations` argument of the `simple_profile()` and `time_profile()` decorators.

```python
from simple_profile import simple_profile

@simple_profile(iterations=100)
def pi(n):
    result = 0
    d = 1
    for i in range(1, n):
        a = 2 * (i % 2) - 1
        result += 4 * a / d
        d += 2
    return result

pi(100)
```

Output:

```
pi | 168 B | 6.461 µs
```

### 5. Change the time and memory units

It is also possible to change the time and memory units used in the logs.\
To do this, you can set the `unit` argument of the `memory_profile()` and `time_profile()` decorators.\
For the `simple_profile()` decorator, you can set the `time_unit` and `memory_unit` arguments.

```python
from simple_profile import simple_profile, MemoryUnit, TimeUnit

@simple_profile(memory_unit=MemoryUnit.KILOBYTES, time_unit=TimeUnit.MILLISECONDS)
def exponential(x, n):
    result = 1.0
    for i in range(n, 0, -1):
        result = 1 + x * result / i
    return result

exponential(8, 100)
```

Output:

```
exponential | 0.168 kB | 0.005429 ms
```

### 6. Change the time and memory precision

Moreover, it is possible to change the precision of memory and time values.\
To do this, you can define the number of significant digits you want in the `precision` argument of any decorator provided by this package.\
For the `simple_profile()` decorator, you can set the `time_precision` and `memory_precision` arguments for more granular control.

```python
from simple_profile import simple_profile

@simple_profile(precision=10)
def average(lst):
    return sum(lst) / len(lst)

average([25, 12, 18, 88, 64, 55, 22])
```

Output:

```
average | 120 B | 176.6314 ns
```

### 7. Log the arguments and the result

Furthermore, it is possible to log the arguments and the result of each function call.\
Indeed, this can be useful to better profile a function and analyze its behavior.

```python
from simple_profile import simple_profile

@simple_profile(print_args=True, print_result=True)
def greeting_message(name, coins):
    return "Hello {}! You have {} coins.".format(name, coins)

greeting_message("John", coins=5)
```

Output:

```
greeting_message | John, coins=5 | Hello John! You have 5 coins. | 521 B | 350.1 ns
```

### 8. Set a custom name for a function

Additionally, it is possible to define a custom descriptive name for each function.\
To do this, you can set the `name` argument of any decorator provided by this package.

```python
from simple_profile import simple_profile

@simple_profile(name="Naive method")
def factorial(n):
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result

factorial(10)
```

Output:

```
Naive method | 160 B | 411.3 ns
```

### 9. Compare multiple functions

```python
from simple_profile import simple_profile

@simple_profile(name="List comprehension")
def my_function(n):
    return [pow(2, i) for i in range(n)]


@simple_profile(name="For loop")
def my_function_2(n):
    lst = []
    for i in range(n):
        lst.append(pow(2, i))
    return lst

my_function(10)
my_function_2(10)
```

Output:

```
List comprehension | 464 B | 666.8 ns
For loop | 312 B | 650.7 ns
```

### 10. Profile a recursive function

The decorators work seamlessly with recursive functions.\
Only one profiling message is logged per function call even if the function is recursive.

```python
from simple_profile import simple_profile

@simple_profile(print_args=True, print_result=True, iterations=100)
def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

fibonacci(10)
```

Output:

```
fibonacci | 10 | 55 | 1.648 kB | 21.04 µs
```

### 11. Enable garbage collection during measurements

By default, garbage collection is temporarily turned off to make measurements more comparable, but it is possible to enable it if you prefer.\
To do this, you can set the `enable_gc` argument of the `simple_profile()` and `time_profile()` decorators to `True`.

```python
from simple_profile import simple_profile

@simple_profile(name="Without GC")
def my_function():
    return [oct(i) for i in range(10)]

@simple_profile(name="With GC", enable_gc=True)
def my_function_2():
    return [oct(i) for i in range(10)]

my_function()
my_function_2()
```

Output:

```
Without GC | 954 B | 666.5 ns
With GC | 954 B | 669.2 ns
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/JoaoBrlt/simple-profile",
    "name": "simple-profile",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.11,<4.0",
    "maintainer_email": "",
    "keywords": "profiler,profiling,timer,timing,timeit,tracemalloc,memory,execution,decorator",
    "author": "Jo\u00e3o Brilhante",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/64/36/7899a1ab16f660c2c948be11e4835b87dc41ac1fe17c004f19fe46e9ecca/simple_profile-1.1.2.tar.gz",
    "platform": null,
    "description": "# simple-profile\n\nSimple decorators to profile the memory usage and execution time.\n\n## Installation\n\n```bash\npip install simple-profile\n```\n\n## Decorators\n\n| Decorator           | Description                                                                  |\n|---------------------|------------------------------------------------------------------------------|\n| `@simple_profile()` | Profiles the peak memory usage and the average execution time of a function. |\n| `@memory_profile()` | Profiles only the peak memory usage of a function.                           |\n| `@time_profile()`   | Profiles only the average execution time of a function.                      |\n\n## Usage\n\n### 1. Profile a function\n\nThe `@simple_profile()` decorator allows to log the peak memory usage and the average execution time of each function call.\\\nBy default, memory usage and execution time are logged in the most suitable units, but it is possible to change the units.\n\n```python\nfrom simple_profile import simple_profile\n\n@simple_profile()\ndef my_function():\n    return [2 * i for i in range(10)]\n\nmy_function()\n```\n\nOutput: \n\n```\nmy_function | 432 B | 445.2 ns\n```\n\n### 2. Profile only the memory usage of a function\n\nThe `@memory_profile()` decorator allows to log the peak memory usage of each function call.\\\nThis is done using the `tracemalloc` module provided by Python.\n\n```python\nfrom simple_profile import memory_profile\n\n@memory_profile()\ndef my_function():\n    return [2 * i for i in range(10)]\n\nmy_function()\n```\n\nOutput: \n\n```\nmy_function | 432 B\n```\n\n### 3. Profile only the execution time of a function\n\nThe `@time_profile()` decorator allows to log the average execution time of each function call.\\\nThis is done using the `timeit` module provided by Python.\\\nBy default, each function call is repeated `1,000,000` times to get a reliable measurement, but it is possible to change this value.\n\n```python\nfrom simple_profile import time_profile\n\n@time_profile()\ndef my_function():\n    return [2 * i for i in range(10)]\n\nmy_function()\n```\n\nOutput: \n\n```\nmy_function | 439.3 ns\n```\n\n### 4. Change the number of iterations\n\nIt is possible to change the number of times a function call is repeated when profiling the execution time.\\\nTo do this, you can set the `iterations` argument of the `simple_profile()` and `time_profile()` decorators.\n\n```python\nfrom simple_profile import simple_profile\n\n@simple_profile(iterations=100)\ndef pi(n):\n    result = 0\n    d = 1\n    for i in range(1, n):\n        a = 2 * (i % 2) - 1\n        result += 4 * a / d\n        d += 2\n    return result\n\npi(100)\n```\n\nOutput:\n\n```\npi | 168 B | 6.461 \u00b5s\n```\n\n### 5. Change the time and memory units\n\nIt is also possible to change the time and memory units used in the logs.\\\nTo do this, you can set the `unit` argument of the `memory_profile()` and `time_profile()` decorators.\\\nFor the `simple_profile()` decorator, you can set the `time_unit` and `memory_unit` arguments.\n\n```python\nfrom simple_profile import simple_profile, MemoryUnit, TimeUnit\n\n@simple_profile(memory_unit=MemoryUnit.KILOBYTES, time_unit=TimeUnit.MILLISECONDS)\ndef exponential(x, n):\n    result = 1.0\n    for i in range(n, 0, -1):\n        result = 1 + x * result / i\n    return result\n\nexponential(8, 100)\n```\n\nOutput:\n\n```\nexponential | 0.168 kB | 0.005429 ms\n```\n\n### 6. Change the time and memory precision\n\nMoreover, it is possible to change the precision of memory and time values.\\\nTo do this, you can define the number of significant digits you want in the `precision` argument of any decorator provided by this package.\\\nFor the `simple_profile()` decorator, you can set the `time_precision` and `memory_precision` arguments for more granular control.\n\n```python\nfrom simple_profile import simple_profile\n\n@simple_profile(precision=10)\ndef average(lst):\n    return sum(lst) / len(lst)\n\naverage([25, 12, 18, 88, 64, 55, 22])\n```\n\nOutput:\n\n```\naverage | 120 B | 176.6314 ns\n```\n\n### 7. Log the arguments and the result\n\nFurthermore, it is possible to log the arguments and the result of each function call.\\\nIndeed, this can be useful to better profile a function and analyze its behavior.\n\n```python\nfrom simple_profile import simple_profile\n\n@simple_profile(print_args=True, print_result=True)\ndef greeting_message(name, coins):\n    return \"Hello {}! You have {} coins.\".format(name, coins)\n\ngreeting_message(\"John\", coins=5)\n```\n\nOutput:\n\n```\ngreeting_message | John, coins=5 | Hello John! You have 5 coins. | 521 B | 350.1 ns\n```\n\n### 8. Set a custom name for a function\n\nAdditionally, it is possible to define a custom descriptive name for each function.\\\nTo do this, you can set the `name` argument of any decorator provided by this package.\n\n```python\nfrom simple_profile import simple_profile\n\n@simple_profile(name=\"Naive method\")\ndef factorial(n):\n    result = 1\n    for i in range(1, n + 1):\n        result *= i\n    return result\n\nfactorial(10)\n```\n\nOutput:\n\n```\nNaive method | 160 B | 411.3 ns\n```\n\n### 9. Compare multiple functions\n\n```python\nfrom simple_profile import simple_profile\n\n@simple_profile(name=\"List comprehension\")\ndef my_function(n):\n    return [pow(2, i) for i in range(n)]\n\n\n@simple_profile(name=\"For loop\")\ndef my_function_2(n):\n    lst = []\n    for i in range(n):\n        lst.append(pow(2, i))\n    return lst\n\nmy_function(10)\nmy_function_2(10)\n```\n\nOutput:\n\n```\nList comprehension | 464 B | 666.8 ns\nFor loop | 312 B | 650.7 ns\n```\n\n### 10. Profile a recursive function\n\nThe decorators work seamlessly with recursive functions.\\\nOnly one profiling message is logged per function call even if the function is recursive.\n\n```python\nfrom simple_profile import simple_profile\n\n@simple_profile(print_args=True, print_result=True, iterations=100)\ndef fibonacci(n):\n    if n <= 1:\n        return n\n    else:\n        return fibonacci(n - 1) + fibonacci(n - 2)\n\nfibonacci(10)\n```\n\nOutput:\n\n```\nfibonacci | 10 | 55 | 1.648 kB | 21.04 \u00b5s\n```\n\n### 11. Enable garbage collection during measurements\n\nBy default, garbage collection is temporarily turned off to make measurements more comparable, but it is possible to enable it if you prefer.\\\nTo do this, you can set the `enable_gc` argument of the `simple_profile()` and `time_profile()` decorators to `True`.\n\n```python\nfrom simple_profile import simple_profile\n\n@simple_profile(name=\"Without GC\")\ndef my_function():\n    return [oct(i) for i in range(10)]\n\n@simple_profile(name=\"With GC\", enable_gc=True)\ndef my_function_2():\n    return [oct(i) for i in range(10)]\n\nmy_function()\nmy_function_2()\n```\n\nOutput:\n\n```\nWithout GC | 954 B | 666.5 ns\nWith GC | 954 B | 669.2 ns\n```\n",
    "bugtrack_url": null,
    "license": "GPL-3.0-only",
    "summary": "Simple profile decorators to monitor execution time and memory usage.",
    "version": "1.1.2",
    "split_keywords": [
        "profiler",
        "profiling",
        "timer",
        "timing",
        "timeit",
        "tracemalloc",
        "memory",
        "execution",
        "decorator"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "md5": "d118d3119835e800e713e6d9bbef9c98",
                "sha256": "cbc59dcfed821dd08e31a847c216d6f43b0331b38c779d10b55778e6dcf37ea9"
            },
            "downloads": -1,
            "filename": "simple_profile-1.1.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d118d3119835e800e713e6d9bbef9c98",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.11,<4.0",
            "size": 19153,
            "upload_time": "2022-12-15T17:44:31",
            "upload_time_iso_8601": "2022-12-15T17:44:31.637664Z",
            "url": "https://files.pythonhosted.org/packages/f4/67/d27351a077b024d137cfdbc8888cffcdd0b25ffb9d58ff302eae7b4dded5/simple_profile-1.1.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "md5": "a2f3a62c69a2d7a83f72a41272bdc1e7",
                "sha256": "9548512379b38391729f31b7656049ac67b4113279c97fd77d7ac2099933519c"
            },
            "downloads": -1,
            "filename": "simple_profile-1.1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "a2f3a62c69a2d7a83f72a41272bdc1e7",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11,<4.0",
            "size": 19340,
            "upload_time": "2022-12-15T17:44:33",
            "upload_time_iso_8601": "2022-12-15T17:44:33.230959Z",
            "url": "https://files.pythonhosted.org/packages/64/36/7899a1ab16f660c2c948be11e4835b87dc41ac1fe17c004f19fe46e9ecca/simple_profile-1.1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2022-12-15 17:44:33",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "JoaoBrlt",
    "github_project": "simple-profile",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "simple-profile"
}
        
Elapsed time: 0.02180s