Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(perf): continuosly measure on single conn (iperf-style) #276

Merged
merged 32 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ad823e1
feat(perf): continuosly measure on single conn (iperf-style)
mxinden Aug 24, 2023
b1d7cd5
Use "Max out quic connection and stream data"
mxinden Aug 25, 2023
2c29805
Push results
mxinden Aug 25, 2023
65f4ae6
Add go-libp2p v0.29
mxinden Aug 28, 2023
533f24f
Increase time to run
mxinden Aug 28, 2023
b223d7c
Add quic-go
mxinden Aug 28, 2023
fe93e28
Merge branch 'master' of https://github.com/libp2p/test-plans into pe…
mxinden Sep 4, 2023
a1096e0
Add benchmark results
mxinden Sep 4, 2023
bba3f71
Increase iterations for CI to do longer run
mxinden Sep 4, 2023
7ed527a
perf: update benchmark results
mxinden Sep 4, 2023
eb08da5
Disable Nagle's algorithm on iperf
mxinden Sep 4, 2023
a409e63
perf: update benchmark results
mxinden Sep 4, 2023
f48d729
perf: update benchmark results
mxinden Sep 4, 2023
39603f0
fix(perf/https): call time.Now once
mxinden Sep 15, 2023
fb3785b
Reintroduce latency benchmark
mxinden Sep 15, 2023
027127c
fix(perf/https): log on download and introduce reportingReader
mxinden Sep 15, 2023
73f7e06
fix(perf/go-libp2p): log on download
mxinden Sep 15, 2023
7903f12
feat(perf): introduce download test
mxinden Sep 15, 2023
38daa81
feat(perf/quic-go): update git ref
mxinden Sep 15, 2023
1b75a03
Update benchmark results with --testing data
mxinden Sep 15, 2023
83e891c
Merge branch 'master' of https://github.com/libp2p/test-plans into pe…
mxinden Sep 20, 2023
02d4238
Document changes to output format
mxinden Sep 20, 2023
b0eaec5
Disable js-libp2p for now
mxinden Sep 20, 2023
175597c
Increase iterations, decrease time
mxinden Sep 20, 2023
27d07a6
perf: update benchmark results
mxinden Sep 20, 2023
dac602c
Update TODOs and implement final log for https
mxinden Sep 25, 2023
26820e7
Use uint64 and >=
mxinden Sep 26, 2023
6b05b73
Port changes to all go-libp2p versions
mxinden Oct 19, 2023
822c56c
perf: update benchmark results
mxinden Oct 19, 2023
9b7a12d
Update to latest rust-libp2p
mxinden Oct 25, 2023
2e86c0f
Update to latest master
mxinden Oct 25, 2023
a3d3ca6
fix(perf): remove js-libp2p
mxinden Oct 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions perf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,33 @@ Given you have provisioned your infrastructure, you can now build and run the li
- `--download-bytes` number of bytes to download per stream.
- Output
- Logging MUST go to `stderr`.
- Measurement output is printed to `stdout` as JSON in the form of:
```json
{"latency": 0.246442851}
```
Note that the measurement includes the time to (1) establish the
connection, (2) upload the bytes and (3) download the bytes.
- Measurement output is printed to `stdout` as JSON.
- The output schema is:
``` typescript
interface Data {
type: "intermediary" | "final";
timeSeconds: number;
uploadBytes: number;
downloadBytes: number;
}
```
- Every second the client must print the current progress to stdout. See example below. Note the `type: "intermediary"`.
``` json
{
"type": "intermediary",
"timeSeconds": 1.004957645,
"uploadBytes": 73039872,
"downloadBytes": 0
},
```
- Before terminating the client must print a final summary. See example below. Note the `type: "final"`. Also note that the measurement includes the time to (1) establish the connection, (2) upload the bytes and (3) download the bytes.
``` json
{
"type": "final",
"timeSeconds": 60.127230659,
"uploadBytes": 4382392320,
"downloadBytes": 0
}
```
mxinden marked this conversation as resolved.
Show resolved Hide resolved
2. For a new implementation, in [`impl/Makefile` include your implementation in the `all` target.](./impl/Makefile#L7)
3. For a new version, reference version in [`runner/src/versions.ts`](./runner/src/versions.ts#L7-L43).
10 changes: 8 additions & 2 deletions perf/impl/go-libp2p/v0.29/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ func main() {
}

jsonB, err := json.Marshal(Result{
Latency: time.Since(start).Seconds(),
TimeSeconds: time.Since(start).Seconds(),
UploadBytes: uint(*uploadBytes),
DownloadBytes: uint(*downloadBytes),
Type: "final",
})
if err != nil {
log.Fatalf("failed to marshal perf result: %s", err)
Expand All @@ -99,7 +102,10 @@ func main() {
}

type Result struct {
Latency float64 `json:"latency"`
Type string `json:"type"`
TimeSeconds float64 `json:"timeSeconds"`
UploadBytes uint `json:"uploadBytes"`
mxinden marked this conversation as resolved.
Show resolved Hide resolved
DownloadBytes uint `json:"downloadBytes"`
}

type simpleReader struct {
Expand Down
57 changes: 56 additions & 1 deletion perf/impl/go-libp2p/v0.29/perf.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package main
import (
"context"
"encoding/binary"
"encoding/json"
"fmt"
"io"
"time"

logging "github.com/ipfs/go-log/v2"
pool "github.com/libp2p/go-buffer-pool"
Expand Down Expand Up @@ -89,7 +91,26 @@ func sendBytes(s io.Writer, bytesToSend uint64) error {
buf := pool.Get(blockSize)
defer pool.Put(buf)

lastReportTime := time.Now()
lastReportWrite := 0

for bytesToSend > 0 {
now := time.Now()
if now.Sub(lastReportTime) > time.Second {
mxinden marked this conversation as resolved.
Show resolved Hide resolved
jsonB, err := json.Marshal(Result{
TimeSeconds: now.Sub(lastReportTime).Seconds(),
UploadBytes: uint(lastReportWrite),
Type: "intermediary",
})
if err != nil {
log.Fatalf("failed to marshal perf result: %s", err)
}
fmt.Println(string(jsonB))

lastReportTime = now
lastReportWrite = 0
}

toSend := buf
if bytesToSend < blockSize {
toSend = buf[:bytesToSend]
Expand All @@ -100,15 +121,49 @@ func sendBytes(s io.Writer, bytesToSend uint64) error {
return err
}
bytesToSend -= uint64(n)
lastReportWrite += n
}
return nil
}

func drainStream(s io.Reader) (uint64, error) {
var recvd int64
recvd, err := io.Copy(io.Discard, s)
recvd, err := io.Copy(io.Discard, & reportingReader { orig: s, LastReportTime: time.Now() })
mxinden marked this conversation as resolved.
Show resolved Hide resolved
if err != nil && err != io.EOF {
return uint64(recvd), err
}
return uint64(recvd), nil
}

type reportingReader struct {
orig io.Reader
LastReportTime time.Time
lastReportRead uint64
}

var _ io.Reader = &reportingReader{}

func (r *reportingReader) Read(b []byte) (int, error) {
n, err := r.orig.Read(b)
r.lastReportRead += uint64(n)

now := time.Now()
if now.Sub(r.LastReportTime) > time.Second {
mxinden marked this conversation as resolved.
Show resolved Hide resolved
result := Result{
TimeSeconds: now.Sub(r.LastReportTime).Seconds(),
Type: "intermediary",
DownloadBytes: uint(r.lastReportRead),
}

jsonB, err := json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal perf result: %s", err)
}
fmt.Println(string(jsonB))

r.LastReportTime = now
r.lastReportRead = 0
}

return n, err
}
97 changes: 73 additions & 24 deletions perf/impl/https/v0.1/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,6 @@ func handleRequest(w http.ResponseWriter, r *http.Request) {
}
}

type nullReader struct {
N uint64
read uint64
}

var _ io.Reader = &nullReader{}

func (r *nullReader) Read(b []byte) (int, error) {
remaining := r.N - r.read
l := uint64(len(b))
if uint64(len(b)) > remaining {
l = remaining
}
r.read += l
if r.read == r.N {
return int(l), io.EOF
}
return int(l), nil
}

func runClient(serverAddr string, uploadBytes, downloadBytes uint64) (time.Duration, error) {
client := &http.Client{
Transport: &http.Transport{
Expand All @@ -84,7 +64,7 @@ func runClient(serverAddr string, uploadBytes, downloadBytes uint64) (time.Durat
fmt.Sprintf("https://%s/", serverAddr),
io.MultiReader(
bytes.NewReader(b),
&nullReader{N: uploadBytes},
&reportingReader { orig: &nullReader{ N: uploadBytes }, LastReportTime: time.Now(), isUpload: true },
),
)
if err != nil {
Expand Down Expand Up @@ -167,7 +147,10 @@ func generateEphemeralCertificate() (tls.Certificate, error) {
}

type Result struct {
Latency float64 `json:"latency"`
Type string `json:"type"`
TimeSeconds float64 `json:"timeSeconds"`
UploadBytes uint `json:"uploadBytes"`
DownloadBytes uint `json:"downloadBytes"`
}

func main() {
Expand Down Expand Up @@ -220,7 +203,10 @@ func main() {
}

jsonB, err := json.Marshal(Result{
Latency: latency.Seconds(),
TimeSeconds: latency.Seconds(),
UploadBytes: uint(*uploadBytes),
DownloadBytes: uint(*downloadBytes),
Type: "final",
})
if err != nil {
log.Fatalf("failed to marshal perf result: %s", err)
Expand Down Expand Up @@ -249,9 +235,72 @@ func sendBytes(s io.Writer, bytesToSend uint64) error {

func drainStream(s io.Reader) (uint64, error) {
var recvd int64
recvd, err := io.Copy(io.Discard, s)
recvd, err := io.Copy(io.Discard, & reportingReader { orig: s, LastReportTime: time.Now(), isUpload: false })
if err != nil && err != io.EOF {
return uint64(recvd), err
}
return uint64(recvd), nil
}

type reportingReader struct {
orig io.Reader
LastReportTime time.Time
lastReportRead uint64
isUpload bool
}

var _ io.Reader = &reportingReader{}

func (r *reportingReader) Read(b []byte) (int, error) {
n, err := r.orig.Read(b)
r.lastReportRead += uint64(n)

now := time.Now()
if now.Sub(r.LastReportTime) > time.Second {
// This section is analogous to your Read implementation
result := Result{
TimeSeconds: now.Sub(r.LastReportTime).Seconds(),
Type: "intermediary",
}
if r.isUpload {
result.UploadBytes = uint(r.lastReportRead)
} else {
result.DownloadBytes = uint(r.lastReportRead)
}

jsonB, err := json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal perf result: %s", err)
}
fmt.Println(string(jsonB))

r.LastReportTime = now
r.lastReportRead = 0
}

return n, err
}

type nullReader struct {
N uint64
read uint64
LastReportTime time.Time
lastReportRead uint64
}

var _ io.Reader = &nullReader{}

func (r *nullReader) Read(b []byte) (int, error) {
remaining := r.N - r.read
l := uint64(len(b))
if uint64(len(b)) > remaining {
l = remaining
}
r.read += l

if r.read == r.N {
return int(l), io.EOF
}

return int(l), nil
}
5 changes: 3 additions & 2 deletions perf/impl/quic-go/v0.34/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
commitSha := a5cd126c97b6d8d8328141bfa84cc57e74ebc57c
commitSha := 3a12ea9207e40de20533b0a6aa2e40e3727aa796

all: perf

Expand All @@ -10,7 +10,8 @@ perf-${commitSha}: perf-${commitSha}.zip
unzip -o perf-${commitSha}.zip

perf-${commitSha}.zip:
wget -O $@ "https://github.com/quic-go/perf/archive/${commitSha}.zip"
# TODO: revert
wget -O $@ "https://github.com/mxinden/perf/archive/${commitSha}.zip"

clean:
rm perf-*.zip
Expand Down
5 changes: 3 additions & 2 deletions perf/impl/rust-libp2p/v0.52/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
commitSha := e8759c85c278006f5fc94e823c2a3620abaaf697
commitSha := 0f99dd444f2b9b8e903c5be2db5b420086114c16

all: perf

Expand All @@ -12,7 +12,8 @@ rust-libp2p-${commitSha}: rust-libp2p-${commitSha}.zip
unzip -o rust-libp2p-${commitSha}.zip

rust-libp2p-${commitSha}.zip:
wget -O $@ "https://github.com/libp2p/rust-libp2p/archive/${commitSha}.zip"
# TODO revert
wget -O $@ "https://github.com/mxinden/rust-libp2p/archive/${commitSha}.zip"

clean:
rm rust-libp2p-*.zip
Expand Down
Loading