Browse Source

improve performance on copy

Darien Raymond 7 years ago
parent
commit
9bc6a5813e
2 changed files with 20 additions and 4 deletions
  1. 7 2
      common/buf/copy.go
  2. 13 2
      common/buf/copy_test.go

+ 7 - 2
common/buf/copy.go

@@ -3,6 +3,7 @@ package buf
 import (
 	"io"
 	"time"
+	"unsafe"
 
 	"v2ray.com/core/common/errors"
 	"v2ray.com/core/common/signal"
@@ -11,6 +12,7 @@ import (
 type errorHandler func(error) error
 type dataHandler func(MultiBuffer)
 
+//go:notinheap
 type copyHandler struct {
 	onReadError  []errorHandler
 	onData       []dataHandler
@@ -119,10 +121,13 @@ func copyInternal(reader Reader, writer Writer, handler *copyHandler) error {
 // Copy dumps all payload from reader to writer or stops when an error occurs. It returns nil when EOF.
 func Copy(reader Reader, writer Writer, options ...CopyOption) error {
 	var handler copyHandler
+	p := uintptr(unsafe.Pointer(&handler))
+	h := (*copyHandler)(unsafe.Pointer(p))
+
 	for _, option := range options {
-		option(&handler)
+		option(h)
 	}
-	err := copyInternal(reader, writer, &handler)
+	err := copyInternal(reader, writer, h)
 	if err != nil && errors.Cause(err) != io.EOF {
 		return err
 	}

+ 13 - 2
common/buf/copy_test.go

@@ -1,7 +1,8 @@
 package buf_test
 
 import (
-	"crypto/rand"
+	"io"
+	"math/rand"
 	"testing"
 
 	"github.com/golang/mock/gomock"
@@ -39,7 +40,7 @@ func TestWriteError(t *testing.T) {
 	mockWriter := mocks.NewWriter(mockCtl)
 	mockWriter.EXPECT().Write(gomock.Any()).Return(0, errors.New("error"))
 
-	err := buf.Copy(buf.NewReader(rand.Reader), buf.NewWriter(mockWriter))
+	err := buf.Copy(buf.NewReader(rand.New(rand.NewSource(0))), buf.NewWriter(mockWriter))
 	if err == nil {
 		t.Fatal("expected error, but nil")
 	}
@@ -52,3 +53,13 @@ func TestWriteError(t *testing.T) {
 		t.Fatal("unexpected error message: ", err.Error())
 	}
 }
+
+func BenchmarkCopy(b *testing.B) {
+	reader := buf.NewReader(io.LimitReader(rand.New(rand.NewSource(0)), 1024*10))
+	writer := buf.Discard
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_ = buf.Copy(reader, writer)
+	}
+}