diff options
author | Daniel Martí <mvdan@mvdan.cc> | 2018-12-31 19:48:21 +0100 |
---|---|---|
committer | Daniel Martí <mvdan@mvdan.cc> | 2019-03-02 20:43:08 +0000 |
commit | e0ff4e6dc013ac18728743a43b6faa812737bdb2 (patch) | |
tree | d467e8f652976395a365caabd1029ce21c06b312 /src/encoding/pem | |
parent | 06c86e0fc3eec6635fce31b8cd6b988087a8f872 (diff) | |
download | go-e0ff4e6dc013ac18728743a43b6faa812737bdb2.tar.gz go-e0ff4e6dc013ac18728743a43b6faa812737bdb2.zip |
encoding/pem: skip whitespace work on most inputs
encoding/base64 already skips \r and \n when decoding, so this package
must only deal with spaces and tabs. Those aren't nearly as common, so
we can add a fast path with bytes.ContainsAny to skip the costly alloc
and filtering code.
name old time/op new time/op delta
Decode-8 279µs ± 0% 259µs ± 1% -7.07% (p=0.002 n=6+6)
name old speed new speed delta
Decode-8 319MB/s ± 0% 343MB/s ± 1% +7.61% (p=0.002 n=6+6)
name old alloc/op new alloc/op delta
Decode-8 164kB ± 0% 74kB ± 0% -54.90% (p=0.002 n=6+6)
name old allocs/op new allocs/op delta
Decode-8 12.0 ± 0% 11.0 ± 0% -8.33% (p=0.002 n=6+6)
Change-Id: Idfca8700c52f46eb70a4a7e0d2db3bf0124e4699
Reviewed-on: https://go-review.googlesource.com/c/155964
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/encoding/pem')
-rw-r--r-- | src/encoding/pem/pem.go | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/src/encoding/pem/pem.go b/src/encoding/pem/pem.go index 35058c306b..a7272da5ad 100644 --- a/src/encoding/pem/pem.go +++ b/src/encoding/pem/pem.go @@ -50,14 +50,22 @@ func getLine(data []byte) (line, rest []byte) { return bytes.TrimRight(data[0:i], " \t"), data[j:] } -// removeWhitespace returns a copy of its input with all spaces, tab and -// newline characters removed. -func removeWhitespace(data []byte) []byte { +// removeSpacesAndTabs returns a copy of its input with all spaces and tabs +// removed, if there were any. Otherwise, the input is returned unchanged. +// +// The base64 decoder already skips newline characters, so we don't need to +// filter them out here. +func removeSpacesAndTabs(data []byte) []byte { + if !bytes.ContainsAny(data, " \t") { + // Fast path; most base64 data within PEM contains newlines, but + // no spaces nor tabs. Skip the extra alloc and work. + return data + } result := make([]byte, len(data)) n := 0 for _, b := range data { - if b == ' ' || b == '\t' || b == '\r' || b == '\n' { + if b == ' ' || b == '\t' { continue } result[n] = b @@ -155,7 +163,7 @@ func Decode(data []byte) (p *Block, rest []byte) { return decodeError(data, rest) } - base64Data := removeWhitespace(rest[:endIndex]) + base64Data := removeSpacesAndTabs(rest[:endIndex]) p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data))) n, err := base64.StdEncoding.Decode(p.Bytes, base64Data) if err != nil { |