All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Laight <david.laight.linux@gmail.com>
To: Guan-Chun Wu <409411716@gms.tku.edu.tw>
Cc: akpm@linux-foundation.org, andriy.shevchenko@intel.com,
	axboe@kernel.dk, ceph-devel@vger.kernel.org, ebiggers@kernel.org,
	hch@lst.de, home7438072@gmail.com, idryomov@gmail.com,
	jaegeuk@kernel.org, kbusch@kernel.org,
	linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-nvme@lists.infradead.org, sagi@grimberg.me, tytso@mit.edu,
	visitorckw@gmail.com, xiubli@redhat.com
Subject: Re: [PATCH v5 2/6] lib/base64: Optimize base64_decode() with reverse lookup tables
Date: Fri, 14 Nov 2025 09:14:54 +0000	[thread overview]
Message-ID: <20251114091454.5a5dbfc7@pumpkin> (raw)
In-Reply-To: <20251114060107.89026-1-409411716@gms.tku.edu.tw>

On Fri, 14 Nov 2025 14:01:07 +0800
Guan-Chun Wu <409411716@gms.tku.edu.tw> wrote:

> From: Kuan-Wei Chiu <visitorckw@gmail.com>
> 
> Replace the use of strchr() in base64_decode() with precomputed reverse
> lookup tables for each variant. This avoids repeated string scans and
> improves performance. Use -1 in the tables to mark invalid characters.
> 
> Decode:
>   64B   ~1530ns  ->  ~80ns    (~19.1x)
>   1KB  ~27726ns  -> ~1239ns   (~22.4x)
> 
> Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com>
> Co-developed-by: Guan-Chun Wu <409411716@gms.tku.edu.tw>
> Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw>

Reviewed-by: David Laight <david.laight.linux@gmail.com>

