mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-18 02:48:40 +00:00
net/speedtest: retune to meet iperf on localhost in a VM
- removed some in-flow time calls - increase buffer size to 2MB to overcome syscall cost - move relative time computation from record to report time Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
parent
146f51ce76
commit
f7cb535693
@ -110,11 +110,12 @@ func runSpeedtest(ctx context.Context, args []string) error {
|
||||
w := tabwriter.NewWriter(os.Stdout, 12, 0, 0, ' ', tabwriter.TabIndent)
|
||||
fmt.Println("Results:")
|
||||
fmt.Fprintln(w, "Interval\t\tTransfer\t\tBandwidth\t\t")
|
||||
startTime := results[0].IntervalStart
|
||||
for _, r := range results {
|
||||
if r.Total {
|
||||
fmt.Fprintln(w, "-------------------------------------------------------------------------")
|
||||
}
|
||||
fmt.Fprintf(w, "%.2f-%.2f\tsec\t%.4f\tMBits\t%.4f\tMbits/sec\t\n", r.IntervalStart.Seconds(), r.IntervalEnd.Seconds(), r.MegaBits(), r.MBitsPerSecond())
|
||||
fmt.Fprintf(w, "%.2f-%.2f\tsec\t%.4f\tMBits\t%.4f\tMbits/sec\t\n", r.IntervalStart.Sub(startTime).Seconds(), r.IntervalEnd.Sub(startTime).Seconds(), r.MegaBits(), r.MBitsPerSecond())
|
||||
}
|
||||
w.Flush()
|
||||
return nil
|
||||
|
@ -11,11 +11,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
blockSize = 32000 // size of the block of data to send
|
||||
blockSize = 2 * 1024 * 1024 // size of the block of data to send
|
||||
MinDuration = 5 * time.Second // minimum duration for a test
|
||||
DefaultDuration = MinDuration // default duration for a test
|
||||
MaxDuration = 30 * time.Second // maximum duration for a test
|
||||
version = 1 // value used when comparing client and server versions
|
||||
version = 2 // value used when comparing client and server versions
|
||||
increment = time.Second // increment to display results for, in seconds
|
||||
minInterval = 10 * time.Millisecond // minimum interval length for a result to be included
|
||||
DefaultPort = 20333
|
||||
@ -37,14 +37,14 @@ type configResponse struct {
|
||||
|
||||
// This represents the Result of a speedtest within a specific interval
|
||||
type Result struct {
|
||||
Bytes int // number of bytes sent/received during the interval
|
||||
IntervalStart time.Duration // duration between the start of the interval and the start of the test
|
||||
IntervalEnd time.Duration // duration between the end of the interval and the start of the test
|
||||
Total bool // if true, this result struct represents the entire test, rather than a segment of the test
|
||||
Bytes int // number of bytes sent/received during the interval
|
||||
IntervalStart time.Time // start of the interval
|
||||
IntervalEnd time.Time // end of the interval
|
||||
Total bool // if true, this result struct represents the entire test, rather than a segment of the test
|
||||
}
|
||||
|
||||
func (r Result) MBitsPerSecond() float64 {
|
||||
return r.MegaBits() / (r.IntervalEnd - r.IntervalStart).Seconds()
|
||||
return r.MegaBits() / r.IntervalEnd.Sub(r.IntervalStart).Seconds()
|
||||
}
|
||||
|
||||
func (r Result) MegaBytes() float64 {
|
||||
@ -56,7 +56,7 @@ func (r Result) MegaBits() float64 {
|
||||
}
|
||||
|
||||
func (r Result) Interval() time.Duration {
|
||||
return r.IntervalEnd - r.IntervalStart
|
||||
return r.IntervalEnd.Sub(r.IntervalStart)
|
||||
}
|
||||
|
||||
type Direction int
|
||||
|
@ -81,9 +81,6 @@ func doTest(conn net.Conn, conf config) ([]Result, error) {
|
||||
var currentTime time.Time
|
||||
var results []Result
|
||||
|
||||
startTime := time.Now()
|
||||
lastCalculated := startTime
|
||||
|
||||
if conf.Direction == Download {
|
||||
conn.SetReadDeadline(time.Now().Add(conf.TestDuration).Add(5 * time.Second))
|
||||
} else {
|
||||
@ -94,6 +91,9 @@ func doTest(conn net.Conn, conf config) ([]Result, error) {
|
||||
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
lastCalculated := startTime
|
||||
|
||||
SpeedTestLoop:
|
||||
for {
|
||||
var n int
|
||||
@ -110,48 +110,37 @@ SpeedTestLoop:
|
||||
return nil, fmt.Errorf("unexpected error has occurred: %w", err)
|
||||
}
|
||||
} else {
|
||||
// Need to change the data a little bit, to avoid any compression.
|
||||
for i := range bufferData {
|
||||
bufferData[i]++
|
||||
}
|
||||
n, err = conn.Write(bufferData)
|
||||
if err != nil {
|
||||
// If the write failed, there is most likely something wrong with the connection.
|
||||
return nil, fmt.Errorf("upload failed: %w", err)
|
||||
}
|
||||
}
|
||||
currentTime = time.Now()
|
||||
intervalBytes += n
|
||||
|
||||
currentTime = time.Now()
|
||||
// checks if the current time is more or equal to the lastCalculated time plus the increment
|
||||
if currentTime.After(lastCalculated.Add(increment)) {
|
||||
intervalStart := lastCalculated.Sub(startTime)
|
||||
intervalEnd := currentTime.Sub(startTime)
|
||||
if (intervalEnd - intervalStart) > minInterval {
|
||||
results = append(results, Result{Bytes: intervalBytes, IntervalStart: intervalStart, IntervalEnd: intervalEnd, Total: false})
|
||||
}
|
||||
if currentTime.Sub(lastCalculated) >= increment {
|
||||
results = append(results, Result{Bytes: intervalBytes, IntervalStart: lastCalculated, IntervalEnd: currentTime, Total: false})
|
||||
lastCalculated = currentTime
|
||||
totalBytes += intervalBytes
|
||||
intervalBytes = 0
|
||||
}
|
||||
|
||||
if conf.Direction == Upload && time.Since(startTime) > conf.TestDuration {
|
||||
if conf.Direction == Upload && currentTime.Sub(startTime) > conf.TestDuration {
|
||||
break SpeedTestLoop
|
||||
}
|
||||
}
|
||||
|
||||
// get last segment
|
||||
intervalStart := lastCalculated.Sub(startTime)
|
||||
intervalEnd := currentTime.Sub(startTime)
|
||||
if (intervalEnd - intervalStart) > minInterval {
|
||||
results = append(results, Result{Bytes: intervalBytes, IntervalStart: intervalStart, IntervalEnd: intervalEnd, Total: false})
|
||||
if currentTime.Sub(lastCalculated) > minInterval {
|
||||
results = append(results, Result{Bytes: intervalBytes, IntervalStart: lastCalculated, IntervalEnd: currentTime, Total: false})
|
||||
}
|
||||
|
||||
// get total
|
||||
totalBytes += intervalBytes
|
||||
intervalEnd = currentTime.Sub(startTime)
|
||||
if intervalEnd > minInterval {
|
||||
results = append(results, Result{Bytes: totalBytes, IntervalStart: 0, IntervalEnd: intervalEnd, Total: true})
|
||||
if currentTime.Sub(startTime) > minInterval {
|
||||
results = append(results, Result{Bytes: totalBytes, IntervalStart: startTime, IntervalEnd: currentTime, Total: true})
|
||||
}
|
||||
|
||||
return results, nil
|
||||
|
@ -7,6 +7,7 @@ package speedtest
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDownload(t *testing.T) {
|
||||
@ -23,9 +24,9 @@ func TestDownload(t *testing.T) {
|
||||
type state struct {
|
||||
err error
|
||||
}
|
||||
displayResult := func(t *testing.T, r Result) {
|
||||
displayResult := func(t *testing.T, r Result, start time.Time) {
|
||||
t.Helper()
|
||||
t.Logf("{ Megabytes: %.2f, Start: %.1f, End: %.1f, Total: %t }", r.MegaBytes(), r.IntervalStart.Seconds(), r.IntervalEnd.Seconds(), r.Total)
|
||||
t.Logf("{ Megabytes: %.2f, Start: %.1f, End: %.1f, Total: %t }", r.MegaBytes(), r.IntervalStart.Sub(start).Seconds(), r.IntervalEnd.Sub(start).Seconds(), r.Total)
|
||||
}
|
||||
stateChan := make(chan state, 1)
|
||||
|
||||
@ -49,8 +50,9 @@ func TestDownload(t *testing.T) {
|
||||
t.Fatalf("download results: expected length: %d, actual length: %d", expectedLen, len(results))
|
||||
}
|
||||
|
||||
start := results[0].IntervalStart
|
||||
for _, result := range results {
|
||||
displayResult(t, result)
|
||||
displayResult(t, result, start)
|
||||
}
|
||||
})
|
||||
|
||||
@ -66,8 +68,9 @@ func TestDownload(t *testing.T) {
|
||||
t.Fatalf("upload results: expected length: %d, actual length: %d", expectedLen, len(results))
|
||||
}
|
||||
|
||||
start := results[0].IntervalStart
|
||||
for _, result := range results {
|
||||
displayResult(t, result)
|
||||
displayResult(t, result, start)
|
||||
}
|
||||
})
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user