File 4131-base64-Optimize-encoding-and-decoding-of-binaries.patch of Package erlang

From a03cf1601605dee767cd9d5f18fc44fc39148795 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Thu, 25 Aug 2022 04:09:21 +0200
Subject: [PATCH] base64: Optimize encoding and decoding of binaries

We will take advantage of the newly introduced performance
improvements for binary matching to speed up Base64 encoding and
decoding.

For decoding, we now attempt to match out four characters at once
because that is faster than matching out one character at the time.

For encoding, we now match out four 6-bit chunks at once, which
allows us to eliminate the bit shifting and masking operations.
(For some more speed, we first try to match out eight 6-bits chunks
at once.)

Fixes #5639
---
 lib/stdlib/src/base64.erl | 82 ++++++++++++++++++++++++++++++++-------
 1 file changed, 67 insertions(+), 15 deletions(-)

diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl
index be4d9d42b4..600f73a4cb 100644
--- a/lib/stdlib/src/base64.erl
+++ b/lib/stdlib/src/base64.erl
@@ -70,21 +70,30 @@ encode_list_to_string([B1,B2,B3|Ls]) ->
      b64e((BB bsr 6) band 63),
      b64e(BB band 63) | encode_list_to_string(Ls)].
 
+encode_binary(<<B1:6, B2:6, B3:6, B4:6, B5:6, B6:6, B7:6, B8:6, Ls/bits>>, A) ->
+    encode_binary(Ls,
+                  <<A/bits,
+                    (b64e(B1)):8,
+                    (b64e(B2)):8,
+                    (b64e(B3)):8,
+                    (b64e(B4)):8,
+                    (b64e(B5)):8,
+                    (b64e(B6)):8,
+                    (b64e(B7)):8,
+                    (b64e(B8)):8>>);
 encode_binary(<<>>, A) ->
     A;
-encode_binary(<<B1:8>>, A) ->
-    <<A/bits,(b64e(B1 bsr 2)):8,(b64e((B1 band 3) bsl 4)):8,$=:8,$=:8>>;
-encode_binary(<<B1:8, B2:8>>, A) ->
-    <<A/bits,(b64e(B1 bsr 2)):8,
-      (b64e(((B1 band 3) bsl 4) bor (B2 bsr 4))):8,
-      (b64e((B2 band 15) bsl 2)):8, $=:8>>;
-encode_binary(<<B1:8, B2:8, B3:8, Ls/bits>>, A) ->
-    BB = (B1 bsl 16) bor (B2 bsl 8) bor B3,
+encode_binary(<<B1:6, B2:6, B3:6, B4:6, Ls/bits>>, A) ->
     encode_binary(Ls,
-                  <<A/bits,(b64e(BB bsr 18)):8,
-                    (b64e((BB bsr 12) band 63)):8,
-                    (b64e((BB bsr 6) band 63)):8,
-                    (b64e(BB band 63)):8>>).
+                  <<A/bits,
+                    (b64e(B1)):8,
+                    (b64e(B2)):8,
+                    (b64e(B3)):8,
+                    (b64e(B4)):8>>);
+encode_binary(<<B1:6, B2:2>>, A) ->
+    <<A/bits,(b64e(B1)):8,(b64e(B2 bsl 4)):8,$=:8,$=:8>>;
+encode_binary(<<B1:6, B2:6, B3:4>>, A) ->
+    <<A/bits,(b64e(B1)):8,(b64e(B2)):8,(b64e(B3 bsl 2)):8, $=:8>>.
 
 encode_list([], A) ->
     A;
@@ -358,13 +367,56 @@ decode_list([C4 | Cs], A, B1, B2, B3) ->
         B4                -> decode_list(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>)
     end.
 
+decode_binary(<<C1:8, C2:8, C3:8, C4:8, Cs/bits>>, A) ->
+    case {b64d(C1), b64d(C2), b64d(C3), b64d(C4)} of
+        {B1, B2, B3, B4} when is_integer(B1), is_integer(B2),
+                              is_integer(B3), is_integer(B4) ->
+            decode_binary(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>);
+        {B1, B2, B3, B4} ->
+            dec_bin(Cs, B1, B2, B3, B4, A)
+    end;
+decode_binary(<<>>, A) ->
+    A;
 decode_binary(<<C1:8, Cs/bits>>, A) ->
     case b64d(C1) of
         ws -> decode_binary(Cs, A);
         B1 -> decode_binary(Cs, A, B1)
-    end;
-decode_binary(<<>>, A) ->
-    A.
+    end.
+
+dec_bin(Cs, ws, B2, B3, B4, A) ->
+    dec_bin(Cs, B2, B3, B4, A);
+dec_bin(Cs, B1, ws, B3, B4, A) ->
+    dec_bin(Cs, B1, B3, B4, A);
+dec_bin(Cs, B1, B2, ws, B4, A) ->
+    dec_bin(Cs, B1, B2, B4, A);
+dec_bin(Cs, B1, B2, B3, B4, A) ->
+    case B4 of
+        ws                -> decode_binary(Cs, A, B1, B2, B3);
+        eq when B3 =:= eq -> only_ws_binary(Cs, <<A/bits,B1:6,(B2 bsr 4):2>>);
+        eq                -> only_ws_binary(Cs, <<A/bits,B1:6,B2:6,(B3 bsr 2):4>>);
+        B4                -> decode_binary(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>)
+    end.
+
+dec_bin(Cs, ws, B2, B3, A) ->
+    dec_bin(Cs, B2, B3, A);
+dec_bin(Cs, B1, ws, B3, A) ->
+    dec_bin(Cs, B1, B3, A);
+dec_bin(Cs, B1, B2, ws, A) ->
+    dec_bin(Cs, B1, B2, A);
+dec_bin(Cs, B1, B2, B3, A) ->
+    decode_binary(Cs, A, B1, B2, B3).
+
+dec_bin(Cs, ws, B2, A) ->
+    dec_bin(Cs, B2, A);
+dec_bin(Cs, B1, ws, A) ->
+    dec_bin(Cs, B1, A);
+dec_bin(Cs, B1, B2, A) ->
+    decode_binary(Cs, A, B1, B2).
+
+dec_bin(Cs, ws, A) ->
+    decode_binary(Cs, A);
+dec_bin(Cs, B1, A) ->
+    decode_binary(Cs, A, B1).
 
 decode_binary(<<C2:8, Cs/bits>>, A, B1) ->
     case b64d(C2) of
-- 
2.35.3

openSUSE Build Service is sponsored by