> ---
>  lib/base64.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 47 insertions(+), 4 deletions(-)
> 
> diff --git a/lib/base64.c b/lib/base64.c
> index a7c20a8e8e98..9d1074bb821c 100644
> --- a/lib/base64.c
> +++ b/lib/base64.c
> @@ -21,6 +21,49 @@ static const char base64_tables[][65] = {
>  	[BASE64_IMAP] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,",
>  };
>  
> +/**
> + * Initialize the base64 reverse mapping for a single character
> + * This macro maps a character to its corresponding base64 value,
> + * returning -1 if the character is invalid.
> + * char 'A'-'Z' maps to 0-25, 'a'-'z' maps to 26-51, '0'-'9' maps to 52-61,
> + * ch_62 maps to 62, ch_63 maps to 63, and other characters return -1
> + */
> +#define INIT_1(v, ch_62, ch_63) \
> +	[v] = (v) >= 'A' && (v) <= 'Z' ? (v) - 'A' \
> +		: (v) >= 'a' && (v) <= 'z' ? (v) - 'a' + 26 \
> +		: (v) >= '0' && (v) <= '9' ? (v) - '0' + 52 \
> +		: (v) == (ch_62) ? 62 : (v) == (ch_63) ? 63 : -1
> +/**
> + * Recursive macros to generate multiple Base64 reverse mapping table entries.
> + * Each macro generates a sequence of entries in the lookup table:
> + * INIT_2 generates 2 entries, INIT_4 generates 4, INIT_8 generates 8, and so on up to INIT_32.
> + */
> +#define INIT_2(v, ...) INIT_1(v, __VA_ARGS__), INIT_1((v) + 1, __VA_ARGS__)
> +#define INIT_4(v, ...) INIT_2(v, __VA_ARGS__), INIT_2((v) + 2, __VA_ARGS__)
> +#define INIT_8(v, ...) INIT_4(v, __VA_ARGS__), INIT_4((v) + 4, __VA_ARGS__)
> +#define INIT_16(v, ...) INIT_8(v, __VA_ARGS__), INIT_8((v) + 8, __VA_ARGS__)
> +#define INIT_32(v, ...) INIT_16(v, __VA_ARGS__), INIT_16((v) + 16, __VA_ARGS__)
> +
> +#define BASE64_REV_INIT(ch_62, ch_63) { \
> +	[0 ... 0x1f] = -1, \
> +	INIT_32(0x20, ch_62, ch_63), \
> +	INIT_32(0x40, ch_62, ch_63), \
> +	INIT_32(0x60, ch_62, ch_63), \
> +	[0x80 ... 0xff] = -1 }
> +
> +static const s8 base64_rev_maps[][256] = {
> +	[BASE64_STD] = BASE64_REV_INIT('+', '/'),
> +	[BASE64_URLSAFE] = BASE64_REV_INIT('-', '_'),
> +	[BASE64_IMAP] = BASE64_REV_INIT('+', ',')
> +};
> +
> +#undef BASE64_REV_INIT
> +#undef INIT_32
> +#undef INIT_16
> +#undef INIT_8
> +#undef INIT_4
> +#undef INIT_2
> +#undef INIT_1
>  /**
>   * base64_encode() - Base64-encode some binary data
>   * @src: the binary data to encode
> @@ -84,10 +127,9 @@ int base64_decode(const char *src, int srclen, u8 *dst, bool padding, enum base6
>  	int bits = 0;
>  	int i;
>  	u8 *bp = dst;
> -	const char *base64_table = base64_tables[variant];
> +	s8 ch;
>  
>  	for (i = 0; i < srclen; i++) {
> -		const char *p = strchr(base64_table, src[i]);
>  		if (padding) {
>  			if (src[i] == '=') {
>  				ac = (ac << 6);
> @@ -97,9 +139,10 @@ int base64_decode(const char *src, int srclen, u8 *dst, bool padding, enum base6
>  				continue;
>  			}
>  		}
> -		if (p == NULL || src[i] == 0)
> +		ch = base64_rev_maps[variant][(u8)src[i]];
> +		if (ch == -1)
>  			return -1;
> -		ac = (ac << 6) | (p - base64_table);
> +		ac = (ac << 6) | ch;
>  		bits += 6;
>  		if (bits >= 8) {
>  			bits -= 8;


  reply	other threads:[~2025-11-14  9:14 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-14  5:58 [PATCH v5 0/6] lib/base64: add generic encoder/decoder, migrate users Guan-Chun Wu
2025-11-14  6:00 ` [PATCH v5 1/6] lib/base64: Add support for multiple variants Guan-Chun Wu
2025-11-14  9:13   ` David Laight
2025-11-14  6:01 ` [PATCH v5 2/6] lib/base64: Optimize base64_decode() with reverse lookup tables Guan-Chun Wu
2025-11-14  9:14   ` David Laight [this message]
2025-11-14  6:01 ` [PATCH v5 3/6] lib/base64: rework encode/decode for speed and stricter validation Guan-Chun Wu
2025-11-14  9:18   ` David Laight
2025-11-16 10:28     ` Guan-Chun Wu
2025-11-17 17:46       ` Andrew Morton
2025-11-18 10:38         ` Andy Shevchenko
2025-11-18 17:24           ` Andrew Morton
2025-11-14  6:01 ` [PATCH v5 4/6] lib: add KUnit tests for base64 encoding/decoding Guan-Chun Wu
2025-11-14  6:02 ` [PATCH v5 5/6] fscrypt: replace local base64url helpers with lib/base64 Guan-Chun Wu
2025-11-14  6:02 ` [PATCH v5 6/6] ceph: replace local base64 " Guan-Chun Wu
2025-11-14 18:07   ` Viacheslav Dubeyko
2025-11-16 10:36     ` Guan-Chun Wu
2025-11-17 19:42       ` Viacheslav Dubeyko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251114091454.5a5dbfc7@pumpkin \
    --to=david.laight.linux@gmail.com \
    --cc=409411716@gms.tku.edu.tw \
    --cc=akpm@linux-foundation.org \
    --cc=andriy.shevchenko@intel.com \
    --cc=axboe@kernel.dk \
    --cc=ceph-devel@vger.kernel.org \
    --cc=ebiggers@kernel.org \
    --cc=hch@lst.de \
    --cc=home7438072@gmail.com \
    --cc=idryomov@gmail.com \
    --cc=jaegeuk@kernel.org \
    --cc=kbusch@kernel.org \
    --cc=linux-fscrypt@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nvme@lists.infradead.org \
    --cc=sagi@grimberg.me \
    --cc=tytso@mit.edu \
    --cc=visitorckw@gmail.com \
    --cc=xiubli@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.