Skip to content

Commit

Permalink
perf: improve padding performance
Browse files Browse the repository at this point in the history
this results in a ~10-20% speedup in benchmarks.
  • Loading branch information
mplanchard committed Sep 20, 2021
1 parent c73899d commit b5503d6
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 10 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Performance is one of the primary concerns of this library (see
This implementation is currently about 20x faster than the reference JavaScript
implementation.

It takes about 400 nanoseconds to generate a CUID, or 335 nanoseconds
It takes about 300 nanoseconds to generate a CUID, or 250 nanoseconds
to generate a CUID slug, on relatively modern desktop hardware.

In a long-running process or thread, CUID generation is faster, since the system
Expand Down Expand Up @@ -89,4 +89,10 @@ from other processes running on the system:
$ nice -n -20 cargo bench
```

Note that you may need to run `nice` as root:

``` text
sudo nice -n -20 su <username> -l -c "cd $PWD && cargo bench"
```

[benches]: ./benches/cuid.rs
7 changes: 6 additions & 1 deletion src/fingerprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ fn pid() -> Result<String, CuidError> {
.map_err(|_| CuidError::FingerprintError("Could not encode pid"))
}

/// Convert the hostname to a padded String in the appropriate base
/// Convert the hostname to a padded String in the appropriate base.
///
/// First converts the hostname to a number comprising the length of the
/// hostname, added to the base radix for CUID strings, added to the sum of
/// the integer value of each character in the hostname, then converts that
/// number to base radix.
fn convert_hostname(hn: &str) -> Result<String, CuidError> {
to_base_string(
hn.chars()
Expand Down
22 changes: 14 additions & 8 deletions src/text.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::f64;
use std::{char, cmp::Ordering};
use std::{f64, iter};

use crate::error::CuidError;
use crate::BASE;

/// Convert a number to a string of the specified radix.
fn to_radix_string<N: Into<u128>>(radix: u8, number: N) -> Result<String, CuidError> {
let mut number = number.into();
let rad_u32: u32 = radix.into();
Expand All @@ -19,7 +20,7 @@ fn to_radix_string<N: Into<u128>>(radix: u8, number: N) -> Result<String, CuidEr
return Err(CuidError::TextError("Input number too large"));
}

// 64 chars should almost always be enough to fill without needing to grow
// 32 chars should almost always be enough to fill without needing to grow
let mut chars: Vec<char> = Vec::with_capacity(32);
while number > 0 {
// We can unwrap here b/c we know that the modulus must be less than the
Expand All @@ -35,6 +36,11 @@ pub fn to_base_string<N: Into<u128>>(number: N) -> Result<String, CuidError> {
to_radix_string(BASE, number)
}

/// Pad a string `to_pad` up to size `size` with char `char`
///
/// Inserts `char` at the beginning of the string until the string is equal to
/// size `size`. If `to_pad` is longer than `size`, remove characters from the
/// start of the string until it is of size `size`.
fn pad_with_char(pad_char: char, size: usize, mut to_pad: String) -> String {
let length = to_pad.len();

Expand All @@ -44,16 +50,16 @@ fn pad_with_char(pad_char: char, size: usize, mut to_pad: String) -> String {
Ordering::Greater => {
// Cut from the start of the string to pad down to the expected size,
// e.g. for a size of 2, `abc` would become `bc`
to_pad.replace_range(0..length - size, "");
return to_pad;
// benchmarking has shown that returning a new string here is faster
// than mutating the old one
return to_pad[length - size..].to_string();
}
}

let size_diff = size - length;
to_pad.reserve(size_diff);
for _ in 0..size_diff {
to_pad.insert(0, pad_char);
}

let to_insert: String = iter::once(pad_char).cycle().take(size_diff).collect();
to_pad.insert_str(0, &to_insert);
to_pad
}

Expand Down

0 comments on commit b5503d6

Please sign in to comment.