Jelajahi Sumber

Add statistics in conn testing

Occasional error is observed when we execute long test
Print time and memory for better troubleshooting in the future

Co-authored-by: Jebbs <[email protected]>
yuhan6665 3 tahun lalu
induk
melakukan
dd9da23a59
3 mengubah file dengan 179 tambahan dan 1 penghapusan
  1. 100 0
      common/units/bytesize.go
  2. 66 0
      common/units/bytesize_test.go
  3. 13 1
      testing/scenarios/common.go

+ 100 - 0
common/units/bytesize.go

@@ -0,0 +1,100 @@
+package units
+
+import (
+	"errors"
+	"strconv"
+	"strings"
+	"unicode"
+)
+
+var (
+	errInvalidSize = errors.New("invalid size")
+	errInvalidUnit = errors.New("invalid or unsupported unit")
+)
+
+// ByteSize is the size of bytes
+type ByteSize uint64
+
+const (
+	_ = iota
+	// KB = 1KB
+	KB ByteSize = 1 << (10 * iota)
+	// MB = 1MB
+	MB
+	// GB = 1GB
+	GB
+	// TB = 1TB
+	TB
+	// PB = 1PB
+	PB
+	// EB = 1EB
+	EB
+)
+
+func (b ByteSize) String() string {
+	unit := ""
+	value := float64(0)
+	switch {
+	case b == 0:
+		return "0"
+	case b < KB:
+		unit = "B"
+		value = float64(b)
+	case b < MB:
+		unit = "KB"
+		value = float64(b) / float64(KB)
+	case b < GB:
+		unit = "MB"
+		value = float64(b) / float64(MB)
+	case b < TB:
+		unit = "GB"
+		value = float64(b) / float64(GB)
+	case b < PB:
+		unit = "TB"
+		value = float64(b) / float64(TB)
+	case b < EB:
+		unit = "PB"
+		value = float64(b) / float64(PB)
+	default:
+		unit = "EB"
+		value = float64(b) / float64(EB)
+	}
+	result := strconv.FormatFloat(value, 'f', 2, 64)
+	result = strings.TrimSuffix(result, ".0")
+	return result + unit
+}
+
+// Parse parses ByteSize from string
+func (b *ByteSize) Parse(s string) error {
+	s = strings.TrimSpace(s)
+	s = strings.ToUpper(s)
+	i := strings.IndexFunc(s, unicode.IsLetter)
+	if i == -1 {
+		return errInvalidUnit
+	}
+
+	bytesString, multiple := s[:i], s[i:]
+	bytes, err := strconv.ParseFloat(bytesString, 64)
+	if err != nil || bytes <= 0 {
+		return errInvalidSize
+	}
+	switch multiple {
+	case "B":
+		*b = ByteSize(bytes)
+	case "K", "KB", "KIB":
+		*b = ByteSize(bytes * float64(KB))
+	case "M", "MB", "MIB":
+		*b = ByteSize(bytes * float64(MB))
+	case "G", "GB", "GIB":
+		*b = ByteSize(bytes * float64(GB))
+	case "T", "TB", "TIB":
+		*b = ByteSize(bytes * float64(TB))
+	case "P", "PB", "PIB":
+		*b = ByteSize(bytes * float64(PB))
+	case "E", "EB", "EIB":
+		*b = ByteSize(bytes * float64(EB))
+	default:
+		return errInvalidUnit
+	}
+	return nil
+}

+ 66 - 0
common/units/bytesize_test.go

@@ -0,0 +1,66 @@
+package units_test
+
+import (
+	"testing"
+
+	"github.com/xtls/xray-core/common/units"
+)
+
+func TestByteSizes(t *testing.T) {
+	size := units.ByteSize(0)
+	assertSizeString(t, size, "0")
+	size++
+	assertSizeValue(t,
+		assertSizeString(t, size, "1.00B"),
+		size,
+	)
+	size <<= 10
+	assertSizeValue(t,
+		assertSizeString(t, size, "1.00KB"),
+		size,
+	)
+	size <<= 10
+	assertSizeValue(t,
+		assertSizeString(t, size, "1.00MB"),
+		size,
+	)
+	size <<= 10
+	assertSizeValue(t,
+		assertSizeString(t, size, "1.00GB"),
+		size,
+	)
+	size <<= 10
+	assertSizeValue(t,
+		assertSizeString(t, size, "1.00TB"),
+		size,
+	)
+	size <<= 10
+	assertSizeValue(t,
+		assertSizeString(t, size, "1.00PB"),
+		size,
+	)
+	size <<= 10
+	assertSizeValue(t,
+		assertSizeString(t, size, "1.00EB"),
+		size,
+	)
+}
+
+func assertSizeValue(t *testing.T, size string, expected units.ByteSize) {
+	actual := units.ByteSize(0)
+	err := actual.Parse(size)
+	if err != nil {
+		t.Error(err)
+	}
+	if actual != expected {
+		t.Errorf("expect %s, but got %s", expected, actual)
+	}
+}
+
+func assertSizeString(t *testing.T, size units.ByteSize, expected string) string {
+	actual := size.String()
+	if actual != expected {
+		t.Errorf("expect %s, but got %s", expected, actual)
+	}
+	return expected
+}

+ 13 - 1
testing/scenarios/common.go

@@ -23,6 +23,7 @@ import (
 	"github.com/xtls/xray-core/common/net"
 	"github.com/xtls/xray-core/common/retry"
 	"github.com/xtls/xray-core/common/serial"
+	"github.com/xtls/xray-core/common/units"
 	core "github.com/xtls/xray-core/core"
 )
 
@@ -198,7 +199,18 @@ func testUDPConn(port net.Port, payloadSize int, timeout time.Duration) func() e
 }
 
 func testTCPConn2(conn net.Conn, payloadSize int, timeout time.Duration) func() error {
-	return func() error {
+	return func() (err1 error) {
+		start := time.Now()
+		defer func() {
+			var m runtime.MemStats
+			runtime.ReadMemStats(&m)
+			// For info on each, see: https://golang.org/pkg/runtime/#MemStats
+			fmt.Println("testConn finishes:", time.Since(start).Milliseconds(), "ms\t",
+				err1, "\tAlloc =", units.ByteSize(m.Alloc).String(),
+				"\tTotalAlloc =", units.ByteSize(m.TotalAlloc).String(),
+				"\tSys =", units.ByteSize(m.Sys).String(),
+				"\tNumGC =", m.NumGC)
+		}()
 		payload := make([]byte, payloadSize)
 		common.Must2(rand.Read(payload))