refactor(perf): expose single latency measurement (#207)
This commit is contained in:
parent
81b6e7c370
commit
cdf7820037
|
@ -51,7 +51,9 @@ _WARNING_: Running the perf tests might take a while.
|
|||
- Logging MUST go to stderr.
|
||||
- Measurement output is printed to stdout as JSON in the form of:
|
||||
```json
|
||||
{"connectionEstablishedSeconds":0.246442851,"uploadSeconds":0.000002077,"downloadSeconds":0.060712241}
|
||||
{"latency": 0.246442851}
|
||||
```
|
||||
Note that the measurement includes the time to (1) establish the
|
||||
connection, (2) upload the bytes and (3) download the bytes.
|
||||
2. In `impl/Makefile` include your implementation in the `all` target.
|
||||
3. Reference implementation in `runner/src/versions.ts`.
|
||||
|
|
|
@ -82,17 +82,14 @@ func main() {
|
|||
if err != nil {
|
||||
log.Fatalf("failed to dial peer: %s", err)
|
||||
}
|
||||
connectionEstablished := time.Since(start)
|
||||
|
||||
upload, download, err := perf.RunPerf(context.Background(), serverInfo.ID, uint64(*uploadBytes), uint64(*downloadBytes))
|
||||
err = perf.RunPerf(context.Background(), serverInfo.ID, uint64(*uploadBytes), uint64(*downloadBytes))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to execute perf: %s", err)
|
||||
}
|
||||
|
||||
jsonB, err := json.Marshal(Result{
|
||||
ConnectionEstablishedSeconds: connectionEstablished.Seconds(),
|
||||
UploadSeconds: upload.Seconds(),
|
||||
DownloadSeconds: download.Seconds(),
|
||||
Latency: time.Since(start).Seconds(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("failed to marshal perf result: %s", err)
|
||||
|
@ -102,9 +99,7 @@ func main() {
|
|||
}
|
||||
|
||||
type Result struct {
|
||||
ConnectionEstablishedSeconds float64 `json:"connectionEstablishedSeconds"`
|
||||
UploadSeconds float64 `json:"uploadSeconds"`
|
||||
DownloadSeconds float64 `json:"downloadSeconds"`
|
||||
Latency float64 `json:"latency"`
|
||||
}
|
||||
|
||||
type simpleReader struct {
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
pool "github.com/libp2p/go-buffer-pool"
|
||||
|
@ -55,10 +54,10 @@ func (ps *PerfService) PerfHandler(s network.Stream) {
|
|||
s.CloseWrite()
|
||||
}
|
||||
|
||||
func (ps *PerfService) RunPerf(ctx context.Context, p peer.ID, bytesToSend uint64, bytesToRecv uint64) (time.Duration, time.Duration, error) {
|
||||
func (ps *PerfService) RunPerf(ctx context.Context, p peer.ID, bytesToSend uint64, bytesToRecv uint64) error {
|
||||
s, err := ps.Host.NewStream(ctx, p, ID)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return err
|
||||
}
|
||||
|
||||
sizeBuf := make([]byte, 8)
|
||||
|
@ -66,28 +65,24 @@ func (ps *PerfService) RunPerf(ctx context.Context, p peer.ID, bytesToSend uint6
|
|||
|
||||
_, err = s.Write(sizeBuf)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return err
|
||||
}
|
||||
|
||||
sendStart := time.Now()
|
||||
if err := sendBytes(s, bytesToSend); err != nil {
|
||||
return 0, 0, err
|
||||
return err
|
||||
}
|
||||
s.CloseWrite()
|
||||
sendDuration := time.Since(sendStart)
|
||||
|
||||
recvStart := time.Now()
|
||||
recvd, err := drainStream(s)
|
||||
if err != nil {
|
||||
return sendDuration, 0, err
|
||||
return err
|
||||
}
|
||||
recvDuration := time.Since(recvStart)
|
||||
|
||||
if recvd != bytesToRecv {
|
||||
return sendDuration, recvDuration, fmt.Errorf("expected to recv %d bytes, got %d", bytesToRecv, recvd)
|
||||
return fmt.Errorf("expected to recv %d bytes, got %d", bytesToRecv, recvd)
|
||||
}
|
||||
|
||||
return sendDuration, recvDuration, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func sendBytes(s io.Writer, bytesToSend uint64) error {
|
||||
|
|
|
@ -69,7 +69,7 @@ func (r *nullReader) Read(b []byte) (int, error) {
|
|||
return int(l), nil
|
||||
}
|
||||
|
||||
func runClient(serverAddr string, uploadBytes, downloadBytes uint64) (time.Duration, time.Duration, error) {
|
||||
func runClient(serverAddr string, uploadBytes, downloadBytes uint64) (time.Duration, error) {
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
|
@ -88,7 +88,7 @@ func runClient(serverAddr string, uploadBytes, downloadBytes uint64) (time.Durat
|
|||
),
|
||||
)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return 0, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/octet-stream")
|
||||
|
@ -97,23 +97,22 @@ func runClient(serverAddr string, uploadBytes, downloadBytes uint64) (time.Durat
|
|||
startTime := time.Now()
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return 0, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return 0, 0, fmt.Errorf("server returned non-OK status: %d %s", resp.StatusCode, resp.Status)
|
||||
return 0, fmt.Errorf("server returned non-OK status: %d %s", resp.StatusCode, resp.Status)
|
||||
}
|
||||
uploadDoneTime := time.Now()
|
||||
defer resp.Body.Close()
|
||||
|
||||
n, err := drainStream(resp.Body)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("error reading response: %w", err)
|
||||
return 0, fmt.Errorf("error reading response: %w", err)
|
||||
}
|
||||
if n != downloadBytes {
|
||||
return 0, 0, fmt.Errorf("expected %d bytes in response, but received %d", downloadBytes, n)
|
||||
return 0, fmt.Errorf("expected %d bytes in response, but received %d", downloadBytes, n)
|
||||
}
|
||||
|
||||
return uploadDoneTime.Sub(startTime), time.Since(uploadDoneTime), nil
|
||||
return time.Since(startTime), nil
|
||||
}
|
||||
|
||||
func generateEphemeralCertificate() (tls.Certificate, error) {
|
||||
|
@ -168,9 +167,7 @@ func generateEphemeralCertificate() (tls.Certificate, error) {
|
|||
}
|
||||
|
||||
type Result struct {
|
||||
ConnectionEstablishedSeconds float64 `json:"connectionEstablishedSeconds"`
|
||||
UploadSeconds float64 `json:"uploadSeconds"`
|
||||
DownloadSeconds float64 `json:"downloadSeconds"`
|
||||
Latency float64 `json:"latency"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@ -217,16 +214,13 @@ func main() {
|
|||
}
|
||||
|
||||
// Run the client and print the results
|
||||
upload, download, err := runClient(*serverAddr, *uploadBytes, *downloadBytes)
|
||||
latency, err := runClient(*serverAddr, *uploadBytes, *downloadBytes)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
jsonB, err := json.Marshal(Result{
|
||||
// TODO: Ideally we would be able to measure the Go std TCP+TLS connection establishment time.
|
||||
ConnectionEstablishedSeconds: 0,
|
||||
UploadSeconds: upload.Seconds(),
|
||||
DownloadSeconds: download.Seconds(),
|
||||
Latency: latency.Seconds(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("failed to marshal perf result: %s", err)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
commitSha := bdfafffc8b7ec786ff41ea245f24920930eec720
|
||||
commitSha := a5cd126c97b6d8d8328141bfa84cc57e74ebc57c
|
||||
|
||||
all: perf
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
commitSha := 84d29b34b19aef161a8583daffb9f63a385a613b
|
||||
commitSha := 3287f079a8faf5e633a85edae2e76bf490ef1e51
|
||||
|
||||
all: perf
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
commitSha := ed14630672b66958d1da52ecbff03004f0c057c0
|
||||
commitSha := 73dbde1519f71aa8d76f4c5fa018860ddcd2a8ea
|
||||
|
||||
all: perf
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue