Skip to content

Commit

Permalink
perf: reduce encode int buffer u128 -> u64 to boost parallel perf
Browse files Browse the repository at this point in the history
  • Loading branch information
uhmarcel committed Nov 20, 2022
1 parent 7266dba commit f9d3ee4
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 183 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/audit.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
on:
pull_request:
paths:
- '**/Cargo.toml'
- '**/Cargo.lock'
push:
branches:
- main
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rbase64"
version = "1.3.1"
version = "1.4.0"
edition = "2021"
description = "A simple base64 encoder / decoder CLI tool made in Rust"
authors = ["Marcel Riera <marcel.riera@outlook.com>"]
Expand Down
331 changes: 165 additions & 166 deletions benches/baseline.md

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ pub const ENCODE_MAP: &[u8; 64] =
b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
pub const DECODE_MAP: &[u8; 256] = &construct_decode_map();

pub const SIX_BIT_MASK: u128 = 0x3f;
pub const SIX_BIT_MASK: u64 = 0x3f;
pub const BYTE_MASK: u64 = 0xff;
pub const INVALID_BYTE: u8 = 0x40;

pub const ENC_CHUNK_SIZE: usize = 4;
pub const ENC_CHUNK_SIZE: usize = 2;
pub const DEC_CHUNK_SIZE: usize = 2;
pub const PARALLEL_THRESHOLD_BYTES: usize = 2 << 17; // 256 KiB

pub const ENC_U128_OFFSET: usize = (ENC_CHUNK_SIZE * 3 - 1) * 8;
pub const DEC_U64_OFFSET: usize = (DEC_CHUNK_SIZE * 4 - 1) * 6;

pub const PARALLEL_THRESHOLD_BYTES: usize = 2 << 16; // 128 KiB

const fn construct_decode_map() -> [u8; 256] {
let mut map = [INVALID_BYTE; 256];
let mut index = 0;
Expand Down
14 changes: 7 additions & 7 deletions src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::cmp::min;
use std::iter::zip;

#[inline(always)]
pub(crate) fn encode_u128_chunks(input: &[u8], buffer: &mut [u8]) {
pub(crate) fn encode_u64_chunks(input: &[u8], buffer: &mut [u8]) {
let in_chunks = input.chunks_exact(ENC_CHUNK_SIZE * 3);
let out_chunks = buffer.chunks_exact_mut(ENC_CHUNK_SIZE * 4);

Expand All @@ -14,7 +14,7 @@ pub(crate) fn encode_u128_chunks(input: &[u8], buffer: &mut [u8]) {
}

#[inline(always)]
pub(crate) fn encode_u128_chunks_parallel(input: &[u8], buffer: &mut [u8]) {
pub(crate) fn encode_u64_chunks_parallel(input: &[u8], buffer: &mut [u8]) {
let in_chunks = input.par_chunks_exact(ENC_CHUNK_SIZE * 3);
let out_chunks = buffer.par_chunks_exact_mut(ENC_CHUNK_SIZE * 4);

Expand Down Expand Up @@ -57,13 +57,13 @@ fn encode_u128(input: &[u8], buffer: &mut [u8]) {
}

#[inline(always)]
fn read_u128_partial(bytes: &[u8]) -> u128 {
let size = min(bytes.len(), 16);
let mut buffer = [0u8; 16];
fn read_u128_partial(bytes: &[u8]) -> u64 {
let mut buffer = [0u8; 8];
let size = min(bytes.len(), 8);

buffer[16 - size..].copy_from_slice(&bytes[..size]);
buffer[8 - size..].copy_from_slice(&bytes[..size]);

u128::from_be_bytes(buffer)
u64::from_be_bytes(buffer)
}

#[inline(always)]
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ pub fn encode(input: &[u8]) -> String {
let total_chunks = input.len() / (ENC_CHUNK_SIZE * 3);

if input.len() < PARALLEL_THRESHOLD_BYTES {
encode::encode_u128_chunks(input, &mut buffer);
encode::encode_u64_chunks(input, &mut buffer);
} else {
encode::encode_u128_chunks_parallel(input, &mut buffer);
encode::encode_u64_chunks_parallel(input, &mut buffer);
};

let bytes_rem = encode_u128_remainder(
Expand Down

0 comments on commit f9d3ee4

Please sign in to comment.