{ "info": { "author": "Philip Trauner", "author_email": "philip.trauner@arztpraxis.io", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7" ], "description": "

\n\"nibbler\"/\n

\n\n---\n[![Python 3.7](https://img.shields.io/badge/python-3.7-%233572A5.svg)](https://docs.python.org/3/whatsnew/3.7.html)\n[![PyPI version](https://badge.fury.io/py/nibbler.svg)](https://badge.fury.io/py/nibbler)\n[![Not production ready](https://img.shields.io/badge/production%20ready-hell%20no-red.svg)]()\n[![Travis status](https://travis-ci.org/PhilipTrauner/nibbler.svg?branch=master)](https://travis-ci.org/PhilipTrauner/nibbler)\n\n**nibbler** is a runtime bytecode optimizer.\n\nIt explores the concept of using existing Python syntax features such as *type annotations* and *decorators* to **speed up** code execution by running additional bytecode optimization passes that make use of runtime context provided through these means.\n\n## Optimization passes\n* [`inline`](https://github.com/PhilipTrauner/nibbler/blob/master/nibbler/extension/inline.py) \n\tInlines parameter-less calls to functions that are decorated with `@nibbler.inline`.\n* [`constantize_globals`](https://github.com/PhilipTrauner/nibbler/blob/master/nibbler/extension/constantize_globals.py) \n\tCopies the value of globals that were marked constant (with a `Constant` type annotation or with the `@nibbler.constant` decorator) into the `co_consts` tuple of functions that would normally have to access the global namespace, which speeds up variable access. This also applies to builtins (`any`, `all`, `print`, ...).\n* [`precompute_conditionals`](https://github.com/PhilipTrauner/nibbler/blob/master/nibbler/extension/precompute_conditionals.py) \n\tStrips out conditionals that test constants which the peephole optimizer doesn't pick up on.\n* [`global_to_fast`](https://github.com/PhilipTrauner/nibbler/blob/master/nibbler/extension/global_to_fast.py) \n\tTransforms global variable loads to local variable loads if a local variable with the same name exists (mostly a cleanup pass for [`inline`](https://github.com/PhilipTrauner/nibbler/blob/master/nibbler/extension/inline.py))\n* [`peephole`](https://github.com/PhilipTrauner/nibbler/blob/master/nibbler/extension/peephole.py) \n\tInvokes the [Python peephole optimizer](https://github.com/python/cpython/blob/master/Python/peephole.c) with additional context.\n\n\n## Usage\n```python\nfrom typing import Iterable\n\nfrom nibbler import Constant, Nibbler\n\nDEBUG: Constant[bool] = False\n\nnibbler = Nibbler(globals())\n\n\n@nibbler.inline\ndef square(number: int, base: int) -> int:\n result = number ** base\n return result\n\n\n@nibbler.nibble\ndef sequential_square(numbers: Iterable[int]) -> int:\n product = 0\n base = 2\n for number in numbers:\n square()\n\n if DEBUG:\n print(result)\n\n product += result\n\n print(f\"Result: {product}\")\n\n return product\n\n\nsequential_square(range(4))\n```\n

\u2193

\n\n```\nResult: 14\n```\n\nExamining the function bytecode reveals which optimizations **nibbler** has performed:\n```\n 2 0 LOAD_CONST 1 (0)\n 2 STORE_FAST 1 (product)\n\n 3 4 LOAD_CONST 2 (2)\n 6 STORE_FAST 2 (base)\n\n 4 8 SETUP_LOOP 28 (to 38)\n 10 LOAD_FAST 0 (numbers)\n 12 GET_ITER\n >> 14 FOR_ITER 20 (to 36)\n 16 STORE_FAST 3 (number)\n\n 5 18 LOAD_FAST 3 (number)\n 20 LOAD_FAST 2 (base)\n 22 BINARY_POWER\n 24 STORE_FAST 4 (result)\n\n 6 26 LOAD_FAST 1 (product)\n 28 LOAD_FAST 4 (result)\n 30 INPLACE_ADD\n 32 STORE_FAST 1 (product)\n 34 JUMP_ABSOLUTE 14\n >> 36 POP_BLOCK\n\n 8 >> 38 LOAD_CONST 5 ()\n 40 LOAD_CONST 3 ('Result: ')\n 42 LOAD_FAST 1 (product)\n 44 FORMAT_VALUE 0\n 46 BUILD_STRING 2\n 48 CALL_FUNCTION 1\n 50 POP_TOP\n\n 9 52 LOAD_FAST 1 (product)\n 54 RETURN_VALUE\n```\n\n* The `square` function was inlined ([`inline`](https://github.com/PhilipTrauner/nibbler/blob/master/nibbler/extension/inline.py)) (18-24)\n* Conditional (`if DEBUG`) was stripped out, because `DEBUG` was declared a constant ([`precompute_conditionals`](https://github.com/PhilipTrauner/nibbler/blob/master/nibbler/extension/precompute_conditionals.py)) (26)\n* The `print` function was promoted to a function-level constant ([`constantize_globals`](https://github.com/PhilipTrauner/nibbler/blob/master/nibbler/extension/constantize_globals.py)) (38)\n\n## Installation\n```sh\npip3 install nibbler\n```\n\n## FAQ\n\n* Is this production ready? \n\tHell no.\n* Why is it called **nibbler**? \n\t\u00af\\\\\\_(\u30c4)\\_/\u00af\n\n## Prior Art\n* [fatoptimizer](https://github.com/vstinner/fatoptimizer)\n* [PEP 510](https://www.python.org/dev/peps/pep-0510/)\n* [PEP 511](https://www.python.org/dev/peps/pep-0511/)\n* [falcon](https://github.com/rjpower/falcon)\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "", "keywords": "", "license": "MIT", "maintainer": "Philip Trauner", "maintainer_email": "philip.trauner@arztpraxis.io", "name": "nibbler", "package_url": "https://pypi.org/project/nibbler/", "platform": "", "project_url": "https://pypi.org/project/nibbler/", "project_urls": null, "release_url": "https://pypi.org/project/nibbler/0.1.3/", "requires_dist": [ "black (>=18.9b0,<19.0)", "uncompyle6 (>=3.2,<4.0)" ], "requires_python": ">=3.7,<4.0", "summary": "Runtime bytecode optimizer.", "version": "0.1.3" }, "last_serial": 5139161, "releases": { "0.1.2": [ { "comment_text": "", "digests": { "md5": "3afd997bab37d47de0ca803cdb5d3405", "sha256": "424713bf3c985cb91d1a3023e55e8a6c5a20201e491fb841d2d3e91bb6ab2122" }, "downloads": -1, "filename": "nibbler-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "3afd997bab37d47de0ca803cdb5d3405", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 38255, "upload_time": "2019-03-17T19:38:05", "url": "https://files.pythonhosted.org/packages/89/64/ed4c1aa3a5c0c2c2f951d064bbc038742c36b74443a4457271583010a34a/nibbler-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "15c0e92b36dc1b02cadb6e9c186188b1", "sha256": "ff76b5584d71e0ae046b80525f695a9b65cca57d3f1d87b26819d05bb2921a83" }, "downloads": -1, "filename": "nibbler-0.1.2.tar.gz", "has_sig": false, "md5_digest": "15c0e92b36dc1b02cadb6e9c186188b1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 12407, "upload_time": "2019-03-17T19:38:07", "url": "https://files.pythonhosted.org/packages/01/7e/0c3790394d4d849b65e4d96a51d7ae151e6261c128b40f683fdfbdb91168/nibbler-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "f358b291c3d66b63e1935a56ac19f2e6", "sha256": "5e30c8fc4bc70eaebdf127919493c4f8362e763c00c03213ce8d60785b824ff8" }, "downloads": -1, "filename": "nibbler-0.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "f358b291c3d66b63e1935a56ac19f2e6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 38256, "upload_time": "2019-04-13T21:08:59", "url": "https://files.pythonhosted.org/packages/6b/f8/fe6821ccfae42dc6bb7f61cef8ee90deb4cefb00c074e5ad1381195a3d6f/nibbler-0.1.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2612a6e39183e253c2be4f91df657e90", "sha256": "945fd900b47311898c245f79ef7bfd6f20538ed1cb8c4793cebf471c273aa852" }, "downloads": -1, "filename": "nibbler-0.1.3.tar.gz", "has_sig": false, "md5_digest": "2612a6e39183e253c2be4f91df657e90", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 12416, "upload_time": "2019-04-13T21:09:00", "url": "https://files.pythonhosted.org/packages/85/94/e5f5894e7f8fa8cd0a328d213e25c2528147ade859cd6a3b1429256e8704/nibbler-0.1.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "f358b291c3d66b63e1935a56ac19f2e6", "sha256": "5e30c8fc4bc70eaebdf127919493c4f8362e763c00c03213ce8d60785b824ff8" }, "downloads": -1, "filename": "nibbler-0.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "f358b291c3d66b63e1935a56ac19f2e6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7,<4.0", "size": 38256, "upload_time": "2019-04-13T21:08:59", "url": "https://files.pythonhosted.org/packages/6b/f8/fe6821ccfae42dc6bb7f61cef8ee90deb4cefb00c074e5ad1381195a3d6f/nibbler-0.1.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2612a6e39183e253c2be4f91df657e90", "sha256": "945fd900b47311898c245f79ef7bfd6f20538ed1cb8c4793cebf471c273aa852" }, "downloads": -1, "filename": "nibbler-0.1.3.tar.gz", "has_sig": false, "md5_digest": "2612a6e39183e253c2be4f91df657e90", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7,<4.0", "size": 12416, "upload_time": "2019-04-13T21:09:00", "url": "https://files.pythonhosted.org/packages/85/94/e5f5894e7f8fa8cd0a328d213e25c2528147ade859cd6a3b1429256e8704/nibbler-0.1.3.tar.gz" } ] }