{"id":15898433,"url":"https://github.com/bobronium/timesup","last_synced_at":"2025-04-02T19:12:42.313Z","repository":{"id":65427643,"uuid":"592162587","full_name":"Bobronium/timesup","owner":"Bobronium","description":"Measure performance and showcase the difference between results without boilerplate.","archived":false,"fork":false,"pushed_at":"2023-01-27T23:42:10.000Z","size":4,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-08T08:05:33.463Z","etag":null,"topics":["benchmark","fast","performance","performance-testing","python","timeit","tools"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Bobronium.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2023-01-23T04:29:23.000Z","updated_at":"2023-03-26T07:00:00.000Z","dependencies_parsed_at":"2023-02-12T20:33:15.529Z","dependency_job_id":null,"html_url":"https://github.com/Bobronium/timesup","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bobronium%2Ftimesup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bobronium%2Ftimesup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bobronium%2Ftimesup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bobronium%2Ftimesup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Bobronium","download_url":"https://codeload.github.com/Bobronium/timesup/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246875909,"owners_count":20848048,"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":["benchmark","fast","performance","performance-testing","python","timeit","tools"],"created_at":"2024-10-06T10:03:59.129Z","updated_at":"2025-04-02T19:12:42.292Z","avatar_url":"https://github.com/Bobronium.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# timesup\n\nMeasure performance and showcase the difference between results without boilerplate.\n\n\n\n![timesup_duper_demo](https://user-images.githubusercontent.com/36469655/215218569-1f833d77-d974-49ab-98cf-a03d9ab32899.gif)\n\n\n\n\n### 🚧 Project is in development\nThere's no source code available yet.\n\nIf you have any feedback or ideas, you can [open the issue](https://github.com/Bobronium/timesup/issues), or  contact me directly via [bobronium@gmail.com](mailto:bobronium@gmail.com) or [Telegram](https://t.me/Bobronium).\n\n---\n\n### Why?\nI was tired of writing benchmarks that not only measured performance, but also output it in an accessible and intuitive way ([like this one](https://github.com/Bobronium/fastenum/tree/master/benchmark)), but also easy to reproduce.\nSo I decided to abstract all that away so the only thing left is to write the actual code you want to measure.\n\nI believe that by making benchmarking more accessible (and fun), I can create incentive to build faster software. \n\n\n### Features\n- Output is a Python code that contains the benchmark itself and ready to be published\n- Effortless comparisons of results\n- Compare current implementation to one in any given git revision\n- Compare interpreted CPython code to compiled code it produces via cython or mypyc\n- Profiling support for expressions\n- HTML output for viewing individual profiling results by expanding expressions\n- Automatically selects the appropriate number of runs and repeats, if they weren't provided\n- Out-of-the-box support for multiline expressions\n\n\n## Showcase \n###### All snippets are self-contained\n### Comparing within the same process \n`cat benchmark.py`\n```py\nimport copy\nimport duper\nimport timesup\n\n@timesup.it(number=100000, repeats=3)\ndef duper_vs_deepcopy():\n    x = {\"a\": 1, \"b\": [(1, 2, 3), (4, 5, 6)], \"c\": []}  # i\n    copy.deepcopy(x)  # t deepcopy\n    dup = duper.Duper(x)  # t duper_init deepcopy\n    dup.deep()  # t duper deepcopy\n```\n`python benchmark.py`\n```py\nimport copy\nimport duper\nimport timesup\n\n@timesup.it(number=100000, repeats=3)\ndef reconstruction():\n    x = {\"a\": 1, \"b\": [(1, 2, 3), (4, 5, 6)], \"c\": []} \n    copy.deepcopy(x)        # ~0.00643 ms (deepcopy)\n    dup = duper.Duper(x)    # ~0.00009 ms (duper_init): 69.44 times faster than deepcopy\n    dup.deep()              # ~0.00014 ms (duper): 44.76 times faster than deepcopy\n```\n\n### Interpreted vs compiled code\n\u003cdetails\u003e\n\u003csummary\u003ecat fib.py\u003c/summary\u003e\n\n```py\ndef fib(n: int) -\u003e int:\n    if n \u003c= 1:\n        return n\n    else:\n        return fib(n - 2) + fib(n - 1)\n```\n`mypyc fib.py`\n```\nbuilding 'compiled_test' extension\n...\ncopying build/lib.macosx-12.0-arm64-cpython-310/fib.cpython-310-darwin.so -\u003e \n```\n\u003c/details\u003e\n\n`cat benchmark.py`\n```py\nimport timesup\nfrom fib import fib\n\n@timesup.compare(to_interpreted=True)\ndef cpython_vs_mypyc():\n    fib(32)\n```\n`python benchmark.py`\n```python\nimport timesup\nfrom fib import fib\n\n@timesup.compare(to_interpreted=True)\ndef cpython_vs_mypyc():\n    fib(32)     # ~510.73292 ms (interpreted)\n    #|_________ # ~21.72464 ms (compiled): 23.51 times faster than interpreted\n```\n\n\n### Existing vs new code\nConsider you're trying to improve performance of `app.used_to_be_slow` function.\n\nIt's crucial to have a baseline that you can compare your changes to.\n\nBy allowing to pass a target revision that changes need to be compared to, `timesup`:\n- removes the need to capture the baseline beforehand\n- since baseline is calculated each time automatically, you're not limited to the input you've got your baseline results with\n- creates a perfect code snippet to include in PR with the changes ✨\n- this snipped can be run by any of reviewers without them needing to manually download any benchmarks, measuring the baseline and testing the results\n\n\n`cat benchmark.py`\n```py\nimport timesup\nfrom app import used_to_be_slow\n\n@timesup.compare(to_revision=\"main\")\ndef measure_improvement():\n    used_to_be_slow()\n```\n`python benchmark.py`\n```python\nimport timesup\nfrom app import used_to_be_slow\n\n@timesup.compare(to_revision=\"main\")\ndef measure_improvement():\n    used_to_be_slow()     # ~0.00106 ms (34dc8225)\n    #|___________________ # ~0.00035 ms (changes): 2.99 times faster than 34dc8225 \n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbobronium%2Ftimesup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbobronium%2Ftimesup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbobronium%2Ftimesup/lists"}