{"id":13501502,"url":"https://github.com/rochacbruno/rust-python-example","last_synced_at":"2025-04-04T07:07:41.175Z","repository":{"id":44392494,"uuid":"110371573","full_name":"rochacbruno/rust-python-example","owner":"rochacbruno","description":"Example of using Rust to Extend Python","archived":false,"fork":false,"pushed_at":"2022-07-10T11:51:22.000Z","size":47,"stargazers_count":789,"open_issues_count":7,"forks_count":62,"subscribers_count":26,"default_branch":"master","last_synced_at":"2025-03-28T06:08:08.047Z","etag":null,"topics":["c","cargo","cffi","comparison","cpython","cython","ffi","llvm","numba","python","redhat","rust","rust-cpython","rust-packages"],"latest_commit_sha":null,"homepage":"https://developers.redhat.com/blog/2017/11/16/speed-python-using-rust/","language":"Python","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/rochacbruno.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":"2017-11-11T18:56:02.000Z","updated_at":"2025-03-28T05:12:22.000Z","dependencies_parsed_at":"2022-07-14T21:16:52.373Z","dependency_job_id":null,"html_url":"https://github.com/rochacbruno/rust-python-example","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/rochacbruno%2Frust-python-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rochacbruno%2Frust-python-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rochacbruno%2Frust-python-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rochacbruno%2Frust-python-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rochacbruno","download_url":"https://codeload.github.com/rochacbruno/rust-python-example/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247135144,"owners_count":20889421,"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":["c","cargo","cffi","comparison","cpython","cython","ffi","llvm","numba","python","redhat","rust","rust-cpython","rust-packages"],"created_at":"2024-07-31T22:01:39.650Z","updated_at":"2025-04-04T07:07:41.154Z","avatar_url":"https://github.com/rochacbruno.png","language":"Python","readme":"# Speed up your Python using Rust\n\n![Rust](https://www.rust-lang.org/logos/rust-logo-blk.svg)\n\n## What is Rust?\n\n**Rust** is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety. \n\nFeaturing\n\n* zero-cost abstractions\n* move semantics\n* guaranteed memory safety\n* threads without data races\n* trait-based generics\n* pattern matching\n* type inference\n* minimal runtime\n* efficient C bindings\n\n\u003e Taken from: from rust-lang.org\n\n## Why does it matter for a Python developer?\n\nThe better description of Rust I heard from [**Elias**](https://github.com/dlight) a member and the **Rust Guru** of the [**Rust Brazil Telegram Group**](https://t.me/rustlangbr)\n\n\u003e **Rust is** a language that allows you to build high level abstractions, but without giving up low level control - that is, control of how data is represented in memory, control of which threading model you want to use etc.  \n\u003e **Rust is** a language that can usually detect, during compilation, the worst parallelism and memory management errors (such as accessing data on different threads without synchronization, or using data after they have been deallocated), but gives you a hatch escape in the case you really know what you're doing.  \n\u003e **Rust is** a language that, because it has no runtime, can be used to integrate with any runtime; you can write a native extension in Rust that is called by a program node.js, or by a python program, or by a program in ruby, lua etc. and, on the other hand, you can script a program in Rust using these languages.  -- \"Elias Gabriel Amaral da Silva\"\n\n\n![PyRust](https://user-images.githubusercontent.com/458654/32692578-9a424482-c701-11e7-8ea5-09c71612b96c.png)\n\nThere are a bunch of Rust packages out there to help you extending Python with Rust. \n\nI can mention [Milksnake](https://github.com/getsentry/milksnake) created by Armin Ronacher (the creator of Flask)  and also [PyO3](https://github.com/PyO3/pyo3) The Rust bindings for Python interpreter\n\n\u003e See a complete reference list at the bottom.\n\nFor this post, I am going to use [Rust Cpython](https://github.com/dgrunwald/rust-cpython), it's the only one I have tested, it is compatible with **stable version of Rust** and found it straightforward to use.\n\n\u003e **NOTE**: [PyO3](https://github.com/PyO3/pyo3) is a fork of rust-cpython, comes with many improvements, but works only with the nightly version of Rust, so I prefered to use the stable for this post, anyway the examples here must work also with PyO3.\n\n**Pros:** It is really easy to write Rust functions and import from Python and as you will see by the benchmarks it worth in terms of performance.\n\n**Cons:** The distribution of your **project/lib/framework** will demand the Rust module to be compiled on the target system because of variation of environment and architecture, there will be a **compiling** stage which you don't have when installing Pure Python libraries, you can make it easier using [rust-setuptools](https://pypi.python.org/pypi/setuptools-rust) or using the [MilkSnake](https://github.com/getsentry/milksnake) to embed binary data in Python Wheels.\n\n## Python is sometimes slow\n\nYes, Python is known for being \"slow\" in some cases and the good news is that this doesn't really matter depending on your project goals and priorities. For most projects this \ndetail will not be very important.\n\nHowever, you may face the **rare** case where a single function or module is taking too much time and is detected as the bottleneck of your project performance, often happens with string parsing and image processing.\n\n## Example\n\nLets say you have a Python function which does some kind of string processing, take the following easy example of `counting pairs of repeated chars` but have in mind that this example can be reproduced with other `string processing` functions or any other generally slow process in Python.\n\n\n```bash\n# How many subsequent-repeated group of chars are in the given string? \nabCCdeFFghiJJklmnopqRRstuVVxyZZ... {millions of chars here}\n  1   2    3        4    5   6 \n```\n\nPython is pretty slow for doing large `string` processing so you can use `pytest-benchmark` to compare a `Pure Python (with Iterator Zipping)` function versus a `Regexp` implementation.\n\n```bash\n# Using a Python3.6 environment\n$ pip3 install pytest pytest-benchmark\n\n```\n\nThen write a new Python program called `doubles.py`\n\n```python\nimport re\nimport string\nimport random\n\n# Python ZIP version\ndef count_doubles(val):\n    total = 0\n    for c1, c2 in zip(val, val[1:]):\n        if c1 == c2:\n            total += 1\n    return total\n\n\n# Python REGEXP version\ndouble_re = re.compile(r'(?=(.)\\1)')\n\ndef count_doubles_regex(val):\n    return len(double_re.findall(val))\n\n\n# Benchmark it\n# generate 1M of random letters to test it\nval = ''.join(random.choice(string.ascii_letters) for i in range(1000000))\n\ndef test_pure_python(benchmark):\n    benchmark(count_doubles, val)\n\ndef test_regex(benchmark):\n    benchmark(count_doubles_regex, val)\n```\n\nRun **pytest** to compare:\n\n\n```bash\n$ pytest doubles.py                                                                                                           \n=============================================================================\nplatform linux -- Python 3.6.0, pytest-3.2.3, py-1.4.34, pluggy-0.4.\nbenchmark: 3.1.1 (defaults: timer=time.perf_counter disable_gc=False min_roun\nrootdir: /Projects/rustpy, inifile:\nplugins: benchmark-3.1.1\ncollected 2 items\n\ndoubles.py ..\n\n\n-----------------------------------------------------------------------------\nName (time in ms)         Min                Max               Mean          \n-----------------------------------------------------------------------------\ntest_regex            24.6824 (1.0)      32.3960 (1.0)      27.0167 (1.0)    \ntest_pure_python      51.4964 (2.09)     62.5680 (1.93)     52.8334 (1.96)   \n-----------------------------------------------------------------------------\n\n```\n\nLets take the `Mean` for comparison:\n\n- **Regexp** - 27.0167    **\u003c-- less is better**\n- **Python Zip** - 52.8334  \n\n# Extending Python with Rust\n\n# Create a new crate\n\n\u003e **crate** is how we call Rust Packages.\n\nHaving rust installed (recommended way is https://www.rustup.rs/) \nRust is also available on Fedora and RHEL [rust-toolset](https://developers.redhat.com/blog/2017/11/01/getting-started-rust-toolset-rhel/)\n\n\u003e I used `rustc 1.21.0`\n\n\nIn the same folder run:\n\n```bash\ncargo new pyext-myrustlib\n```\n\nIt creates a new Rust project in that same folder called `pyext-myrustlib` containing the `Cargo.toml` (cargo is the Rust package manager) and also a `src/lib.rs` (where we write our library implementation)\n\n# Edit Cargo.toml\n\nIt will use the `rust-cpython` crate as dependency and tell cargo to generate a `dylib` to be imported from Python\n\n```toml\n[package]\nname = \"pyext-myrustlib\"\nversion = \"0.1.0\"\nauthors = [\"Bruno Rocha \u003crochacbruno@gmail.com\u003e\"]\n\n[lib]\nname = \"myrustlib\"\ncrate-type = [\"dylib\"]\n\n[dependencies.cpython]\nversion = \"0.1\"\nfeatures = [\"extension-module\"]\n```  \n\n# Edit src/lib.rs\n\nWhat we need to do:\n\n1) Import all macros from `cpython` crate\n2) Take `Python` and `PyResult` types from cpython in to our lib scope\n3) Write the `count_doubles` function implementation in `Rust`, note that this is very similar to the Pure Python version except for:\n\n    * It takes a `Python` as first argument, which is a reference to the Python Interpreter and allows Rust to use the `Python GIL`\n    * Receives a `\u0026str` typed `val` as reference\n    * Returns a `PyResult` which is a type that allows the raise of Python exceptions\n    * Returns a `PyResult` object in `Ok(total)` (**Result** is a enum type that represents either success (Ok) or failure (Err)) and as our function is expected to return a `PyResult` the compiler will take care of **wrapping** our `Ok` on that type. (note that our PyResult expects a `u64` as return value)\n\n4) Using `py_module_initializer!` macro we register new attributes to the lib, including the `__doc__` and also we add the `count_doubles` attribute referencing our `Rust implementation of the function`\n    * Attention to the names **lib**myrustlib, **initlib**myrustlib and **PyInit**_myrustlib which is suffixed by our library name (defined in Cargo.toml)\n    * We also use the `try!` macro which is the equivalent to Python's `try.. except`\n    * Return `Ok(())` - The `()` is an empty result tuple, the equivalent of `None` in Python\n\n```rust\n#[macro_use]\nextern crate cpython;\n\nuse cpython::{Python, PyResult};\n\nfn count_doubles(_py: Python, val: \u0026str) -\u003e PyResult\u003cu64\u003e {\n    let mut total = 0u64;\n\n    for (c1, c2) in val.chars().zip(val.chars().skip(1)) {\n        if c1 == c2 {\n            total += 1;\n        }\n    }\n\n    Ok(total)\n}\n\npy_module_initializer!(libmyrustlib, initlibmyrustlib, PyInit_myrustlib, |py, m | {\n    try!(m.add(py, \"__doc__\", \"This module is implemented in Rust\"));\n    try!(m.add(py, \"count_doubles\", py_fn!(py, count_doubles(val: \u0026str))));\n    Ok(())\n});\n\n```\n\nNow lets build it in cargo\n\n```bash\n$ cargo build --release\n    Finished release [optimized] target(s) in 0.0 secs\n\n$ ls -la target/release/libmyrustlib*\ntarget/release/libmyrustlib.d\ntarget/release/libmyrustlib.so*  \u003c-- Our dylib is here\n```\n\nNow lets copy the generated `.so` lib to the same folder where our `doubles.py` is:\n\n\u003e NOTE: on **Fedora** you must get a `.so` in other system you may get a `.dylib` and you can rename it changing extension to `.so`\n\n```bash\n$ cd ..\n$ ls\ndoubles.py pyext-myrustlib/\n\n$ cp pyext-myrustlib/target/release/libmyrustlib.so myrustlib.so\n\n$ ls\ndoubles.py myrustlib.so pyext-myrustlib/\n```\n\n\u003e Having the `myrustlib.so` in the same folder or added to your Python path allows it to be directly imported, transparently as it was a Python module.\n\n\n# Importing from Python and comparing the results\n\nEdit your `doubles.py` now importing our `Rust implemented` version and also adding a `benchmark` for it.\n\n\n```python\nimport re\nimport string\nimport random\nimport myrustlib   #  \u003c-- Import the Rust implemented module (myrustlib.so)\n\n\ndef count_doubles(val):\n    \"\"\"Count repeated pair of chars ins a string\"\"\"\n    total = 0\n    for c1, c2 in zip(val, val[1:]):\n        if c1 == c2:\n            total += 1\n    return total\n\n\ndouble_re = re.compile(r'(?=(.)\\1)')\n\n\ndef count_doubles_regex(val):\n    return len(double_re.findall(val))\n\n\nval = ''.join(random.choice(string.ascii_letters) for i in range(1000000))\n\n\ndef test_pure_python(benchmark):\n    benchmark(count_doubles, val)\n\n\ndef test_regex(benchmark):\n    benchmark(count_doubles_regex, val)\n\n\ndef test_rust(benchmark):   #  \u003c-- Benchmark the Rust version\n    benchmark(myrustlib.count_doubles, val)\n\n```\n\n# Benchmark\n\n```bash\n$ pytest doubles.py\n==============================================================================\nplatform linux -- Python 3.6.0, pytest-3.2.3, py-1.4.34, pluggy-0.4.\nbenchmark: 3.1.1 (defaults: timer=time.perf_counter disable_gc=False min_round\nrootdir: /Projects/rustpy, inifile:\nplugins: benchmark-3.1.1\ncollected 3 items\n\ndoubles_rust.py ...\n\n\n-----------------------------------------------------------------------------\nName (time in ms)         Min                Max               Mean          \n-----------------------------------------------------------------------------\ntest_rust              2.5555 (1.0)       2.9296 (1.0)       2.6085 (1.0)    \ntest_regex            25.6049 (10.02)    27.2190 (9.29)     25.8876 (9.92)   \ntest_pure_python      52.9428 (20.72)    56.3666 (19.24)    53.9732 (20.69)  \n-----------------------------------------------------------------------------\n```\n\nLets take the `Mean` for comparison:\n\n- **Rust** - 2.6085    **\u003c-- less is better**\n- **Regexp** - 25.8876\n- **Python Zip** - 53.9732\n\nRust implementation can be **10x** faster than Python Regex and **21x** faster than Pure Python Version.\n\n\u003e Interesting that **Regex** version is only 2x faster than Pure Python :)\n\n\u003e NOTE: That numbers makes sense only for this particular scenario, for other cases that comparison may be different.\n\n\n# Updates and improvements\n\nAfter this article has been published I got some comments on [r/python](https://www.reddit.com/r/Python/comments/7dct9v/use_rust_to_write_python_modules/)\nand also on [r/rust](https://www.reddit.com/r/rust/comments/7dctmp/red_hat_developers_blog_speed_up_your_python/) \n\nThe contributions come as [Pull Requests](https://github.com/rochacbruno/rust-python-example/pulls?utf8=%E2%9C%93\u0026q=is%3Apr) and you can send a new if you think the functions can be improved.\n\nThanks to: [Josh Stone](https://github.com/cuviper) we got a better implementarion for Rust which iterates the string only once and also the Python equivalent.\n\nThanks to: [Purple Pixie](https://github.com/purple-pixie) we got a Python implementation using `itertools`, however this version is not performing any better, needs improvements.\n\n\n## Iterating only once\n\n```rust\nfn count_doubles_once(_py: Python, val: \u0026str) -\u003e PyResult\u003cu64\u003e {\n    let mut total = 0u64;\n\n    let mut chars = val.chars();\n    if let Some(mut c1) = chars.next() {\n        for c2 in chars {\n            if c1 == c2 {\n                total += 1;\n            }\n            c1 = c2;\n        }\n    }\n\n    Ok(total)\n}\n```\n\n```python\ndef count_doubles_once(val):\n    total = 0\n    chars = iter(val)\n    c1 = next(chars)\n    for c2 in chars:\n        if c1 == c2:\n            total += 1\n        c1 = c2\n    return total\n```\n\n\n## Python with Itertools\n\n```python\nimport itertools\n\ndef count_doubles_itertools(val):\n    c1s, c2s = itertools.tee(val)\n    next(c2s, None)\n    total = 0\n    for c1, c2 in zip(c1s, c2s):\n        if c1 == c2:\n            total += 1\n    return total\n```\n\n### Why not C/C++/Nim/Go/Ĺua/PyPy/{other language}?\n\nOk, that is not the purpose of this post, this post was never about comparing `Rust` X `other language`, this post was specifically about\n**how to use Rust to extend and speed up Python** and by doing that it means you have a good reason to choose Rust instead of `other language`\nor by its ecosystem or by its safety and tooling or just to follow the hype, or simply because you like Rust\ndoesn't matter the reason, this post is here to show how to use it with **Python**.\n\nI (personally) may say that Rust is more `future proof` as it is new and there are lots of improvements to come, also because of its ecosystem, tooling and community\nand also because I feel comfortable with Rust syntax, I really like it!\n\nSo, as expected people started complaining about the use of other languages and it becomes a sort of benchmark, and I think it is cool! \n\nSo as part of my request for improvements some people on [Hacker News](https://news.ycombinator.com/item?id=15719254) also sent ideas, [martinxyz](https://github.com/martinxyz) sent an implementaion using\nC and SWIG that performed very well.\n\nC Code (swig boilerplate ommited)\n\n```c\nuint64_t count_byte_doubles(char * str) {\n  uint64_t count = 0;\n  while (str[0] \u0026\u0026 str[1]) {\n    if (str[0] == str[1]) count++;\n    str++;\n  }\n  return count;\n}\n```\n\nAnd our fellow Red Hatter [Josh Stone](https://github.com/cuviper) improved the Rust implementation again by replacing `chars` with `bytes` so it is a fair competition with `C` as\nC is comparing bytes instead of unicode chars.\n\n\n```rust\nfn count_doubles_once_bytes(_py: Python, val: \u0026str) -\u003e PyResult\u003cu64\u003e {\n    let mut total = 0u64;\n\n    let mut chars = val.bytes();\n    if let Some(mut c1) = chars.next() {\n        for c2 in chars {\n            if c1 == c2 {\n                total += 1;\n            }\n            c1 = c2;\n        }\n    }\n\n    Ok(total)\n}\n```\n\nThere are also ideas to compare Python `list comprehension` and `numpy` so I included here\n\nNumpy:\n\n```python\nimport numpy as np\n\ndef count_double_numpy(val):\n    ng=np.fromstring(val,dtype=np.byte)\n    return np.sum(ng[:-1]==ng[1:])\n```\n\nList comprehension\n\n```python\ndef count_doubles_comprehension(val):\n    return sum(1 for c1, c2 in zip(val, val[1:]) if c1 == c2)\n```\n\nThe complete test case is on repository `test_all.py` file.\n\n\n## New Results\n\n```bash\n-------------------------------------------------------------------------------------------------\nName (time in us)                     Min                    Max                   Mean          \n-------------------------------------------------------------------------------------------------\ntest_rust_bytes_once             476.7920 (1.0)         830.5610 (1.0)         486.6116 (1.0)    \ntest_c_swig_bytes_once           795.3460 (1.67)      1,504.3380 (1.81)        827.3898 (1.70)   \ntest_rust_once                   985.9520 (2.07)      1,483.8120 (1.79)      1,017.4251 (2.09)   \ntest_numpy                     1,001.3880 (2.10)      2,461.1200 (2.96)      1,274.8132 (2.62)   \ntest_rust                      2,555.0810 (5.36)      3,066.0430 (3.69)      2,609.7403 (5.36)   \ntest_regex                    24,787.0670 (51.99)    26,513.1520 (31.92)    25,333.8143 (52.06)  \ntest_pure_python_once         36,447.0790 (76.44)    48,596.5340 (58.51)    38,074.5863 (78.24)  \ntest_python_comprehension     49,166.0560 (103.12)   50,832.1220 (61.20)    49,699.2122 (102.13) \ntest_pure_python              49,586.3750 (104.00)   50,697.3780 (61.04)    50,148.6596 (103.06) \ntest_itertools                56,762.8920 (119.05)   69,660.0200 (83.87)    58,402.9442 (120.02) \n-------------------------------------------------------------------------------------------------\n\n```\n\n- The `new Rust implementation comparing bytes` is **2x better** than the old comparing unicode `chars`\n- The `Rust` version is still better than the `C` using SWIG\n- `Rust` comparing `unicode chars` is still better than `numpy`\n- However `Numpy` is better than the `first Rust implementation` which had the problem of **double iteration over the unicode chars**\n- Using a `list comprehension` does not make significative difference than using `pure Python`\n\n\u003e NOTE: If you want to propose changes or improvements send a PR here: https://github.com/rochacbruno/rust-python-example/\n\n\nI received more contributions as Pull Requests one of then was by [Jason Knight](https://github.com/binarybana) to improve `Rust` using \n\n```bash\nRUSTFLAGS=\"-C target-cpu=native\" cargo build --release\n```\n\nAnd for those who were curious about a comparison with `numba` so [Shyba](https://github.com/shyba) implemented it and it is available in the numba branch https://github.com/rochacbruno/rust-python-example/tree/numba.\n\n```python\nfrom numba import jit\n\n@jit(nopython=True, cache=True)\ndef count_doubles_once_numba(val):\n    total = 0\n    chars = iter(val)\n    c1 = next(chars)\n    for c2 in chars:\n        if c1 == c2:\n            total += 1\n        c1 = c2\n    return total\n```\n\nLook the new results with **numba** at the top, pretty close to **Rust**\n\n```bash\n----------------------------------------------------------------------------------------------------\nName (time in us)                       Min                    Max                   Mean           \n----------------------------------------------------------------------------------------------------\ntest_pure_python_once_numba        292.0990 (1.0)         317.7590 (1.0)         296.7477 (1.0)     \ntest_numpy_numba                   326.2470 (1.12)        526.1350 (1.66)        338.1704 (1.14)    \ntest_rust_bytes_once               336.0620 (1.15)      1,053.0090 (3.31)        342.5122 (1.15)    \ntest_c_swig_bytes_once             375.6310 (1.29)      1,389.9070 (4.37)        388.9181 (1.31)    \ntest_rust_once                     986.0360 (3.38)      2,498.5850 (7.86)      1,006.5819 (3.39)    \ntest_numpy                       1,137.1750 (3.89)      2,000.5430 (6.30)      1,167.2551 (3.93)    \ntest_rust                        2,555.1400 (8.75)      3,645.3900 (11.47)     2,592.0419 (8.73)    \ntest_regex                      22,597.1750 (77.36)    25,027.2820 (78.76)    22,851.8456 (77.01)   \ntest_pure_python_once           32,418.8830 (110.99)   34,818.0800 (109.57)   32,756.3244 (110.38)  \ntest_pure_python                43,823.5140 (150.03)   45,961.8460 (144.64)   44,367.1028 (149.51)  \ntest_python_comprehension       46,360.1640 (158.71)   50,578.1740 (159.17)   46,986.8058 (158.34)  \ntest_itertools                  49,080.8640 (168.03)   51,016.5230 (160.55)   49,405.2562 (166.49)  \n----------------------------------------------------------------------------------------------------\n```\n\nAnd there is also a **Cython** implementation by [MIke Fletcher](https://github.com/mcfletch) in the branch `cython` https://github.com/rochacbruno/rust-python-example/tree/cython \n\nwith the results:\n\n\n```bash\n----------------------------------------------------------------------------------------------------\nName (time in us)                       Min                    Max                   Mean           \n----------------------------------------------------------------------------------------------------\ntest_rust_bytes_once             336.7590 (1.0)         806.2610 (1.0)         346.5317 (1.0)       \ntest_cython                      756.1610 (2.25)      2,343.3680 (2.91)        785.6455 (2.27)      \ntest_c_swig_bytes_once           802.4250 (2.38)      1,632.4290 (2.02)        840.8603 (2.43)      \n----------------------------------------------------------------------------------------------------\n```\n\n\n# Conclusion\n\nBack to the purpose of this post **How to Speed Up your Python with Rust** we started with:\n\n- **Pure Python** function taking **102 **.\n- Improved with **Numpy** (which is implemented in C) to take **3**.\n- Ended with **Rust** taking **1** (just like numba version).\n\nIn this example **Rust** performed **100x** faster than our **Pure Python**.\n\n`Rust` will not magically save you, you must know the language to be able to implement the clever solution and once implemented in the right it worth as much as C in terms of performance and also comes with amazing tooling, ecosystem, community and safety bonuses. \n\n`Rust` may not be **yet** the `general purpose language` of choice by its level of complexity and may not be the better choice **yet** to write common simple `applications` such as `web` sites and `test automation` scripts.\n\nHowever, for `specific parts` of the project where Python is known to be the bottleneck and your natural choice would be implementing a `C/C++` extension, writing this extension in Rust seems easy and better to maintain.\n\nThere are still many improvements to come in Rust and lots of others crates to offer `Python \u003c--\u003e Rust` integration. Even if your are not including the language in your tool belt right now, it is really worth to keep an eye open to the future!\n\n## Credits\n\nThe examples on this publication are inspired by `Extending Python with Rust` talk by **Samuel Cormier-Iijima** in **Pycon Canada**.\nvideo here: https://www.youtube.com/watch?v=-ylbuEzkG4M\n\nAnd also by `My Python is a little Rust-y` by **Dan Callahan** in **Pycon Montreal**.\nvideo here: https://www.youtube.com/watch?v=3CwJ0MH-4MA\n\nOther references:\n\n- https://github.com/mitsuhiko/snaek\n- https://github.com/PyO3/pyo3\n- https://pypi.python.org/pypi/setuptools-rust\n- https://github.com/mckaymatt/cookiecutter-pypackage-rust-cross-platform-publish\n- http://jakegoulding.com/rust-ffi-omnibus/\n- https://github.com/urschrei/polylabel-rs/blob/master/src/ffi.rs\n- https://bheisler.github.io/post/calling-rust-in-python/\n- https://github.com/saethlin/rust-lather\n\nJoin Community:\n\nJoin Rust community, you can find group links in https://www.rust-lang.org/en-US/community.html\n\n**If you speak Portuguese** I recommend you to join https://t.me/rustlangbr and there\nis also the http://bit.ly/canalrustbr on Youtube.\n\n## Author\n\n**Bruno Rocha**\n- Senior Quality Enginner at **Red Hat**\n- Teaching Python at CursoDePython.com.br\n- Fellow Member of Python Software Foundation\n\nMore info: http://about.me/rochacbruno and http://brunorocha.org\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frochacbruno%2Frust-python-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frochacbruno%2Frust-python-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frochacbruno%2Frust-python-example/lists"}