crypto/tls, crypto/aes: remove allocations when Writing & Reading

benchmark          old ns/op     new ns/op     delta
BenchmarkTLS-4     8571          7938          -7.39%

benchmark          old MB/s     new MB/s     speedup
BenchmarkTLS-4     119.46       128.98       1.08x

benchmark          old allocs     new allocs     delta
BenchmarkTLS-4     8              0              -100.00%

benchmark          old bytes     new bytes     delta
BenchmarkTLS-4     128           0             -100.00%

On:

func BenchmarkTLS(b *testing.B) {
        b.ReportAllocs()
        b.SetBytes(1024)
        ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                io.Copy(ioutil.Discard, r.Body)
        }))
        defer ts.Close()
        buf := make([]byte, 1024)
        for i := range buf {
                buf[i] = byte(i)
        }
        c, err := tls.Dial("tcp", ts.Listener.Addr().String(), &tls.Config{
                InsecureSkipVerify: true,
        })
        if err != nil {
                b.Fatal(err)
        }
        defer c.Close()
        clen := int64(b.N) * 1024
        if _, err := c.Write([]byte(
            "POST / HTTP/1.1\r\nHost: foo\r\nContent-Length: " +
            fmt.Sprint(clen) + "\r\n\r\n")); err != nil {
                b.Fatal(err)
        }
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
                if _, err := c.Write(buf); err != nil {
                        b.Fatal(err)
                }
        }
}

Change-Id: I206e7e2118b97148f9751b740d8470895634d3f5
Reviewed-on: https://go-review.googlesource.com/16828
Reviewed-by: Adam Langley <agl@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Brad Fitzpatrick 2015-11-12 14:09:03 +00:00
parent 59e7c9bc39
commit 527a98e440

23
conn.go
View File

@ -104,6 +104,7 @@ type halfConn struct {
mac macFunction mac macFunction
seq [8]byte // 64-bit sequence number seq [8]byte // 64-bit sequence number
bfree *block // list of free blocks bfree *block // list of free blocks
additionalData [13]byte // to avoid allocs; interface method args escape
nextCipher interface{} // next encryption state nextCipher interface{} // next encryption state
nextMac macFunction // next MAC algorithm nextMac macFunction // next MAC algorithm
@ -262,14 +263,13 @@ func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert)
nonce := payload[:8] nonce := payload[:8]
payload = payload[8:] payload = payload[8:]
var additionalData [13]byte copy(hc.additionalData[:], hc.seq[:])
copy(additionalData[:], hc.seq[:]) copy(hc.additionalData[8:], b.data[:3])
copy(additionalData[8:], b.data[:3])
n := len(payload) - c.Overhead() n := len(payload) - c.Overhead()
additionalData[11] = byte(n >> 8) hc.additionalData[11] = byte(n >> 8)
additionalData[12] = byte(n) hc.additionalData[12] = byte(n)
var err error var err error
payload, err = c.Open(payload[:0], nonce, payload, additionalData[:]) payload, err = c.Open(payload[:0], nonce, payload, hc.additionalData[:])
if err != nil { if err != nil {
return false, 0, alertBadRecordMAC return false, 0, alertBadRecordMAC
} }
@ -378,13 +378,12 @@ func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
payload := b.data[recordHeaderLen+explicitIVLen:] payload := b.data[recordHeaderLen+explicitIVLen:]
payload = payload[:payloadLen] payload = payload[:payloadLen]
var additionalData [13]byte copy(hc.additionalData[:], hc.seq[:])
copy(additionalData[:], hc.seq[:]) copy(hc.additionalData[8:], b.data[:3])
copy(additionalData[8:], b.data[:3]) hc.additionalData[11] = byte(payloadLen >> 8)
additionalData[11] = byte(payloadLen >> 8) hc.additionalData[12] = byte(payloadLen)
additionalData[12] = byte(payloadLen)
c.Seal(payload[:0], nonce, payload, additionalData[:]) c.Seal(payload[:0], nonce, payload, hc.additionalData[:])
case cbcMode: case cbcMode:
blockSize := c.BlockSize() blockSize := c.BlockSize()
if explicitIVLen > 0 { if explicitIVLen > 0 {