Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Speed up Base58 encoding/decoding by 400%/200% via preliminary byte packing #29473

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Commits on May 29, 2024

  1. Configuration menu
    Copy the full SHA
    d419b39 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    5821eea View commit details
    Browse the repository at this point in the history
  3. Encode by iterating forward and dividing in-place

    Instead of collecting the values to and empty b58, we're cloning the input without leading zeros and dividing it in-place, while doing the quadratic division from the most significant, non-zero digit, forward.
    
    make && ./src/bench/bench_bitcoin --filter=Base58Encode --min-time=1000
    Before:
    ```
    |             ns/byte |              byte/s |    err% |     total | benchmark
    |--------------------:|--------------------:|--------:|----------:|:----------
    |               59.34 |       16,851,250.88 |    0.2% |      1.10 | `Base58Encode`
    |               59.20 |       16,892,479.61 |    0.2% |      1.10 | `Base58Encode`
    |               58.97 |       16,958,226.76 |    0.2% |      1.10 | `Base58Encode`
    ```
    After:
    ```
    |             ns/byte |              byte/s |    err% |     total | benchmark
    |--------------------:|--------------------:|--------:|----------:|:----------
    |               40.80 |       24,508,402.06 |    0.1% |      1.10 | `Base58Encode`
    |               40.83 |       24,489,762.49 |    0.2% |      1.10 | `Base58Encode`
    |               39.71 |       25,182,310.62 |    0.2% |      1.10 | `Base58Encode`
    ```
    
    and
    
    make && ./src/bench/bench_bitcoin --filter=Base58CheckEncode --min-time=1000
    Before:
    ```
    |             ns/byte |              byte/s |    err% |     total | benchmark
    |--------------------:|--------------------:|--------:|----------:|:----------
    |               79.93 |       12,511,576.75 |    0.4% |      1.10 | `Base58CheckEncode`
    |               79.49 |       12,580,136.21 |    0.1% |      1.10 | `Base58CheckEncode`
    |               79.65 |       12,554,785.16 |    0.1% |      1.10 | `Base58CheckEncode`
    ```
    After:
    ```
    |             ns/byte |              byte/s |    err% |     total | benchmark
    |--------------------:|--------------------:|--------:|----------:|:----------
    |               55.27 |       18,094,561.35 |    0.1% |      1.10 | `Base58CheckEncode`
    |               55.41 |       18,046,778.32 |    0.1% |      1.10 | `Base58CheckEncode`
    |               55.32 |       18,075,763.16 |    0.1% |      1.10 | `Base58CheckEncode`
    ```
    paplorinc committed May 29, 2024
    Configuration menu
    Copy the full SHA
    30167f2 View commit details
    Browse the repository at this point in the history
  4. Speed up Base58 encoding with 64-bit packing

    To mitigate the quadratic complexity inherent in the sequential byte division of the Base58 encoding process, this update aggregates characters into groups of 7, fitting them into 64-bit long integers.
    This refinement utilizes the inherent efficiency of native division and modulo operations on 64-bit architectures, significantly optimizing computational overhead.
    The benchmarks indicate a 4x speedup for `Base58CheckEncode` and `Base58Encode`:
    
    make && ./src/bench/bench_bitcoin --filter=Base58Encode --min-time=1000
    After:
    ```
    |             ns/byte |              byte/s |    err% |     total | benchmark
    |--------------------:|--------------------:|--------:|----------:|:----------
    |               14.32 |       69,831,031.44 |    0.1% |      1.10 | `Base58Encode`
    |               14.32 |       69,811,995.18 |    0.1% |      1.10 | `Base58Encode`
    |               14.35 |       69,662,527.88 |    0.5% |      1.10 | `Base58Encode`
    ```
    
    make && ./src/bench/bench_bitcoin --filter=Base58CheckEncode --min-time=1000
    After:
    ```
    |             ns/byte |              byte/s |    err% |     total | benchmark
    |--------------------:|--------------------:|--------:|----------:|:----------
    |               19.15 |       52,231,968.11 |    0.1% |      1.06 | `Base58CheckEncode`
    |               19.13 |       52,269,345.54 |    0.4% |      1.05 | `Base58CheckEncode`
    |               19.14 |       52,244,117.61 |    0.3% |      1.06 | `Base58CheckEncode`
    ```
    paplorinc committed May 29, 2024
    Configuration menu
    Copy the full SHA
    a091223 View commit details
    Browse the repository at this point in the history
  5. Decode by iterating forward and dividing in-place

    > make && ./src/bench/bench_bitcoin --filter=Base58Decode --min-time=1000
    Before:
    ```
    |             ns/byte |              byte/s |    err% |     total | benchmark
    |--------------------:|--------------------:|--------:|----------:|:----------
    |               17.50 |       57,141,622.65 |    0.1% |      1.10 | `Base58Decode`
    |               17.42 |       57,392,223.96 |    0.0% |      1.10 | `Base58Decode`
    |               17.43 |       57,358,655.44 |    0.2% |      1.10 | `Base58Decode`
    ```
    After:
    ```
    |             ns/byte |              byte/s |    err% |     total | benchmark
    |--------------------:|--------------------:|--------:|----------:|:----------
    |               16.37 |       61,093,842.90 |    0.2% |      1.10 | `Base58Decode`
    |               16.37 |       61,100,514.64 |    0.1% |      1.10 | `Base58Decode`
    |               16.38 |       61,046,275.93 |    0.1% |      1.10 | `Base58Decode`
    ```
    paplorinc committed May 29, 2024
    Configuration menu
    Copy the full SHA
    a8e1bae View commit details
    Browse the repository at this point in the history
  6. Speed up Base58 decoding with 64-bit packing

    > make && ./src/bench/bench_bitcoin --filter=Base58Decode --min-time=1000
    
    After:
    ```
    |             ns/byte |              byte/s |    err% |     total | benchmark
    |--------------------:|--------------------:|--------:|----------:|:----------
    |                8.79 |      113,767,685.06 |    0.1% |      1.10 | `Base58Decode`
    |                8.78 |      113,831,528.33 |    0.0% |      1.10 | `Base58Decode`
    |                8.80 |      113,607,470.35 |    0.2% |      1.10 | `Base58Decode`
    ```
    paplorinc committed May 29, 2024
    Configuration menu
    Copy the full SHA
    b774fca View commit details
    Browse the repository at this point in the history