{"id":16129845,"url":"https://github.com/erotemic/timerit","last_synced_at":"2025-10-29T10:03:08.208Z","repository":{"id":32482511,"uuid":"134924343","full_name":"Erotemic/timerit","owner":"Erotemic","description":"Time and benchmark blocks of Python code. A powerful multi-line in-code alternative to timeit. ","archived":false,"fork":false,"pushed_at":"2024-09-25T16:22:10.000Z","size":260,"stargazers_count":36,"open_issues_count":5,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-20T07:04:56.349Z","etag":null,"topics":["benchmarking","python","timeit","timer","utilities"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Erotemic.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-26T03:00:46.000Z","updated_at":"2025-05-10T22:02:34.000Z","dependencies_parsed_at":"2024-04-26T21:39:12.472Z","dependency_job_id":"72be9f3e-8c8e-4108-8492-834610ad3a3a","html_url":"https://github.com/Erotemic/timerit","commit_stats":{"total_commits":130,"total_committers":3,"mean_commits":"43.333333333333336","dds":0.1384615384615384,"last_synced_commit":"82b0c6c4997d45fa6eec42ab58977de8a319b848"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/Erotemic/timerit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Erotemic%2Ftimerit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Erotemic%2Ftimerit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Erotemic%2Ftimerit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Erotemic%2Ftimerit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Erotemic","download_url":"https://codeload.github.com/Erotemic/timerit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Erotemic%2Ftimerit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259453534,"owners_count":22860086,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["benchmarking","python","timeit","timer","utilities"],"created_at":"2024-10-09T22:12:51.291Z","updated_at":"2025-10-29T10:03:08.100Z","avatar_url":"https://github.com/Erotemic.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n|GithubActions| |Appveyor| |Codecov| |Pypi| |Downloads| |ReadTheDocs|\n\n\nTimerit\n=======\n\nA powerful multiline alternative to Python's builtin `timeit \u003chttps://docs.python.org/3/library/timeit.html\u003e`_ module.\n\nDocs are published at https://timerit.readthedocs.io/en/latest/ but this README\nand code comments contain a walkthrough.\n\n+---------------+--------------------------------------------+\n| Github        | https://github.com/Erotemic/timerit        |\n+---------------+--------------------------------------------+\n| Pypi          | https://pypi.org/project/timerit           |\n+---------------+--------------------------------------------+\n| ReadTheDocs   | https://timerit.readthedocs.io/en/latest/  |\n+---------------+--------------------------------------------+\n\nDescription\n-----------\n\nEasily do robust timings on existing blocks of code by simply indenting\nthem. There is no need to refactor into a string representation or\nconvert to a single line.\n\nInstallation\n------------\n\n.. code:: bash\n\n    pip install timerit\n\n\nInteractive Use\n---------------\n\nThe ``timerit`` library provides a succinct API for interactive use:\n\n.. code:: python\n\n    \u003e\u003e\u003e import timerit\n    \u003e\u003e\u003e for _ in timerit:\n    ...     sum(range(100000))\n    Timed for: 288 loops, best of 5\n        time per loop: best=616.740 µs, mean=668.933 ± 124.2 µs\n\nCompare to ``timeit``:\n\n.. code:: bash\n\n    $ python -m timeit 'sum(range(100000))'\n    500 loops, best of 5: 721 usec per loop\n\nBy default, any code within the loop will be repeatedly executed until at least\n200 ms have elapsed.  The timing results are then printed out.\n\nHere's what each of the numbers means:\n\n- \"288 loops\": The code in the loop was run 288 times before the time limit was\n  reached.\n\n- \"best of 5\": Consider only the fastest of every 5 measured times, when\n  calculating the mean and standard deviation.  The reason for doing this is\n  that you can get slow times if the something in the background is consuming\n  resources, so you're generally only interested in the fastest times.  This\n  idea is also described in the\n  `timeit docs \u003chttps://docs.python.org/3/library/timeit.html#timeit.Timer.repeat\u003e`_.\n\n- \"best=616.740 µs\": How long the fastest iteration took to run.  For the reasons\n  described above, this is usually the most consistent number, and the primary\n  number you should focus on.\n\n- \"mean=668.933 ± 124.2 µs\": The mean and the standard deviation of the \"best of 5\"\n  iterations.  This statistic is usually not as robust or useful as the fastest\n  time, but sometimes its helpful to know if there's high variance.\n\nThe loop variable can be used as a context manager to only time a part of each\nloop (e.g. to make the timings more accurate, or to incorporate a setup phase\nthat is not timed):\n\n.. code:: python\n\n    \u003e\u003e\u003e for timer in timerit:\n    ...     n = 100 * 1000\n    ...     with timer:\n    ...         sum(range(n))\n    Timed for: 318 loops, best of 5\n        time per loop: best=616.673 µs, mean=617.545 ± 0.9 µs\n\nIt is also possible to provide arguments controlling how the timing\nmeasurements are made.  See the online documentation for more information on\nthese arguments, but the snippet below runs for exactly 100 iterations, instead\nof however many fit in 200 ms.\n\n.. code:: python\n\n    \u003e\u003e\u003e for _ in timerit(num=100):\n    ...     sum(range(100000))\n    Timed for: 100 loops, best of 5\n        time per loop: best=616.866 µs, mean=619.120 ± 5.3 µs\n\n\nAutomatic Import\n~~~~~~~~~~~~~~~~\nIf you want to make ``timerit`` even easier to use interactively, you can move\nthe import to the PYTHONSTARTUP_ file.  If defined, this environment variable\ngives the path to a python script that will be executed just before every\ninteractive session.  For example:\n\n.. code:: bash\n\n    $ export PYTHONSTARTUP=~/.pythonrc\n    $ cat $PYTHONSTARTUP\n    import timerit\n    $ python\n    \u003e\u003e\u003e for _ in timerit:\n    ...     sum(range(100000))\n    ...\n    Timed for: 59 loops, best of 3\n        time per loop: best=2.532 ms, mean=3.309 ± 1.0 ms\n\n\nProgrammatic Use\n----------------\n\nThe timerit library also provides a ``Timerit`` class that can be used\nprogrammatically.\n\n.. code:: python\n\n    \u003e\u003e\u003e import math, timerit\n    \u003e\u003e\u003e for timer in timerit:\n    \u003e\u003e\u003e     setup_vars = 10000\n    \u003e\u003e\u003e     with timer:\n    \u003e\u003e\u003e         math.factorial(setup_vars)\n    \u003e\u003e\u003e print('t1.total_time = %r' % (t1.total_time,))\n    Timing for 200 loops\n    Timed for: 200 loops, best of 3\n        time per loop: best=2.064 ms, mean=2.115 ± 0.05 ms\n    t1.total_time = 0.4427177629695507\n\nA common pattern is to create a single ``Timerit`` instance, then to repeatedly\n\"reset\" it with different labels to test a number of different algorithms.  The\nlabels assigned in this way will be incorporated into the report strings that\nthe ``Timerit`` instance produces.  The \"Benchmark Recipe\" below shows an example\nof this pattern.  So do all of the scripts in the ``examples/`` directory.\n\nThere is also a simple one-liner that is comparable to ``timeit``'s IPython magic:\n\nCompare the timeit version:\n\n.. code:: python\n\n    \u003e\u003e\u003e %timeit math.factorial(100)\n    564 ns ± 5.46 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n\nWith the Timerit version:\n\n.. code:: python\n\n    \u003e\u003e\u003e Timerit(100000).call(math.factorial, 100).print()\n    Timed for: 1 loops, best of 1\n        time per loop: best=4.828 µs, mean=4.828 ± 0.0 µs\n\n\nHow it works\n------------\n\nThe timerit module defines ``timerit.Timerit``, which is an iterable object\nthat yields ``timerit.Timer`` context managers.\n\n.. code:: python\n\n    \u003e\u003e\u003e import math\n    \u003e\u003e\u003e from timerit import Timerit\n    \u003e\u003e\u003e for timer in Timerit(num=200, verbose=2):\n    \u003e\u003e\u003e     with timer:\n    \u003e\u003e\u003e         math.factorial(10000)\n\nThe timer context manager measures how much time the body of it takes by\n\"tic\"-ing on ``__enter__`` and \"toc\"-ing on ``__exit__``. The parent\n``Timerit`` object has access to the context manager, so it is able to read its\nmeasurement. These measurements are stored and then we compute some statistics\non them. Notably the minimum, mean, and standard-deviation of grouped (batched)\nrunning times.\n\nUsing the with statement inside the loop is nice because you can run untimed\nsetup code before you enter the context manager.\n\nIn the case where no setup code is required, a more concise version of the\nsyntax is available.\n\n.. code:: python\n\n    \u003e\u003e\u003e import math\n    \u003e\u003e\u003e from timerit import Timerit\n    \u003e\u003e\u003e for _ in Timerit(num=200, verbose=2):\n    \u003e\u003e\u003e     math.factorial(10000)\n\nIf the context manager is never called, the ``Timerit`` object detects this and\nthe measurement is made in the ``__iter__`` method in the ``Timerit`` object\nitself. I believe that this concise method contains slightly more overhead than\nthe with-statement version. (I have seen evidence that this might actually be\nmore accurate, but it needs further testing).\n\nBenchmark Recipe\n----------------\n\n.. code:: python\n\n    import ubelt as ub\n    import pandas as pd\n    import timerit\n\n    def method1(x):\n        ret = []\n        for i in range(x):\n            ret.append(i)\n        return ret\n\n    def method2(x):\n        ret = [i for i in range(x)]\n        return ret\n\n    method_lut = locals()  # can populate this some other way\n\n    ti = timerit.Timerit(100, bestof=10, verbose=2)\n\n    basis = {\n        'method': ['method1', 'method2'],\n        'x': list(range(7)),\n        # 'param_name': [param values],\n    }\n    grid_iter = ub.named_product(basis)\n\n    # For each variation of your experiment, create a row.\n    rows = []\n    for params in grid_iter:\n        key = ub.repr2(params, compact=1, si=1)\n        kwargs = params.copy()\n        method_key = kwargs.pop('method')\n        method = method_lut[method_key]\n        # Timerit will run some user-specified number of loops.\n        # and compute time stats with similar methodology to timeit\n        for timer in ti.reset(key):\n            # Put any setup logic you dont want to time here.\n            # ...\n            with timer:\n                # Put the logic you want to time here\n                method(**kwargs)\n        row = {\n            'mean': ti.mean(),\n            'min': ti.min(),\n            'key': key,\n            **params,\n        }\n        rows.append(row)\n\n    # The rows define a long-form pandas data array.\n    # Data in long-form makes it very easy to use seaborn.\n    data = pd.DataFrame(rows)\n    print(data)\n\n    plot = True\n    if plot:\n        # import seaborn as sns\n        # kwplot autosns works well for IPython and script execution.\n        # not sure about notebooks.\n        import kwplot\n        sns = kwplot.autosns()\n\n        # Your variables may change\n        ax = kwplot.figure(fnum=1, doclf=True).gca()\n        sns.lineplot(data=data, x='x', y='min', hue='method', marker='o', ax=ax)\n        ax.set_title('Benchmark Name')\n        ax.set_xlabel('x-variable description')\n        ax.set_ylabel('y-variable description')\n\n\nRelated Work\n============\n\n* `timeit \u003chttps://docs.python.org/3/library/timeit.html\u003e`_: The builtin timeit module for profiling single statements.\n\n* `line_profiler \u003chttps://github.com/pyutils/line_profiler\u003e`_: Line-by-line profiling.\n\n* `ubelt \u003chttps://github.com/Erotemic/ubelt\u003e`_: This library was original developed as a component of ubelt, but has since become a standalone module.\n\n\n.. |Travis| image:: https://img.shields.io/travis/Erotemic/timerit/master.svg?label=Travis%20CI\n   :target: https://travis-ci.org/Erotemic/timerit?branch=master\n.. |Codecov| image:: https://codecov.io/github/Erotemic/timerit/badge.svg?branch=master\u0026service=github\n   :target: https://codecov.io/github/Erotemic/timerit?branch=master\n.. |Appveyor| image:: https://ci.appveyor.com/api/projects/status/github/Erotemic/timerit?branch=master\u0026svg=True\n   :target: https://ci.appveyor.com/project/Erotemic/timerit/branch/master\n.. |Pypi| image:: https://img.shields.io/pypi/v/timerit.svg\n   :target: https://pypi.python.org/pypi/timerit\n.. |Downloads| image:: https://img.shields.io/pypi/dm/timerit.svg\n   :target: https://pypistats.org/packages/timerit\n.. |CircleCI| image:: https://circleci.com/gh/Erotemic/timerit.svg?style=svg\n    :target: https://circleci.com/gh/Erotemic/timerit\n.. |ReadTheDocs| image:: https://readthedocs.org/projects/timerit/badge/?version=latest\n    :target: http://timerit.readthedocs.io/en/latest/\n.. |CodeQuality| image:: https://api.codacy.com/project/badge/Grade/fdcedca723f24ec4be9c7067d91cb43b\n    :target: https://www.codacy.com/manual/Erotemic/timerit?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=Erotemic/timerit\u0026amp;utm_campaign=Badge_Grade\n.. |GithubActions| image:: https://github.com/Erotemic/timerit/actions/workflows/tests.yml/badge.svg?branch=main\n    :target: https://github.com/Erotemic/timerit/actions?query=branch%3Amain\n\n.. _PYTHONSTARTUP: https://docs.python.org/3/using/cmdline.html?highlight=pythonstartup#envvar-PYTHONSTARTUP\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferotemic%2Ftimerit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferotemic%2Ftimerit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferotemic%2Ftimerit/lists"}