Python package for string case formatting; implemented in Rust.
Project description
This module offers a handful of case-formatting utility functions. It is a very simple Python package, written in Rust and implemented using pyo3 which offers you easy Rust bindings for the Python interpreter.
Installation
Install with pip using:
pip install rscase
Note: This package requires Rust nightly 2020-02-06
or an equivalent future release.
Usage
The package provides utility functions for generating strings formatted in several different case standards.
The case-standards and their functions are listed below.
Supported cases |
Function |
Format example |
---|---|---|
camel case |
camel_case |
camelCasedValue |
snake case |
snake_case |
snake_cased_value |
pascal case |
pascal_case |
PascalCasedValue |
kebab case |
kebab_case |
kebab-cased-value |
train case |
train_case |
TRAIN-CASED-VALUE |
All functions are imported and accessed the same way:
>> [in] from rscase import rscase
>> [in] rscase.camel_case('this_is-a_Test')
>> [out] thisIsATest
If you want to use this package, please note that the case functions are written to successfully convert camel case and snake case to the remaining formats. Formatting train case to itself doesn’t really make sense, and the way I would use this would be to, e.g., serialize out response data to a camelCased format.
Benchmarking Performance
This repo is a bit of an experiment, and because the functions contained in this package only do some very simple string manipulation, they seem like they might actually be good candidates for Python vs Rust performance benchmarking.
To try and make this a fair comparison - to make sure we’re comparing apples to apples - I decided to test the Rust function snake_case (see the Rust function here) to an identical Python function. The Python version is shown below:
from rscase import rscase
test_string = "thisIsALongCamelCasedAlphabeticKey"
# Test functions
def original_snake_case():
string = test_string
new_string = ""
dash = "-"
for index in range(len(string)):
if index == 0:
new_string += string[index].lower()
elif string[index] == dash:
new_string += '_'
elif string[index].upper() == string[index]:
new_string += f'_{string[index]}'
else:
new_string += string[index]
return new_string
def rust_snake_case():
string = test_string
return rscase.snake_case(string)
The main difference between the two functions, flow-wise, is only that Rust won’t let you just iterate over a string, so you have to create a vector of char’s instead - or at least that’s how I did it.
Results
After running the tests, the results seems to be pretty promising - in favor of the Rust implementation.
Reps |
Rust Execution Time |
Python Execution Time |
Difference |
---|---|---|---|
1 |
18.30 us |
14.20 us |
0.78x* |
10 |
55.20 us |
114.20 us |
2.07x |
100 |
.49 ms |
1.11 ms |
2.27x |
1000 |
4.88 ms |
11.18 ms |
2.28x |
10 000 |
47.20 ms |
109.13 ms |
2.31x |
100 000 |
.47 s |
1.08 s |
2.31x |
1000 000 |
4.83 s |
11.12 s |
2.30x |
10 000 000 |
46.67 s |
109.27 s |
2.34x |
100 000 000 |
484 s |
1102 s |
2.28x |
The results are pretty clear: after only 100 reps, the results seem to stabilize, and flatten out at around a 2.3x longer execution time for the Python implementation.
* the 1-rep result seems to show that Python actually outperforms Rust in the scenario that would normally actually matter. Since it makes sense that variance would be high when trying to measure something at the microsecond level I decided to run this individual scenario again, another one million times, to increase the sample size. With a larger sample, the average difference for 1 rep averages to 1.85x slower in Python, and the median is 1.88x. In short, the Rust implementation seems to outperform the Python across the board.
Benchmarking Performance - Update
Thanks to Thomas Hartmann for suggesting a significant performance improvement in the packaged Rust code.
Using some experimental features, we’re able to improve the performance of the Rust code considerably. The snake_case
test from above is replicated below, with the performance difference settling at 5x the Python performance.
Reps |
Rust Execution Time |
Python Execution Time |
Difference |
---|---|---|---|
1 |
10.70 us |
15.20 us |
1.42x |
10 |
28.70 us |
113.30 us |
3.95x |
100 |
.24 ms |
1.11 ms |
4.56x |
1000 |
2.24 ms |
11.28 ms |
5.03x |
10 000 |
22.16 ms |
107.79 ms |
4.86x |
100 000 |
.24 s |
1.09 s |
4.44x |
1000 000 |
2.21 s |
11.02 s |
4.99x |
10 000 000 |
22.09 s |
110.47 s |
5.00x |
100 000 000 |
222 s |
1086 s |
4.88x |
Running the 1 rep
scenario one million times, gives an average Rust execution time of 3.84 us compared to an average Python execution time of 12.61 us (~3.3x slower for Python).
This time around, I also decided to test the camel case implementations, as the logic does behave a bit differently:
Reps |
Rust Execution Time |
Python Execution Time |
Difference |
---|---|---|---|
1 |
10.99 us |
14.40 us |
1.31x |
10 |
39.79 us |
106.90 us |
2.69x |
100 |
.25 ms |
1.02 ms |
4.07x |
1000 |
2.40 ms |
10.24 ms |
4.26x |
10 000 |
23.55 ms |
100.17 ms |
4.25x |
100 000 |
.23 s |
0.98 s |
4.26x |
1000 000 |
2.34 s |
9.92 s |
4.23x |
10 000 000 |
23.23 s |
98.91 s |
4.26x |
100 000 000 |
232 s |
990 s |
4.26x |
Running the 1 rep
scenario one million times, gives an average Rust execution time of 3.90 us compared to an average Python execution time of 11.48 us (almost ~3x slower for Python).
In summary, the benchmarked performed similarly, with Rust pulling ahead even more, for these two implementations. At the same time, there’s probably room for improvement for both implementations still, and probably especially for the Python one.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
File details
Details for the file rscase-1.1.1.tar.gz
.
File metadata
- Download URL: rscase-1.1.1.tar.gz
- Upload date:
- Size: 7.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.7.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ff729b1c83fd6c3b2062004a60f50accb635337b55998debc5f2841efec0f17c |
|
MD5 | 60fc6fc586f6d35883de24e8e7862c34 |
|
BLAKE2b-256 | 58923cf1c0947d20400bef9090c74287c66053b75b05f3e3247f3542be3521bb |
File details
Details for the file rscase-1.1.1-cp38-cp38-win_amd64.whl
.
File metadata
- Download URL: rscase-1.1.1-cp38-cp38-win_amd64.whl
- Upload date:
- Size: 115.6 kB
- Tags: CPython 3.8, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.8.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0093eaf411dc95dc485f0f083450ed481cf0e09ea66f09d133f9a674d7128b55 |
|
MD5 | 3aa25dcf2695736e6fe41fa1d3262cc2 |
|
BLAKE2b-256 | f7c95182f80f06d7d452bc9fcc6ab2d0815ded0e7fe8fcabf85521d691039773 |
File details
Details for the file rscase-1.1.1-cp38-cp38-manylinux2010_x86_64.whl
.
File metadata
- Download URL: rscase-1.1.1-cp38-cp38-manylinux2010_x86_64.whl
- Upload date:
- Size: 716.7 kB
- Tags: CPython 3.8, manylinux: glibc 2.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.8.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | f99d904afe40b57c8f260db8e64826ae49582c2396dbd3373b5243127262cdf7 |
|
MD5 | 121e6366b7858c60c50667a4745cd544 |
|
BLAKE2b-256 | 9f14c3e95ac9d3c917389b4c60d30d14239d622d21b2bc92aa03cc5be79eaa38 |
File details
Details for the file rscase-1.1.1-cp38-cp38-manylinux2010_i686.whl
.
File metadata
- Download URL: rscase-1.1.1-cp38-cp38-manylinux2010_i686.whl
- Upload date:
- Size: 791.9 kB
- Tags: CPython 3.8, manylinux: glibc 2.12+ i686
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.8.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6c654e21f302233acbe9e56641fe9c3cd52415ae103616f78bdbbbc309ea3fa6 |
|
MD5 | 829e2ca8e47d31e6040a653663900d9f |
|
BLAKE2b-256 | 6108792457f7d291b3b7fc676c8e91724596d3fd31c8a9ea61765da4501a5e2b |
File details
Details for the file rscase-1.1.1-cp38-cp38-manylinux1_x86_64.whl
.
File metadata
- Download URL: rscase-1.1.1-cp38-cp38-manylinux1_x86_64.whl
- Upload date:
- Size: 716.7 kB
- Tags: CPython 3.8
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.8.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2eb21dddcb0a8df88e5477b85c9e84a1ebd5d4c901afbe78d1e929ab8d0dc647 |
|
MD5 | e8608c118f5df42e84821d08df05d2d6 |
|
BLAKE2b-256 | e3ed8aa11ab698f4fdba2b516305fb6126c7e30f2463da27d6512e155b868e2f |
File details
Details for the file rscase-1.1.1-cp38-cp38-manylinux1_i686.whl
.
File metadata
- Download URL: rscase-1.1.1-cp38-cp38-manylinux1_i686.whl
- Upload date:
- Size: 791.9 kB
- Tags: CPython 3.8
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.8.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 72b365936d90ec4ed11267bc3c1e7a79b0be4b48981a6711d257aef2c889d91d |
|
MD5 | 9bd7d1e6651a48d0a4ce9aaba66e7a78 |
|
BLAKE2b-256 | 3cf0db36f59b38a6858018d22749eac8c351aa99fb7c42993a04be377c254d60 |
File details
Details for the file rscase-1.1.1-cp37-cp37m-win_amd64.whl
.
File metadata
- Download URL: rscase-1.1.1-cp37-cp37m-win_amd64.whl
- Upload date:
- Size: 115.6 kB
- Tags: CPython 3.7m, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.7.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6c52f9cf4e7a29d8568c8d53f889f1a0bfdff59aefc511ba039ad5e05f512873 |
|
MD5 | f768a9b9a798b524fe69f41360180698 |
|
BLAKE2b-256 | 472dcb2ee293b34f62f8ae7bdcfb2a089d898851bb1e4ba9053171fbd4c5cbcd |
File details
Details for the file rscase-1.1.1-cp37-cp37m-manylinux2010_x86_64.whl
.
File metadata
- Download URL: rscase-1.1.1-cp37-cp37m-manylinux2010_x86_64.whl
- Upload date:
- Size: 716.6 kB
- Tags: CPython 3.7m, manylinux: glibc 2.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.7.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 93ea03597a1144a85022bf835fddcca9962a74b7517c326ca297b87b01b46b65 |
|
MD5 | f7c467d34489b7b30fc1d89492ec2bae |
|
BLAKE2b-256 | 9535bcda6c0e53736b0f75b6e50297260bd1552064f363e79a4ed694987d2168 |
File details
Details for the file rscase-1.1.1-cp37-cp37m-manylinux2010_i686.whl
.
File metadata
- Download URL: rscase-1.1.1-cp37-cp37m-manylinux2010_i686.whl
- Upload date:
- Size: 792.0 kB
- Tags: CPython 3.7m, manylinux: glibc 2.12+ i686
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.7.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ce6e8e0dddfd1ac2ef56bb20fb3f26e59e945428819f0115348472999a922c5a |
|
MD5 | c1041bfc2b2e567648d29bf9c78fafb6 |
|
BLAKE2b-256 | 88edad9730001d4ba77a76b7a083cc93b74035ec9e49b23bc4f05898f66b39e8 |
File details
Details for the file rscase-1.1.1-cp37-cp37m-manylinux1_x86_64.whl
.
File metadata
- Download URL: rscase-1.1.1-cp37-cp37m-manylinux1_x86_64.whl
- Upload date:
- Size: 716.6 kB
- Tags: CPython 3.7m
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.7.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | bd3a5a78bdcd9f41df95f40bbdd552fd4004416e27a10ad865106d400c384e5c |
|
MD5 | a7c2bdec32e5fccbae436280761eea19 |
|
BLAKE2b-256 | f36f0b1f6c50c2d8f969351406da0ab78b78743ab47e193148f5d02fbeaf1edc |
File details
Details for the file rscase-1.1.1-cp37-cp37m-manylinux1_i686.whl
.
File metadata
- Download URL: rscase-1.1.1-cp37-cp37m-manylinux1_i686.whl
- Upload date:
- Size: 792.0 kB
- Tags: CPython 3.7m
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.7.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 975ef8a8386107626433455b677a12750015838e797dc559939108363e4e7fb3 |
|
MD5 | 29c27d915c426134a90cc3d2fbf3ebfa |
|
BLAKE2b-256 | 0fabbdeac3d82a79727acae20beba1f241dcdbc8bf69114688d8f82b1e371797 |