mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-11-16 05:05:17 +00:00
131 lines
3.5 KiB
Go
131 lines
3.5 KiB
Go
|
package benchmark
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
crand "crypto/rand"
|
||
|
"io"
|
||
|
"net"
|
||
|
"sync"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/libp2p/go-libp2p/core/crypto"
|
||
|
"github.com/libp2p/go-libp2p/core/peer"
|
||
|
"github.com/libp2p/go-libp2p/core/sec"
|
||
|
"github.com/libp2p/go-libp2p/p2p/security/noise"
|
||
|
tls "github.com/libp2p/go-libp2p/p2p/security/tls"
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
)
|
||
|
|
||
|
type Factory func(*testing.B, crypto.PrivKey) sec.SecureTransport
|
||
|
|
||
|
func benchmarkThroughput(b *testing.B, size int, factory Factory) {
|
||
|
privA, pubA, err := crypto.GenerateEd25519Key(crand.Reader)
|
||
|
assert.NoError(b, err)
|
||
|
idA, err := peer.IDFromPublicKey(pubA)
|
||
|
assert.NoError(b, err)
|
||
|
tptA := factory(b, privA)
|
||
|
|
||
|
privB, pubB, err := crypto.GenerateEd25519Key(crand.Reader)
|
||
|
assert.NoError(b, err)
|
||
|
idB, err := peer.IDFromPublicKey(pubB)
|
||
|
assert.NoError(b, err)
|
||
|
tptB := factory(b, privB)
|
||
|
|
||
|
// pipe here serialize the decryption and encryption, we might want both parallelised to reduce context switching impact on the benchmark.
|
||
|
// https://github.com/golang/go/issues/34502 would be ideal for the parallel usecase.
|
||
|
p1, p2 := net.Pipe()
|
||
|
var ready sync.Mutex // wait for completed handshake
|
||
|
var finished sync.Mutex // wait until all data has been received
|
||
|
ready.Lock()
|
||
|
finished.Lock()
|
||
|
go func() {
|
||
|
defer finished.Unlock()
|
||
|
conn, err := tptB.SecureInbound(context.Background(), p2, idA)
|
||
|
assert.NoError(b, err)
|
||
|
ready.Unlock()
|
||
|
|
||
|
_, err = io.Copy(io.Discard, conn)
|
||
|
assert.NoError(b, err)
|
||
|
}()
|
||
|
|
||
|
conn, err := tptA.SecureOutbound(context.Background(), p1, idB)
|
||
|
assert.NoError(b, err)
|
||
|
ready.Lock()
|
||
|
|
||
|
buf := make([]byte, size)
|
||
|
b.SetBytes(int64(len(buf)))
|
||
|
b.ResetTimer()
|
||
|
|
||
|
for i := b.N; i != 0; i-- {
|
||
|
_, err = conn.Write(buf[:])
|
||
|
assert.NoError(b, err)
|
||
|
}
|
||
|
conn.Close()
|
||
|
|
||
|
finished.Lock()
|
||
|
}
|
||
|
func benchmarkHandshakes(b *testing.B, factory Factory) {
|
||
|
privA, pubA, err := crypto.GenerateEd25519Key(crand.Reader)
|
||
|
assert.NoError(b, err)
|
||
|
idA, err := peer.IDFromPublicKey(pubA)
|
||
|
assert.NoError(b, err)
|
||
|
tptA := factory(b, privA)
|
||
|
|
||
|
privB, pubB, err := crypto.GenerateEd25519Key(crand.Reader)
|
||
|
assert.NoError(b, err)
|
||
|
idB, err := peer.IDFromPublicKey(pubB)
|
||
|
assert.NoError(b, err)
|
||
|
tptB := factory(b, privB)
|
||
|
|
||
|
pipes := make(chan net.Conn, 1)
|
||
|
|
||
|
var finished sync.Mutex // wait until all data has been transferred
|
||
|
finished.Lock()
|
||
|
go func() {
|
||
|
defer finished.Unlock()
|
||
|
var throwAway [1]byte
|
||
|
for p := range pipes {
|
||
|
conn, err := tptB.SecureInbound(context.Background(), p, idA)
|
||
|
assert.NoError(b, err)
|
||
|
_, err = conn.Read(throwAway[:]) // read because currently the tls transport handshake when calling Read.
|
||
|
assert.ErrorIs(b, err, io.EOF)
|
||
|
}
|
||
|
}()
|
||
|
b.ResetTimer()
|
||
|
|
||
|
for i := b.N; i != 0; i-- {
|
||
|
p1, p2 := net.Pipe()
|
||
|
pipes <- p2
|
||
|
conn, err := tptA.SecureOutbound(context.Background(), p1, idB)
|
||
|
assert.NoError(b, err)
|
||
|
assert.NoError(b, conn.Close())
|
||
|
}
|
||
|
close(pipes)
|
||
|
|
||
|
finished.Lock()
|
||
|
}
|
||
|
|
||
|
func bench(b *testing.B, factory Factory) {
|
||
|
b.Run("throughput", func(b *testing.B) {
|
||
|
b.Run("32KiB", func(b *testing.B) { benchmarkThroughput(b, 32*1024, factory) })
|
||
|
b.Run("1MiB", func(b *testing.B) { benchmarkThroughput(b, 1024*1024, factory) })
|
||
|
})
|
||
|
b.Run("handshakes", func(b *testing.B) { benchmarkHandshakes(b, factory) })
|
||
|
}
|
||
|
|
||
|
func BenchmarkNoise(b *testing.B) {
|
||
|
bench(b, func(b *testing.B, priv crypto.PrivKey) sec.SecureTransport {
|
||
|
tpt, err := noise.New("", priv, nil)
|
||
|
assert.NoError(b, err)
|
||
|
return tpt
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func BenchmarkTLS(b *testing.B) {
|
||
|
bench(b, func(b *testing.B, priv crypto.PrivKey) sec.SecureTransport {
|
||
|
tpt, err := tls.New("", priv, nil)
|
||
|
assert.NoError(b, err)
|
||
|
return tpt
|
||
|
})
|
||
|
}
|