Skip to content

Commit

Permalink
Reimplemented encoding and implemented decoding (#1)
Browse files Browse the repository at this point in the history
- base64url support
- added more tests
- added performance tests
- improved README.md
  • Loading branch information
fabianfett committed Dec 10, 2019
1 parent 302a8af commit e4d0371
Show file tree
Hide file tree
Showing 9 changed files with 598 additions and 63 deletions.
21 changes: 21 additions & 0 deletions .codecov.yml
@@ -0,0 +1,21 @@
coverage:
status:
project:
default: off
base64:
flags: base64
target: 100%
unittest:
flags: unittest
performance:
flags: performance
flags:
base64:
paths:
- Sources/Base64
performance:
paths:
- Sources/PerformanceTest
unittests:
paths:
- Tests/Base64Tests
38 changes: 35 additions & 3 deletions .github/workflows/ci.yaml
Expand Up @@ -8,6 +8,7 @@ on:
- master

jobs:

"tuxOS-Tests":
runs-on: ubuntu-latest
strategy:
Expand All @@ -23,8 +24,6 @@ jobs:
uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Install dependencies
run: apt-get update && apt-get install -y zlib1g-dev zip openssl libssl-dev
- name: Test
run: swift test --enable-code-coverage --enable-test-discovery
- name: Convert coverage files
Expand All @@ -33,6 +32,28 @@ jobs:
uses: codecov/codecov-action@v1.0.3
with:
token: ${{secrets.CODECOV_TOKEN}}
flags: base64,unittests
file: info.lcov

"tuxOS-Performance-Tests":
runs-on: ubuntu-latest
strategy:
matrix:
tag: ['5.1']
container:
image: swift:${{ matrix.tag }}
volumes:
- $GITHUB_WORKSPACE:/src
options: --workdir /src
steps:
- name: Checkout
uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Build
run: swift build -c release
- name: Run test
run: .build/release/Base64PerformanceTest

"macOS-Tests":
runs-on: macOS-latest
Expand All @@ -54,5 +75,16 @@ jobs:
swift package generate-xcodeproj
xcodebuild -quiet -parallel-testing-enabled YES -scheme swift-base64-Package -enableCodeCoverage YES build test
- name: Codecov
run: bash <(curl -s https://codecov.io/bash) -J 'Base64' -t ${{secrets.CODECOV_TOKEN}}
run: bash <(curl -s https://codecov.io/bash) -t ${{secrets.CODECOV_TOKEN}} -F base64,unittests -f *.coverage.txt

"macOS-Performance-Tests":
runs-on: macOS-latest
steps:
- name: Checkout
uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Build
run: swift build -c release
- name: Run test
run: .build/release/Base64PerformanceTest
3 changes: 3 additions & 0 deletions Package.swift
Expand Up @@ -12,6 +12,9 @@ let package = Package(
],
dependencies: [],
targets: [
.target(
name: "Base64PerformanceTest",
dependencies: ["Base64"]),
.target(
name: "Base64",
dependencies: []),
Expand Down
68 changes: 62 additions & 6 deletions README.md
Expand Up @@ -6,15 +6,71 @@
![macOS](https://img.shields.io/badge/os-macOS-green.svg?style=flat)
![tuxOS](https://img.shields.io/badge/os-tuxOS-green.svg?style=flat)

The goal of this project is to provide an easy to use base64 encode and decode algorithm
without the use of the Foundation framework.
The goal of this project is to provide an easy to use [RFC4648](https://tools.ietf.org/html/rfc4648)
complient base64 encode and decode implentation in pure Swift. Further this implementation
tries to be faster than the [Foundation Base64](https://developer.apple.com/documentation/foundation/nsdata)
implementation.

Right now the implementation is dead simple. No fancy precomputed lookup tables, no fancy
SIMD instructions.

Everything began with [an issue](https://github.com/apple/swift-nio/issues/1265) on [`swift-nio`](https://github.com/apple/swift-nio).

## Status

- [x] support for base64 and base64url
- [x] faster than Foundation
- [ ] decoding can ignore line breaks
- [ ] encoding can insert line breaks
- [ ] 100% test coverage

## Performance

Super [simple performance test](https://github.com/fabianfett/swift-base64/blob/master/Sources/Base64PerformanceTest/main.swift)
to ensure speediness of this implementation. Encoding and decoding 1m times the base64 string:

```
AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==
```

#### macOS

MacBook Pro (15-inch, late 2016 - the first one with the butterfly keyboard).
Quad Core 2,7 GHz Intel Core i7

| | Encoding | Decoding |
|:--|:--|:--|
| Foundation | 2.21s | 2.28s |
| swift-base64 | 1.01s | 1.06s |
| Speedup | 2.18x | 2.14x |

#### linux

Whatevar runs GitHub Actions 😉

| | Encoding | Decoding |
|:--|:--|:--|
| Foundation | 33.64s | 3.49s |
| swift-base64 | 1.07s | 1.27s |
| Speedup | 31.18x | 2.74x |

I have no idea why Foundation base64 encoding is so slow on linux. 🤷‍♂️

## Literature for a faster algorithm

I would really like to speedup this repository further to be way faster than it is today.
Some food for thought of how this could be approached can be found here:

- [Chromium precomputed lookup tables](https://github.com/lemire/fastbase64/blob/master/src/chromiumbase64.c)
- [Wojciech Muła, Daniel Lemire: Faster Base64 Encoding and Decoding using AVX2 Instructions](https://arxiv.org/pdf/1704.00605.pdf).
- [Daniel Lemire's blog - Ridiculously fast base64 encoding and decoding](https://lemire.me/blog/2018/01/17/ridiculously-fast-base64-encoding-and-decoding/)
- [Swift SIMD support](https://github.com/apple/swift-evolution/blob/master/proposals/0229-simd.md)

## Alternatives

### Maybe one day, we can make this really swift.
As of today (2019-12-10) the author is only aware of two alternatives that both offer
only encoding. Only one of those is a real library.

Some literature:
- [SwiftyBase64](https://github.com/drichardson/SwiftyBase64)
- [NIOWebSocket - Base64](https://github.com/apple/swift-nio/blob/master/Sources/NIOWebSocket/Base64.swift)

- [RFC4648](https://tools.ietf.org/html/rfc4648)
- [Ridiculously fast base64 encoding and decoding - Daniel Lemire's blog](https://lemire.me/blog/2018/01/17/ridiculously-fast-base64-encoding-and-decoding/)

0 comments on commit e4d0371

Please sign in to comment.