Procházet zdrojové kódy

improve simple authenticator performance in amd64

v2ray před 9 roky
rodič
revize
f7396aad8c

+ 16 - 4
transport/internet/kcp/crypt.go

@@ -37,14 +37,26 @@ func (this *SimpleAuthenticator) Seal(buffer *alloc.Buffer) {
 	buffer.SliceBack(4)
 	fnvHash.Sum(buffer.Value[:0])
 
-	for i := 4; i < buffer.Len(); i++ {
-		buffer.Value[i] ^= buffer.Value[i-4]
+	len := buffer.Len()
+	xtra := 4 - len%4
+	if xtra != 0 {
+		buffer.Slice(0, len+xtra)
+	}
+	xorfwd(buffer.Value)
+	if xtra != 0 {
+		buffer.Slice(0, len)
 	}
 }
 
 func (this *SimpleAuthenticator) Open(buffer *alloc.Buffer) bool {
-	for i := buffer.Len() - 1; i >= 4; i-- {
-		buffer.Value[i] ^= buffer.Value[i-4]
+	len := buffer.Len()
+	xtra := 4 - len%4
+	if xtra != 0 {
+		buffer.Slice(0, len+xtra)
+	}
+	xorbkd(buffer.Value)
+	if xtra != 0 {
+		buffer.Slice(0, len)
 	}
 
 	fnvHash := fnv.New32a()

+ 16 - 1
transport/internet/kcp/crypt_test.go

@@ -1,6 +1,7 @@
 package kcp_test
 
 import (
+	"crypto/rand"
 	"testing"
 
 	"github.com/v2ray/v2ray-core/common/alloc"
@@ -18,5 +19,19 @@ func TestSimpleAuthenticator(t *testing.T) {
 	auth.Seal(buffer)
 
 	assert.Bool(auth.Open(buffer)).IsTrue()
-	assert.String(buffer.String()).Equals("abcdefg")
+	assert.Bytes(buffer.Value).Equals([]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'})
+}
+
+func BenchmarkSimpleAuthenticator(b *testing.B) {
+	buffer := alloc.NewBuffer().Clear()
+	buffer.Slice(0, 1024)
+	rand.Read(buffer.Value)
+
+	auth := NewSimpleAuthenticator()
+	b.SetBytes(int64(buffer.Len()))
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		auth.Seal(buffer)
+		auth.Open(buffer)
+	}
 }

+ 44 - 0
transport/internet/kcp/xor.amd64.s

@@ -0,0 +1,44 @@
+#include "textflag.h"
+
+// func xorfwd(x []byte)
+TEXT ·xorfwd(SB),NOSPLIT,$0
+  MOVQ x+0(FP), SI  // x[i]
+  MOVL x+8(FP), CX  // x.len
+  MOVQ x+0(FP), DI
+  ADDQ $4, DI       // x[i+4]
+  SUBQ $4, CX
+loop:
+  CMPL CX, $0
+  JE done
+
+  MOVL (SI), AX
+  XORL AX, (DI)
+  ADDQ $4, SI
+  ADDQ $4, DI
+  SUBQ $4, CX
+  JMP loop
+done:        
+  RET
+
+// func xorbkd(x []byte)
+TEXT ·xorbkd(SB),NOSPLIT,$0
+  MOVQ x+0(FP), SI
+  MOVL x+8(FP), CX  // x.len
+  MOVQ x+0(FP), DI
+  ADDQ CX, SI       // x[-8]
+  SUBQ $8, SI
+  ADDQ CX, DI       // x[-4]
+  SUBQ $4, DI
+  SUBQ $4, CX
+loop:
+  CMPL CX, $0
+  JE done
+
+  MOVL (SI), AX
+  XORL AX, (DI)
+  SUBQ $4, SI
+  SUBQ $4, DI
+  SUBQ $4, CX
+  JMP loop
+done:        
+  RET

+ 7 - 0
transport/internet/kcp/xor.go

@@ -0,0 +1,7 @@
+package kcp
+
+// xorfwd performs XOR forwards in words, x[i] ^= x[i-4], i from 0 to len
+func xorfwd(x []byte)
+
+// xorbkd performs XOR backwords in words, x[i] ^= x[i-4], i from len to 0
+func xorbkd(x []byte)

+ 15 - 0
transport/internet/kcp/xor_other.go

@@ -0,0 +1,15 @@
+// +build !amd64
+
+package kcp
+
+func xorfwd(x []byte) {
+	for i := 4; i < len(x); i++ {
+		x[i] ^= x[i-4]
+	}
+}
+
+func xorbkd(x []byte) {
+	for i := len(x) - 1; i >= 0; i-- {
+		x[i] ^= x[i-4]
+	}
+}