Skip to content

Commit

Permalink
aws/signer/v4: Optimize stripExcessSpaces
Browse files Browse the repository at this point in the history
Optimizes stripExcessSpaces by using a hand rolled trim space avoiding the overhead of strings.TrimSpace and ensuring we only do a single pass on the string for both search and copy when stripping multiple spaces.

This improves the performance on the test machine from 2378 ns/op to 1528 ns/op while keeping allocs the same.
  • Loading branch information
stevenh authored and jasdel committed Jul 25, 2017
1 parent 40f45e3 commit 66fbc91
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 30 deletions.
58 changes: 28 additions & 30 deletions aws/signer/v4/v4.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
package v4

import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
Expand Down Expand Up @@ -717,47 +716,46 @@ func makeSha256Reader(reader io.ReadSeeker) []byte {
return hash.Sum(nil)
}

const doubleSpaces = " "

var doubleSpaceBytes = []byte(doubleSpaces)
const doubleSpace = " "

// stripExcessSpaces will rewrite the passed in slice's string values to not
// contain muliple side-by-side spaces.
func stripExcessSpaces(vals []string) {
var j, k, l, m, spaces int
for i, str := range vals {
// Trim leading and trailing spaces
trimmed := strings.TrimSpace(str)
// Trim trailing spaces
for j = len(str) - 1; j >= 0 && str[j] == ' '; j-- {
}

idx := strings.Index(trimmed, doubleSpaces)
if idx < 0 {
vals[i] = trimmed
continue
// Trim leading spaces
for k = 0; k < j && str[k] == ' '; k++ {
}
str = str[k : j+1]

buf := []byte(trimmed)
for idx > -1 {
idx++ // Start on the second space
// Strip multiple spaces.
j = strings.Index(str, doubleSpace)
if j < 0 {
vals[i] = str
continue
}

stripped := false
for j := idx; j < len(buf); j++ {
if buf[j] != ' ' {
buf = append(buf[:idx], buf[j:]...)
stripped = true
break
buf := []byte(str)
for k, m, l = j, j, len(buf); k < l; k++ {
if buf[k] == ' ' {
if spaces == 0 {
// First space.
buf[m] = buf[k]
m++
}
}
if !stripped {
break
}

// Find next double space
origIdx := idx
idx = bytes.Index(buf[idx:], doubleSpaceBytes)
if idx > 0 {
idx += origIdx
spaces++
} else {
// End of multiple spaces.
spaces = 0
buf[m] = buf[k]
m++
}
}

vals[i] = string(buf)
vals[i] = string(buf[:m])
}
}
4 changes: 4 additions & 0 deletions aws/signer/v4/v4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import (

func TestStripExcessHeaders(t *testing.T) {
vals := []string{
"",
"123",
"1 2 3",
"1 2 3 ",
" 1 2 3",
"1 2 3",
"1 23",
Expand All @@ -35,10 +37,12 @@ func TestStripExcessHeaders(t *testing.T) {
}

expected := []string{
"",
"123",
"1 2 3",
"1 2 3",
"1 2 3",
"1 2 3",
"1 23",
"1 2 3",
"1 2",
Expand Down

0 comments on commit 66fbc91

Please sign in to comment.