diff --git a/.github/workflows/perf.yml b/.github/workflows/perf.yml new file mode 100644 index 000000000..9c0423502 --- /dev/null +++ b/.github/workflows/perf.yml @@ -0,0 +1,101 @@ +name: libp2p perf test + +# How to configure a repository for running this workflow: +# 1. Configure auth for the AWS provider as per https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication-and-configuration +# 2. Run 'terraform init' and 'terraform apply' in 'perf/terraform/configs/remote' to create the resources needed for this workflow +# 3. Go to https://console.aws.amazon.com/iamv2/home?#/users/details/perf?section=security_credentials +# 4. Click 'Create access key' to get the access key ID and secret access key +# 5. Go to https://github.com/libp2p/test-plans/settings/secrets/actions +# 6. Click 'New repository secret', set the name to 'PERF_AWS_SECRET_ACCESS_KEY', and paste the secret access key from step 5 +# 7. Go to https://github.com/libp2p/test-plans/settings/variables/actions +# 8. Click 'New repository variable', set the name to 'PERF_AWS_ACCESS_KEY_ID', and paste the access key ID from step 5 + +on: + workflow_dispatch: + inputs: + push: + description: 'Push the benchmark results to the repository' + required: false + default: 'true' + +jobs: + perf: + name: Perf + runs-on: ubuntu-latest + timeout-minutes: 40 + defaults: + run: + shell: bash + working-directory: perf + env: + AWS_ACCESS_KEY_ID: ${{ vars.PERF_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.PERF_AWS_SECRET_ACCESS_KEY }} + TF_IN_AUTOMATION: 1 + TF_INPUT: 0 + steps: + - name: Checkout test-plans + uses: actions/checkout@v3 + with: + repository: ${{ github.repository }} + ref: ${{ github.ref }} + - id: ssh + name: Generate SSH key + run: | + make ssh-keygen + echo "key<> $GITHUB_OUTPUT + while read -r line; do + echo "::add-mask::$line" + echo "$line" >> $GITHUB_OUTPUT + done < terraform/modules/short_lived/files/perf + echo "EOF" >> $GITHUB_OUTPUT + - name: Configure SSH + uses: webfactory/ssh-agent@d4b9b8ff72958532804b70bbe600ad43b36d5f2e # v0.8.0 + with: + ssh-private-key: ${{ steps.ssh.outputs.key }} + - name: Configure git + run: | + git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com>" + git config --global user.name "${GITHUB_ACTOR}" + - name: Configure terraform + uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 # v2.0.3 + - name: Init terraform + id: init + run: terraform init + working-directory: perf/terraform/configs/local + - name: Apply terraform + run: terraform apply -auto-approve + working-directory: perf/terraform/configs/local + - id: server + name: Retrieve server's IP + run: terraform output -raw server_ip + working-directory: perf/terraform/configs/local + - id: client + name: Retrieve client's IP + run: terraform output -raw client_ip + working-directory: perf/terraform/configs/local + - name: Download dependencies + run: npm ci + working-directory: perf/runner + - name: Run tests + env: + SERVER_IP: ${{ steps.server.outputs.stdout }} + CLIENT_IP: ${{ steps.client.outputs.stdout }} + run: npm run start -- --client-public-ip $CLIENT_IP --server-public-ip $SERVER_IP + working-directory: perf/runner + - name: Push + if: github.event.inputs.push == 'true' + run: | + git add benchmark-results.json + git commit -m "perf: update benchmark results" + git push + working-directory: perf/runner + - name: Archive + if: github.event.intputs.push == 'false' + uses: actions/upload-artifact@v2 + with: + name: benchmark-results + path: perf/runner/benchmark-results.json + - name: Destroy terraform + if: always() && steps.init.outputs.exitcode == 0 + run: terraform destroy -auto-approve + working-directory: perf/terraform/configs/local diff --git a/perf/Makefile b/perf/Makefile new file mode 100644 index 000000000..1d826b01c --- /dev/null +++ b/perf/Makefile @@ -0,0 +1,5 @@ +ssh-keygen: + ssh-keygen -t ed25519 -f ./terraform/modules/short_lived/files/perf -N '' + +ssh-add: + ssh-add ./terraform/modules/short_lived/files/perf diff --git a/perf/README.md b/perf/README.md new file mode 100644 index 000000000..112f7c142 --- /dev/null +++ b/perf/README.md @@ -0,0 +1,57 @@ +# libp2p performance benchmarking + +This project includes the following components: + +- `terraform/`: a Terraform scripts to provision infrastructure +- `impl/`: implementations of the [libp2p perf protocol](https://github.com/libp2p/specs/blob/master/perf/perf.md) running on top of e.g. go-libp2p, rust-libp2p or Go's std-library https stack +- `runner/`: a set of scripts building and running the above implementations on the above infrastructure, reporting the results in `benchmark-results.json` + +Benchmark results can be visualized with https://observablehq.com/@mxinden-workspace/libp2p-performance-dashboard. + +## Provision infrastructure + +### Bootstrap + +1. Save your public SSH key as the file `./terraform/modules/short_lived/files/perf.pub`; or generate a new key pair with `make ssh-keygen` and add it to your SSH agent with `make ssh-add`. +2. `cd terraform/configs/local` +3. `terraform init` +4. `terraform apply` +5. `CLIENT_IP=$(terraform output -raw client_ip)` +6. `SERVER_IP=$(terraform output -raw server_ip)` + +## Build and run implementations + +_WARNING_: Running the perf tests might take a while. + +1. `cd runner` +2. `npm ci` +3. `npm run start -- --client-public-ip $CLIENT_IP --server-public-ip $SERVER_IP` + +## Deprovision infrastructure + +1. `cd terraform/configs/local` +2. `terraform destroy` + +## Adding a new implementation + +1. Add implementation to `impl/`. + - Create a folder `impl//`. + - In that folder include a `Makefile` that builds an executable and stores it next to the `Makefile` under the name `perf`. + - Requirements for the executable: + - Running as a libp2p-perf server + - Command line flags + - `--run-server` + - Running as a libp2p-perf client + - Input via command line + - `--server-ip-address` + - `--transport` (see `runner/versions.ts` for possible variants) + - `--upload-bytes` number of bytes to upload per stream. + - `--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 + {"connectionEstablishedSeconds":0.246442851,"uploadSeconds":0.000002077,"downloadSeconds":0.060712241} + ``` +2. In `impl/Makefile` include your implementation in the `all` target. +3. Reference implementation in `runner/src/versions.ts`. diff --git a/perf/impl/Makefile b/perf/impl/Makefile new file mode 100644 index 000000000..29e9ea363 --- /dev/null +++ b/perf/impl/Makefile @@ -0,0 +1,24 @@ +GO_SUBDIRS := $(wildcard go-libp2p/*/.) +RUST_SUBDIRS := $(wildcard rust-libp2p/*/.) +RUST_QUINN_SUBDIRS := $(wildcard rust-libp2p-quinn/*/.) +HTTPS_SUBDIRS := $(wildcard https/*/.) +QUIC_GO_SUBDIRS := $(wildcard quic-go/*/.) + +all: $(RUST_SUBDIRS) $(RUST_QUINN_SUBDIRS) $(GO_SUBDIRS) $(HTTPS_SUBDIRS) $(QUIC_GO_SUBDIRS) +$(RUST_SUBDIRS): + $(MAKE) -C $@ +$(RUST_QUINN_SUBDIRS): + $(MAKE) -C $@ +$(GO_SUBDIRS): + $(MAKE) -C $@ +$(HTTPS_SUBDIRS): + $(MAKE) -C $@ +$(QUIC_GO_SUBDIRS): + $(MAKE) -C $@ + +clean: $(RUST_SUBDIRS:%=%clean) $(RUST_QUINN_SUBDIRS:%=%clean) $(GO_SUBDIRS:%=%clean) $(HTTPS_SUBDIRS:%=%clean) $(QUIC_GO_SUBDIRS:%=%clean) + +%clean: + $(MAKE) -C $* clean + +.PHONY: $(RUST_SUBDIRS) $(RUST_QUINN_SUBDIRS) $(GO_SUBDIRS) $(HTTPS_SUBDIRS) $(QUIC_GO_SUBDIRS) all clean diff --git a/perf/impl/go-libp2p/.gitignore b/perf/impl/go-libp2p/.gitignore new file mode 100644 index 000000000..6652a25c1 --- /dev/null +++ b/perf/impl/go-libp2p/.gitignore @@ -0,0 +1,4 @@ +go-libp2p-*.zip +go-libp2p-* +go-libp2p-*/* +image.json diff --git a/perf/impl/go-libp2p/v0.27/.gitignore b/perf/impl/go-libp2p/v0.27/.gitignore new file mode 100644 index 000000000..d06b4219a --- /dev/null +++ b/perf/impl/go-libp2p/v0.27/.gitignore @@ -0,0 +1,3 @@ +perf +.cache +v0.27 \ No newline at end of file diff --git a/perf/impl/go-libp2p/v0.27/Dockerfile b/perf/impl/go-libp2p/v0.27/Dockerfile new file mode 100644 index 000000000..5bb5b5aae --- /dev/null +++ b/perf/impl/go-libp2p/v0.27/Dockerfile @@ -0,0 +1,14 @@ +# Build Go Binary +FROM golang:1.20-alpine AS builder + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download +COPY *.go ./ +RUN go build -o perf . + +FROM alpine + +COPY --from=builder /app/perf /app/perf + +ENTRYPOINT [ "/app/perf" ] diff --git a/perf/impl/go-libp2p/v0.27/Makefile b/perf/impl/go-libp2p/v0.27/Makefile new file mode 100644 index 000000000..061ec78ef --- /dev/null +++ b/perf/impl/go-libp2p/v0.27/Makefile @@ -0,0 +1,13 @@ +GO_FILES := $(wildcard *.go) + +all: perf + +perf: $(GO_FILES) + docker run --rm --user "$(shell id -u):$(shell id -g)" -v "$(shell pwd)":/usr/src/myapp -w /usr/src/myapp -e GOCACHE=/usr/src/myapp/.cache golang:1.20 go build -o perf . + +clean: + rm perf + rm .cache + rm v0.27 + +.PHONY: all clean diff --git a/perf/impl/go-libp2p/v0.27/go.mod b/perf/impl/go-libp2p/v0.27/go.mod new file mode 100644 index 000000000..1ddbb04de --- /dev/null +++ b/perf/impl/go-libp2p/v0.27/go.mod @@ -0,0 +1,98 @@ +module github.com/libp2p/test-plans/perf/go/v0.27/v2 + +go 1.19 + +require ( + github.com/ipfs/go-log/v2 v2.5.1 + github.com/libp2p/go-buffer-pool v0.1.0 + github.com/libp2p/go-libp2p v0.27.0 + github.com/multiformats/go-multiaddr v0.9.0 + github.com/stretchr/testify v1.8.2 +) + +require ( + github.com/benbjohnson/clock v1.3.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/containerd/cgroups v1.1.0 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/elastic/gosigar v0.14.2 // indirect + github.com/flynn/noise v1.0.0 // indirect + github.com/francoispqt/gojay v1.2.13 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/gopacket v1.1.19 // indirect + github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b // indirect + github.com/huin/goupnp v1.1.0 // indirect + github.com/ipfs/go-cid v0.4.1 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect + github.com/klauspost/compress v1.16.4 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/koron/go-ssdp v0.0.4 // indirect + github.com/libp2p/go-cidranger v1.1.0 // indirect + github.com/libp2p/go-flow-metrics v0.1.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect + github.com/libp2p/go-msgio v0.3.0 // indirect + github.com/libp2p/go-nat v0.1.0 // indirect + github.com/libp2p/go-netroute v0.2.1 // indirect + github.com/libp2p/go-reuseport v0.2.0 // indirect + github.com/libp2p/go-yamux/v4 v4.0.0 // indirect + github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect + github.com/mattn/go-isatty v0.0.18 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/miekg/dns v1.1.53 // indirect + github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect + github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect + github.com/minio/sha256-simd v1.0.0 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect + github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.8.1 // indirect + github.com/multiformats/go-multihash v0.2.1 // indirect + github.com/multiformats/go-multistream v0.4.1 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect + github.com/onsi/ginkgo/v2 v2.9.2 // indirect + github.com/opencontainers/runtime-spec v1.0.2 // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/quic-go/qpack v0.4.0 // indirect + github.com/quic-go/qtls-go1-19 v0.3.2 // indirect + github.com/quic-go/qtls-go1-20 v0.2.2 // indirect + github.com/quic-go/quic-go v0.33.0 // indirect + github.com/quic-go/webtransport-go v0.5.2 // indirect + github.com/raulk/go-watchdog v1.3.0 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/dig v1.16.1 // indirect + go.uber.org/fx v1.19.2 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/tools v0.7.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + lukechampine.com/blake3 v1.1.7 // indirect + nhooyr.io/websocket v1.8.7 // indirect +) diff --git a/perf/impl/go-libp2p/v0.27/go.sum b/perf/impl/go-libp2p/v0.27/go.sum new file mode 100644 index 000000000..6709fc64f --- /dev/null +++ b/perf/impl/go-libp2p/v0.27/go.sum @@ -0,0 +1,506 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= +github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= +github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= +github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= +github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= +github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b h1:Qcx5LM0fSiks9uCyFZwDBUasd3lxd1RM0GYpL+Li5o4= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= +github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= +github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= +github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= +github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= +github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU= +github.com/klauspost/compress v1.16.4/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= +github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= +github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= +github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= +github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= +github.com/libp2p/go-libp2p v0.27.0 h1:QbhrTuB0ln9j9op6yAOR0o+cx/qa9NyNZ5ov0Tql8ZU= +github.com/libp2p/go-libp2p v0.27.0/go.mod h1:FAvvfQa/YOShUYdiSS03IR9OXzkcJXwcNA2FUCh9ImE= +github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= +github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= +github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= +github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= +github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= +github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= +github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= +github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560= +github.com/libp2p/go-reuseport v0.2.0/go.mod h1:bvVho6eLMm6Bz5hmU0LYN3ixd3nPPvtIlaURZZgOY4k= +github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= +github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw= +github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= +github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= +github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= +github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= +github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= +github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8= +github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= +github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= +github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo= +github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= +github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= +github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= +github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= +github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= +github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U= +github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E= +github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= +github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= +github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3lYhJjnGEk= +github.com/quic-go/webtransport-go v0.5.2/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= +github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= +github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= +github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8= +go.uber.org/dig v1.16.1/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk= +go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= +go.uber.org/fx v1.19.2/go.mod h1:43G1VcqSzbIv77y00p1DRAsyZS8WdzuYdhZXmEUkMyQ= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= +lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/perf/impl/go-libp2p/v0.27/main.go b/perf/impl/go-libp2p/v0.27/main.go new file mode 100644 index 000000000..36ef75318 --- /dev/null +++ b/perf/impl/go-libp2p/v0.27/main.go @@ -0,0 +1,119 @@ +package main + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "net" + "time" + + "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/multiformats/go-multiaddr" +) + +func main() { + runServer := flag.Bool("run-server", false, "Should run as server") + serverAddr := flag.String("server-address", "", "Server address") + transport := flag.String("transport", "tcp", "Transport to use") + uploadBytes := flag.Uint64("upload-bytes", 0, "Upload bytes") + downloadBytes := flag.Uint64("download-bytes", 0, "Download bytes") + flag.Parse() + + host, port, err := net.SplitHostPort(*serverAddr) + if err != nil { + log.Fatal(err) + } + + tcpMultiAddrStr := fmt.Sprintf("/ip4/%s/tcp/%s", host, port) + quicMultiAddrStr := fmt.Sprintf("/ip4/%s/udp/%s/quic-v1", host, port) + + var opts []libp2p.Option + if *runServer { + opts = append(opts, libp2p.ListenAddrStrings(tcpMultiAddrStr, quicMultiAddrStr)) + + // Generate stable fake identity. + // + // Using a stable identity (i.e. peer ID) allows the client to + // connect to the server without a prior exchange of the + // server's peer ID. + priv, _, err := crypto.GenerateEd25519Key(&simpleReader{seed: 0}) + if err != nil { + log.Fatalf("failed to generate key: %s", err) + } + opts = append(opts, libp2p.Identity(priv)) + } + + h, err := libp2p.New(opts...) + if err != nil { + log.Fatalf("failed to instantiate libp2p: %s", err) + } + + perf := NewPerfService(h) + if *runServer { + for _, a := range h.Addrs() { + fmt.Println(a.Encapsulate(multiaddr.StringCast("/p2p/" + h.ID().String()))) + } + + select {} // run forever, exit on interrupt + } + + var multiAddrStr string + switch *transport { + case "tcp": + multiAddrStr = tcpMultiAddrStr + case "quic-v1": + multiAddrStr = quicMultiAddrStr + default: + fmt.Println("Invalid transport. Accepted values: 'tcp' or 'quic-v1'") + return + } + // Peer ID corresponds to the above fake identity. + multiAddrStr = multiAddrStr + "/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN" + serverInfo, err := peer.AddrInfoFromString(multiAddrStr) + if err != nil { + log.Fatalf("failed to build address info: %s", err) + } + + start := time.Now() + err = h.Connect(context.Background(), *serverInfo) + 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)) + 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(), + }) + if err != nil { + log.Fatalf("failed to marshal perf result: %s", err) + } + + fmt.Println(string(jsonB)) +} + +type Result struct { + ConnectionEstablishedSeconds float64 `json:"connectionEstablishedSeconds"` + UploadSeconds float64 `json:"uploadSeconds"` + DownloadSeconds float64 `json:"downloadSeconds"` +} + +type simpleReader struct { + seed uint8 +} + +func (r *simpleReader) Read(p []byte) (n int, err error) { + for i := range p { + p[i] = r.seed + } + return len(p), nil +} diff --git a/perf/impl/go-libp2p/v0.27/perf.go b/perf/impl/go-libp2p/v0.27/perf.go new file mode 100644 index 000000000..33d89835d --- /dev/null +++ b/perf/impl/go-libp2p/v0.27/perf.go @@ -0,0 +1,118 @@ +package main + +import ( + "context" + "encoding/binary" + "fmt" + "io" + "time" + + logging "github.com/ipfs/go-log/v2" + pool "github.com/libp2p/go-buffer-pool" + "github.com/libp2p/go-libp2p/core/host" + "github.com/libp2p/go-libp2p/core/network" + "github.com/libp2p/go-libp2p/core/peer" +) + +var log = logging.Logger("perf") + +const ( + ID = "/perf/1.0.0" + blockSize = 64 << 10 +) + +type PerfService struct { + Host host.Host +} + +func NewPerfService(h host.Host) *PerfService { + ps := &PerfService{h} + h.SetStreamHandler(ID, ps.PerfHandler) + return ps +} + +func (ps *PerfService) PerfHandler(s network.Stream) { + u64Buf := make([]byte, 8) + if _, err := io.ReadFull(s, u64Buf); err != nil { + log.Errorw("err", err) + s.Reset() + return + } + + bytesToSend := binary.BigEndian.Uint64(u64Buf) + + if _, err := drainStream(s); err != nil { + log.Errorw("err", err) + s.Reset() + return + } + + if err := sendBytes(s, bytesToSend); err != nil { + log.Errorw("err", err) + s.Reset() + return + } + s.CloseWrite() +} + +func (ps *PerfService) RunPerf(ctx context.Context, p peer.ID, bytesToSend uint64, bytesToRecv uint64) (time.Duration, time.Duration, error) { + s, err := ps.Host.NewStream(ctx, p, ID) + if err != nil { + return 0, 0, err + } + + sizeBuf := make([]byte, 8) + binary.BigEndian.PutUint64(sizeBuf, bytesToRecv) + + _, err = s.Write(sizeBuf) + if err != nil { + return 0, 0, err + } + + sendStart := time.Now() + if err := sendBytes(s, bytesToSend); err != nil { + return 0, 0, err + } + sendDuration := time.Since(sendStart) + + recvStart := time.Now() + recvd, err := drainStream(s) + if err != nil { + return sendDuration, 0, err + } + recvDuration := time.Since(recvStart) + + if recvd != bytesToRecv { + return sendDuration, recvDuration, fmt.Errorf("expected to recv %d bytes, got %d", bytesToRecv, recvd) + } + + return sendDuration, recvDuration, nil +} + +func sendBytes(s io.Writer, bytesToSend uint64) error { + buf := pool.Get(blockSize) + defer pool.Put(buf) + + for bytesToSend > 0 { + toSend := buf + if bytesToSend < blockSize { + toSend = buf[:bytesToSend] + } + + n, err := s.Write(toSend) + if err != nil { + return err + } + bytesToSend -= uint64(n) + } + return nil +} + +func drainStream(s io.Reader) (uint64, error) { + var recvd int64 + recvd, err := io.Copy(io.Discard, s) + if err != nil && err != io.EOF { + return uint64(recvd), err + } + return uint64(recvd), nil +} diff --git a/perf/impl/https/.gitignore b/perf/impl/https/.gitignore new file mode 100644 index 000000000..819c818b2 --- /dev/null +++ b/perf/impl/https/.gitignore @@ -0,0 +1,5 @@ +go-libp2p-*.zip +go-libp2p-* +go-libp2p-*/* +image.json +https diff --git a/perf/impl/https/v0.1/Makefile b/perf/impl/https/v0.1/Makefile new file mode 100644 index 000000000..7df62c287 --- /dev/null +++ b/perf/impl/https/v0.1/Makefile @@ -0,0 +1,11 @@ +GO_FILES := $(wildcard *.go) + +all: perf + +perf: $(GO_FILES) + docker run --rm --user "$(shell id -u):$(shell id -g)" -v "$(shell pwd)":/usr/src/myapp -w /usr/src/myapp -e GOCACHE=/usr/src/myapp/.cache golang:1.20 go build -o perf . + +clean: + rm perf + +.PHONY: all diff --git a/perf/impl/https/v0.1/go.mod b/perf/impl/https/v0.1/go.mod new file mode 100644 index 000000000..0ff4e1746 --- /dev/null +++ b/perf/impl/https/v0.1/go.mod @@ -0,0 +1,3 @@ +module github.com/libp2p/test-plans/perf/go/https + +go 1.20 diff --git a/perf/impl/https/v0.1/go.sum b/perf/impl/https/v0.1/go.sum new file mode 100644 index 000000000..e69de29bb diff --git a/perf/impl/https/v0.1/main.go b/perf/impl/https/v0.1/main.go new file mode 100644 index 000000000..30373b75a --- /dev/null +++ b/perf/impl/https/v0.1/main.go @@ -0,0 +1,263 @@ +package main + +import ( + "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/binary" + "encoding/json" + "encoding/pem" + "flag" + "fmt" + "io" + "log" + "math/big" + "net" + "net/http" + "strconv" + "time" +) + +const blockSize = 64 << 10 + +func handleRequest(w http.ResponseWriter, r *http.Request) { + u64Buf := make([]byte, 8) + if _, err := io.ReadFull(r.Body, u64Buf); err != nil { + log.Printf("reading upload size failed: %s", err) + w.WriteHeader(http.StatusBadRequest) + return + } + + bytesToSend := binary.BigEndian.Uint64(u64Buf) + + if _, err := drainStream(r.Body); err != nil { + log.Printf("draining stream failed: %s", err) + w.WriteHeader(http.StatusBadRequest) + return + } + + r.Header.Set("Content-Type", "application/octet-stream") + r.Header.Set("Content-Length", strconv.FormatUint(bytesToSend, 10)) + + if err := sendBytes(w, bytesToSend); err != nil { + log.Printf("sending response failed: %s", err) + return + } +} + +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, time.Duration, error) { + client := &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + }, + } + + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, uploadBytes) + + req, err := http.NewRequest( + http.MethodPost, + fmt.Sprintf("https://%s/", serverAddr), + io.MultiReader( + bytes.NewReader(b), + &nullReader{N: uploadBytes}, + ), + ) + if err != nil { + return 0, 0, err + } + + req.Header.Set("Content-Type", "application/octet-stream") + req.Header.Set("Content-Length", strconv.FormatUint(uploadBytes+8, 10)) + + startTime := time.Now() + resp, err := client.Do(req) + if err != nil { + return 0, 0, err + } + if resp.StatusCode != http.StatusOK { + return 0, 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) + } + if n != downloadBytes { + return 0, 0, fmt.Errorf("expected %d bytes in response, but received %d", downloadBytes, n) + } + + return uploadDoneTime.Sub(startTime), time.Since(uploadDoneTime), nil +} + +func generateEphemeralCertificate() (tls.Certificate, error) { + // Generate an ECDSA private key + privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return tls.Certificate{}, err + } + + // Set up the certificate template + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + Organization: []string{"Ephemeral Cert"}, + }, + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, + ExtKeyUsage: []x509.ExtKeyUsage{ + x509.ExtKeyUsageServerAuth, + }, + BasicConstraintsValid: true, + } + + // Set the IP address if required + ip := net.ParseIP("127.0.0.1") + if ip != nil { + template.IPAddresses = append(template.IPAddresses, ip) + } + + // Create a self-signed certificate + certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey) + if err != nil { + return tls.Certificate{}, err + } + + // PEM encode the certificate and private key + certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) + privKeyBytes, err := x509.MarshalECPrivateKey(privKey) + if err != nil { + return tls.Certificate{}, err + } + privKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: privKeyBytes}) + + // Create a tls.Certificate from the PEM encoded certificate and private key + cert, err := tls.X509KeyPair(certPEM, privKeyPEM) + if err != nil { + return tls.Certificate{}, err + } + + return cert, nil +} + +type Result struct { + ConnectionEstablishedSeconds float64 `json:"connectionEstablishedSeconds"` + UploadSeconds float64 `json:"uploadSeconds"` + DownloadSeconds float64 `json:"downloadSeconds"` +} + +func main() { + runServer := flag.Bool("run-server", false, "Should run as server") + serverAddr := flag.String("server-address", "", "Server address") + _ = flag.String("transport", "", "Transport to use") + uploadBytes := flag.Uint64("upload-bytes", 0, "Upload bytes") + downloadBytes := flag.Uint64("download-bytes", 0, "Download bytes") + flag.Parse() + + if *runServer { + // Generate an ephemeral TLS certificate and private key + cert, err := generateEphemeralCertificate() + if err != nil { + log.Fatalf("Error generating ephemeral certificate: %v\n", err) + } + + // Parse the server address + _, port, err := net.SplitHostPort(*serverAddr) + if err != nil { + log.Fatalf("Invalid server address: %v\n", err) + } + + // Create a new HTTPS server with the ephemeral certificate + tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}} + server := &http.Server{ + Addr: ":" + port, + TLSConfig: tlsConfig, + } + + http.HandleFunc("/", handleRequest) + + // Start the HTTPS server + fmt.Printf("Starting HTTPS server on port %s\n", port) + err = server.ListenAndServeTLS("", "") + if err != nil { + fmt.Printf("Error starting HTTPS server: %v\n", err) + } + } else { + // Client mode + if *serverAddr == "" { + flag.Usage() + log.Fatal("Error: Please provide valid server-address flags for client mode.") + } + + // Run the client and print the results + upload, download, 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(), + }) + if err != nil { + log.Fatalf("failed to marshal perf result: %s", err) + } + fmt.Println(string(jsonB)) + } +} + +func sendBytes(s io.Writer, bytesToSend uint64) error { + buf := make([]byte, blockSize) + + for bytesToSend > 0 { + toSend := buf + if bytesToSend < blockSize { + toSend = buf[:bytesToSend] + } + + n, err := s.Write(toSend) + if err != nil { + return err + } + bytesToSend -= uint64(n) + } + return nil +} + +func drainStream(s io.Reader) (uint64, error) { + var recvd int64 + recvd, err := io.Copy(io.Discard, s) + if err != nil && err != io.EOF { + return uint64(recvd), err + } + return uint64(recvd), nil +} diff --git a/perf/impl/quic-go/.gitignore b/perf/impl/quic-go/.gitignore new file mode 100644 index 000000000..6652a25c1 --- /dev/null +++ b/perf/impl/quic-go/.gitignore @@ -0,0 +1,4 @@ +go-libp2p-*.zip +go-libp2p-* +go-libp2p-*/* +image.json diff --git a/perf/impl/quic-go/v0.34/Makefile b/perf/impl/quic-go/v0.34/Makefile new file mode 100644 index 000000000..35ede5174 --- /dev/null +++ b/perf/impl/quic-go/v0.34/Makefile @@ -0,0 +1,22 @@ +commitSha := bdfafffc8b7ec786ff41ea245f24920930eec720 + +all: perf + +perf: perf-${commitSha} + docker run --rm --user "$(shell id -u):$(shell id -g)" -v "$(shell pwd)/perf-${commitSha}":/usr/src/myapp -w /usr/src/myapp -e GOCACHE=/usr/src/myapp/.cache golang:1.20 go build -o perf cmd/main.go + cp perf-${commitSha}/perf . + +perf-${commitSha}: perf-${commitSha}.zip + unzip -o perf-${commitSha}.zip + +perf-${commitSha}.zip: + wget -O $@ "https://github.com/quic-go/perf/archive/${commitSha}.zip" + +clean: + rm perf-*.zip + rm -rf perf-* + rm perf + rm .cache + rm v0.27 + +.PHONY: all clean diff --git a/perf/impl/rust-libp2p-quinn/v0.52/Makefile b/perf/impl/rust-libp2p-quinn/v0.52/Makefile new file mode 100644 index 000000000..cd7b88fc8 --- /dev/null +++ b/perf/impl/rust-libp2p-quinn/v0.52/Makefile @@ -0,0 +1,22 @@ +commitSha := 84d29b34b19aef161a8583daffb9f63a385a613b + +all: perf + +perf: rust-libp2p-${commitSha}/target/release/perf + cp ./rust-libp2p-${commitSha}/target/release/perf . + +rust-libp2p-${commitSha}/target/release/perf: rust-libp2p-${commitSha} + docker run --rm --user "$(shell id -u):$(shell id -g)" -v "$(shell pwd)/rust-libp2p-${commitSha}":/usr/src/myapp -w /usr/src/myapp rust:1.69 cargo build --release --bin perf + +rust-libp2p-${commitSha}: rust-libp2p-${commitSha}.zip + unzip -o rust-libp2p-${commitSha}.zip + +rust-libp2p-${commitSha}.zip: +# TODO: Change to libp2p + wget -O $@ "https://github.com/mxinden/rust-libp2p/archive/${commitSha}.zip" + +clean: + rm rust-libp2p-*.zip + rm -rf rust-libp2p-* + +.PHONY: all clean run diff --git a/perf/impl/rust-libp2p/.gitignore b/perf/impl/rust-libp2p/.gitignore new file mode 100644 index 000000000..54704ed39 --- /dev/null +++ b/perf/impl/rust-libp2p/.gitignore @@ -0,0 +1,4 @@ +rust-libp2p-*.zip +rust-libp2p-* +rust-libp2p-*/* +image.json diff --git a/perf/impl/rust-libp2p/v0.52/Makefile b/perf/impl/rust-libp2p/v0.52/Makefile new file mode 100644 index 000000000..ad2b0df5e --- /dev/null +++ b/perf/impl/rust-libp2p/v0.52/Makefile @@ -0,0 +1,22 @@ +commitSha := ed14630672b66958d1da52ecbff03004f0c057c0 + +all: perf + +perf: rust-libp2p-${commitSha}/target/release/perf + cp ./rust-libp2p-${commitSha}/target/release/perf . + +rust-libp2p-${commitSha}/target/release/perf: rust-libp2p-${commitSha} + docker run --rm --user "$(shell id -u):$(shell id -g)" -v "$(shell pwd)/rust-libp2p-${commitSha}":/usr/src/myapp -w /usr/src/myapp rust:1.69 cargo build --release --bin perf + +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" + +clean: + rm rust-libp2p-*.zip + rm -rf rust-libp2p-* + rm perf + +.PHONY: all clean diff --git a/perf/runner/.gitignore b/perf/runner/.gitignore new file mode 100644 index 000000000..5c09c53cd --- /dev/null +++ b/perf/runner/.gitignore @@ -0,0 +1,2 @@ +# Ignore built ts files +dist/**/* diff --git a/perf/runner/benchmark-results.json b/perf/runner/benchmark-results.json new file mode 100644 index 000000000..367cfba89 --- /dev/null +++ b/perf/runner/benchmark-results.json @@ -0,0 +1,4203 @@ +{ + "benchmarks": [ + { + "name": "Single Connection throughput – Upload 100 MiB", + "unit": "bit/s", + "results": [ + { + "result": [ + { + "connectionEstablishedSeconds": 0.068123765, + "uploadSeconds": 0.970456932, + "downloadSeconds": 5.3e-8 + }, + { + "connectionEstablishedSeconds": 0.062713554, + "uploadSeconds": 0.975849906, + "downloadSeconds": 6.8e-8 + }, + { + "connectionEstablishedSeconds": 0.065501309, + "uploadSeconds": 1.022005129, + "downloadSeconds": 6e-8 + }, + { + "connectionEstablishedSeconds": 0.066928483, + "uploadSeconds": 1.041319663, + "downloadSeconds": 5.3e-8 + }, + { + "connectionEstablishedSeconds": 0.064004129, + "uploadSeconds": 0.996991871, + "downloadSeconds": 5.3e-8 + } + ], + "implementation": "quic-go", + "version": "v0.34", + "transportStack": "quic-v1" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.131599504, + "uploadSeconds": 47.63213805, + "downloadSeconds": 0.064913485 + }, + { + "connectionEstablishedSeconds": 0.127136394, + "uploadSeconds": 43.618970957, + "downloadSeconds": 0.063410859 + }, + { + "connectionEstablishedSeconds": 0.127686874, + "uploadSeconds": 44.623888682, + "downloadSeconds": 0.063648489 + }, + { + "connectionEstablishedSeconds": 0.128835409, + "uploadSeconds": 46.479589264, + "downloadSeconds": 0.065293635 + }, + { + "connectionEstablishedSeconds": 0.128399353, + "uploadSeconds": 45.799956017, + "downloadSeconds": 0.063969977 + } + ], + "implementation": "rust-libp2p", + "version": "v0.52", + "transportStack": "tcp" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.064484261, + "uploadSeconds": 30.439845709, + "downloadSeconds": 0.000163488 + }, + { + "connectionEstablishedSeconds": 0.06265785, + "uploadSeconds": 11.516149765, + "downloadSeconds": 0.000129193 + }, + { + "connectionEstablishedSeconds": 0.065870575, + "uploadSeconds": 16.945701847, + "downloadSeconds": 0.000083312 + }, + { + "connectionEstablishedSeconds": 0.066685308, + "uploadSeconds": 17.157438746, + "downloadSeconds": 0.000134467 + }, + { + "connectionEstablishedSeconds": 0.06508686, + "uploadSeconds": 20.362663014, + "downloadSeconds": 0.00021038 + } + ], + "implementation": "rust-libp2p", + "version": "v0.52", + "transportStack": "quic-v1" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.068856644, + "uploadSeconds": 1.402213112, + "downloadSeconds": 0.000085133 + }, + { + "connectionEstablishedSeconds": 0.065518432, + "uploadSeconds": 1.445110638, + "downloadSeconds": 0.000089192 + }, + { + "connectionEstablishedSeconds": 0.061399509, + "uploadSeconds": 1.347394456, + "downloadSeconds": 0.000055885 + }, + { + "connectionEstablishedSeconds": 0.063340799, + "uploadSeconds": 1.3995380339999999, + "downloadSeconds": 0.000043643 + }, + { + "connectionEstablishedSeconds": 0.063240204, + "uploadSeconds": 1.393610506, + "downloadSeconds": 0.000126388 + } + ], + "implementation": "rust-libp2p-quinn", + "version": "v0.52", + "transportStack": "quic-v1" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 2.79994608, + "downloadSeconds": 0.000001624 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 2.712869064, + "downloadSeconds": 0.000004425 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 2.7989140260000003, + "downloadSeconds": 0.000001659 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 2.797738943, + "downloadSeconds": 0.000003846 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 2.710649859, + "downloadSeconds": 0.000004266 + } + ], + "implementation": "https", + "version": "v0.1", + "transportStack": "tcp" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.257897112, + "uploadSeconds": 2.898714608, + "downloadSeconds": 0.125947478 + }, + { + "connectionEstablishedSeconds": 0.253306448, + "uploadSeconds": 2.935159906, + "downloadSeconds": 0.124808834 + }, + { + "connectionEstablishedSeconds": 0.257107718, + "uploadSeconds": 2.956579177, + "downloadSeconds": 0.125826729 + }, + { + "connectionEstablishedSeconds": 0.261447279, + "uploadSeconds": 3.073232105, + "downloadSeconds": 0.128016533 + }, + { + "connectionEstablishedSeconds": 0.256173976, + "uploadSeconds": 3.094974155, + "downloadSeconds": 0.126269123 + } + ], + "implementation": "go-libp2p", + "version": "v0.27", + "transportStack": "tcp" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.132941292, + "uploadSeconds": 1.3138654889999999, + "downloadSeconds": 0.063525917 + }, + { + "connectionEstablishedSeconds": 0.130994117, + "uploadSeconds": 1.480872529, + "downloadSeconds": 0.063031466 + }, + { + "connectionEstablishedSeconds": 0.131776023, + "uploadSeconds": 1.303614286, + "downloadSeconds": 0.063162675 + }, + { + "connectionEstablishedSeconds": 0.127950072, + "uploadSeconds": 1.282649997, + "downloadSeconds": 0.062072209 + }, + { + "connectionEstablishedSeconds": 0.132015753, + "uploadSeconds": 1.308251399, + "downloadSeconds": 0.063331159 + } + ], + "implementation": "go-libp2p", + "version": "v0.27", + "transportStack": "quic-v1" + } + ], + "parameters": { + "uploadBytes": 104857600, + "downloadBytes": 0 + } + }, + { + "name": "Single Connection throughput – Download 100 MiB", + "unit": "bit/s", + "results": [ + { + "result": [ + { + "connectionEstablishedSeconds": 0.066565584, + "uploadSeconds": 4.14e-7, + "downloadSeconds": 1.156675842 + }, + { + "connectionEstablishedSeconds": 0.064892061, + "uploadSeconds": 4.79e-7, + "downloadSeconds": 1.069297593 + }, + { + "connectionEstablishedSeconds": 0.065190888, + "uploadSeconds": 5.41e-7, + "downloadSeconds": 1.597194709 + }, + { + "connectionEstablishedSeconds": 0.063803854, + "uploadSeconds": 6.02e-7, + "downloadSeconds": 1.263743063 + }, + { + "connectionEstablishedSeconds": 0.064557168, + "uploadSeconds": 5.93e-7, + "downloadSeconds": 1.063204626 + } + ], + "implementation": "quic-go", + "version": "v0.34", + "transportStack": "quic-v1" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.118973999, + "uploadSeconds": 0.00000237, + "downloadSeconds": 43.097832521 + }, + { + "connectionEstablishedSeconds": 0.127215353, + "uploadSeconds": 0.000002032, + "downloadSeconds": 45.641765158 + }, + { + "connectionEstablishedSeconds": 0.124596278, + "uploadSeconds": 0.000002028, + "downloadSeconds": 46.368505073 + }, + { + "connectionEstablishedSeconds": 0.128120916, + "uploadSeconds": 0.000002222, + "downloadSeconds": 47.874739863 + }, + { + "connectionEstablishedSeconds": 0.124931603, + "uploadSeconds": 0.000001954, + "downloadSeconds": 44.744356376 + } + ], + "implementation": "rust-libp2p", + "version": "v0.52", + "transportStack": "tcp" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.064101794, + "uploadSeconds": 0.062433886, + "downloadSeconds": 14.226532904 + }, + { + "connectionEstablishedSeconds": 0.064768482, + "uploadSeconds": 0.063380472, + "downloadSeconds": 9.652918476 + }, + { + "connectionEstablishedSeconds": 0.063089269, + "uploadSeconds": 0.061641026, + "downloadSeconds": 44.248097576 + }, + { + "connectionEstablishedSeconds": 0.065786917, + "uploadSeconds": 0.064454129, + "downloadSeconds": 7.935120556 + }, + { + "connectionEstablishedSeconds": 0.065490198, + "uploadSeconds": 0.064216836, + "downloadSeconds": 12.013647805 + } + ], + "implementation": "rust-libp2p", + "version": "v0.52", + "transportStack": "quic-v1" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.065718437, + "uploadSeconds": 0.063958589, + "downloadSeconds": 1.5755928510000001 + }, + { + "connectionEstablishedSeconds": 0.065243916, + "uploadSeconds": 0.063788174, + "downloadSeconds": 1.374596511 + }, + { + "connectionEstablishedSeconds": 0.065815979, + "uploadSeconds": 0.064431818, + "downloadSeconds": 1.406562029 + }, + { + "connectionEstablishedSeconds": 0.064376266, + "uploadSeconds": 0.062916412, + "downloadSeconds": 1.395864717 + }, + { + "connectionEstablishedSeconds": 0.065978775, + "uploadSeconds": 0.064501789, + "downloadSeconds": 1.412157431 + } + ], + "implementation": "rust-libp2p-quinn", + "version": "v0.52", + "transportStack": "quic-v1" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.188128181, + "downloadSeconds": 2.674302866 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191556654, + "downloadSeconds": 2.862983464 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.1892993, + "downloadSeconds": 2.526412433 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.19302405, + "downloadSeconds": 3.278985925 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.184218404, + "downloadSeconds": 2.509003996 + } + ], + "implementation": "https", + "version": "v0.1", + "transportStack": "tcp" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.25935759, + "uploadSeconds": 0.000044908, + "downloadSeconds": 3.076994748 + }, + { + "connectionEstablishedSeconds": 0.252395091, + "uploadSeconds": 0.000023151, + "downloadSeconds": 5.499522915 + }, + { + "connectionEstablishedSeconds": 0.247996802, + "uploadSeconds": 0.000049357, + "downloadSeconds": 3.000616134 + }, + { + "connectionEstablishedSeconds": 0.254360687, + "uploadSeconds": 0.000014436, + "downloadSeconds": 2.998061834 + }, + { + "connectionEstablishedSeconds": 0.248067035, + "uploadSeconds": 0.00002827, + "downloadSeconds": 8.412003512 + } + ], + "implementation": "go-libp2p", + "version": "v0.27", + "transportStack": "tcp" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.129844268, + "uploadSeconds": 0.000028622, + "downloadSeconds": 17.731692926 + }, + { + "connectionEstablishedSeconds": 0.126124365, + "uploadSeconds": 0.000011456, + "downloadSeconds": 33.438663611 + }, + { + "connectionEstablishedSeconds": 0.125621003, + "uploadSeconds": 0.000052524, + "downloadSeconds": 1.303201594 + }, + { + "connectionEstablishedSeconds": 0.127493675, + "uploadSeconds": 0.000047776, + "downloadSeconds": 1.375030162 + }, + { + "connectionEstablishedSeconds": 0.126735688, + "uploadSeconds": 0.000032102, + "downloadSeconds": 1.33293199 + } + ], + "implementation": "go-libp2p", + "version": "v0.27", + "transportStack": "quic-v1" + } + ], + "parameters": { + "uploadBytes": 0, + "downloadBytes": 104857600 + } + }, + { + "name": "Connection establishment + 1 byte round trip latencies", + "unit": "s", + "results": [ + { + "result": [ + { + "connectionEstablishedSeconds": 0.065960652, + "uploadSeconds": 0.000002015, + "downloadSeconds": 0.063855438 + }, + { + "connectionEstablishedSeconds": 0.065796591, + "uploadSeconds": 7.76e-7, + "downloadSeconds": 0.06396702 + }, + { + "connectionEstablishedSeconds": 0.063741155, + "uploadSeconds": 7.26e-7, + "downloadSeconds": 0.061985858 + }, + { + "connectionEstablishedSeconds": 0.063623635, + "uploadSeconds": 8.74e-7, + "downloadSeconds": 0.061928483 + }, + { + "connectionEstablishedSeconds": 0.065022228, + "uploadSeconds": 8.35e-7, + "downloadSeconds": 0.063295054 + }, + { + "connectionEstablishedSeconds": 0.063489342, + "uploadSeconds": 8.91e-7, + "downloadSeconds": 0.061834942 + }, + { + "connectionEstablishedSeconds": 0.063839197, + "uploadSeconds": 0.000001813, + "downloadSeconds": 0.062152462 + }, + { + "connectionEstablishedSeconds": 0.062052708, + "uploadSeconds": 0.00000184, + "downloadSeconds": 0.060337044 + }, + { + "connectionEstablishedSeconds": 0.06652303, + "uploadSeconds": 0.000001925, + "downloadSeconds": 0.06475633 + }, + { + "connectionEstablishedSeconds": 0.064486313, + "uploadSeconds": 0.000001878, + "downloadSeconds": 0.062974785 + }, + { + "connectionEstablishedSeconds": 0.06602361, + "uploadSeconds": 0.000001897, + "downloadSeconds": 0.064166513 + }, + { + "connectionEstablishedSeconds": 0.065900274, + "uploadSeconds": 0.00000199, + "downloadSeconds": 0.064157587 + }, + { + "connectionEstablishedSeconds": 0.065483286, + "uploadSeconds": 0.000001814, + "downloadSeconds": 0.06382869 + }, + { + "connectionEstablishedSeconds": 0.065826406, + "uploadSeconds": 7.81e-7, + "downloadSeconds": 0.064117447 + }, + { + "connectionEstablishedSeconds": 0.063089169, + "uploadSeconds": 0.00000184, + "downloadSeconds": 0.061341493 + }, + { + "connectionEstablishedSeconds": 0.063718383, + "uploadSeconds": 0.000001888, + "downloadSeconds": 0.063655426 + }, + { + "connectionEstablishedSeconds": 0.066834037, + "uploadSeconds": 7.83e-7, + "downloadSeconds": 0.065118068 + }, + { + "connectionEstablishedSeconds": 0.066410017, + "uploadSeconds": 7.09e-7, + "downloadSeconds": 0.064750831 + }, + { + "connectionEstablishedSeconds": 0.062099751, + "uploadSeconds": 0.000001848, + "downloadSeconds": 0.060406111 + }, + { + "connectionEstablishedSeconds": 0.064540611, + "uploadSeconds": 7.44e-7, + "downloadSeconds": 0.063029603 + }, + { + "connectionEstablishedSeconds": 0.062104416, + "uploadSeconds": 0.000001775, + "downloadSeconds": 0.060452269 + }, + { + "connectionEstablishedSeconds": 0.065979366, + "uploadSeconds": 0.000001828, + "downloadSeconds": 0.064631635 + }, + { + "connectionEstablishedSeconds": 0.064317867, + "uploadSeconds": 0.000001728, + "downloadSeconds": 0.062680971 + }, + { + "connectionEstablishedSeconds": 0.066068105, + "uploadSeconds": 0.000001847, + "downloadSeconds": 0.064407149 + }, + { + "connectionEstablishedSeconds": 0.066437507, + "uploadSeconds": 0.000001732, + "downloadSeconds": 0.064739867 + }, + { + "connectionEstablishedSeconds": 0.063907597, + "uploadSeconds": 0.000001816, + "downloadSeconds": 0.062924509 + }, + { + "connectionEstablishedSeconds": 0.064049647, + "uploadSeconds": 0.000001732, + "downloadSeconds": 0.06234967 + }, + { + "connectionEstablishedSeconds": 0.063910531, + "uploadSeconds": 0.00000186, + "downloadSeconds": 0.062329574 + }, + { + "connectionEstablishedSeconds": 0.065968402, + "uploadSeconds": 0.000001923, + "downloadSeconds": 0.064255131 + }, + { + "connectionEstablishedSeconds": 0.063100228, + "uploadSeconds": 0.000001812, + "downloadSeconds": 0.061423418 + }, + { + "connectionEstablishedSeconds": 0.066908387, + "uploadSeconds": 0.000001842, + "downloadSeconds": 0.065233548 + }, + { + "connectionEstablishedSeconds": 0.066429964, + "uploadSeconds": 0.00000185, + "downloadSeconds": 0.064721823 + }, + { + "connectionEstablishedSeconds": 0.064623603, + "uploadSeconds": 0.000001847, + "downloadSeconds": 0.063768799 + }, + { + "connectionEstablishedSeconds": 0.064637046, + "uploadSeconds": 0.000001848, + "downloadSeconds": 0.062864239 + }, + { + "connectionEstablishedSeconds": 0.066364894, + "uploadSeconds": 0.000001886, + "downloadSeconds": 0.064992379 + }, + { + "connectionEstablishedSeconds": 0.066949464, + "uploadSeconds": 0.000001917, + "downloadSeconds": 0.065019192 + }, + { + "connectionEstablishedSeconds": 0.064527955, + "uploadSeconds": 0.00000189, + "downloadSeconds": 0.062822321 + }, + { + "connectionEstablishedSeconds": 0.065350527, + "uploadSeconds": 7.2e-7, + "downloadSeconds": 0.063855509 + }, + { + "connectionEstablishedSeconds": 0.063090567, + "uploadSeconds": 0.000001824, + "downloadSeconds": 0.061434879 + }, + { + "connectionEstablishedSeconds": 0.065239703, + "uploadSeconds": 0.00000196, + "downloadSeconds": 0.063566127 + }, + { + "connectionEstablishedSeconds": 0.063867134, + "uploadSeconds": 0.000001787, + "downloadSeconds": 0.062171417 + }, + { + "connectionEstablishedSeconds": 0.064744197, + "uploadSeconds": 0.000001909, + "downloadSeconds": 0.063078302 + }, + { + "connectionEstablishedSeconds": 0.063921323, + "uploadSeconds": 0.000001774, + "downloadSeconds": 0.062253087 + }, + { + "connectionEstablishedSeconds": 0.065797461, + "uploadSeconds": 0.000001763, + "downloadSeconds": 0.064141632 + }, + { + "connectionEstablishedSeconds": 0.063432254, + "uploadSeconds": 7.52e-7, + "downloadSeconds": 0.063523257 + }, + { + "connectionEstablishedSeconds": 0.063448576, + "uploadSeconds": 0.000001847, + "downloadSeconds": 0.061447665 + }, + { + "connectionEstablishedSeconds": 0.064840213, + "uploadSeconds": 0.000001799, + "downloadSeconds": 0.063268648 + }, + { + "connectionEstablishedSeconds": 0.062984093, + "uploadSeconds": 0.000001873, + "downloadSeconds": 0.061266251 + }, + { + "connectionEstablishedSeconds": 0.063835431, + "uploadSeconds": 0.000001041, + "downloadSeconds": 0.062294655 + }, + { + "connectionEstablishedSeconds": 0.066513465, + "uploadSeconds": 0.000001802, + "downloadSeconds": 0.06479643 + }, + { + "connectionEstablishedSeconds": 0.064597329, + "uploadSeconds": 0.000001768, + "downloadSeconds": 0.062962919 + }, + { + "connectionEstablishedSeconds": 0.065778361, + "uploadSeconds": 0.00000186, + "downloadSeconds": 0.06410771 + }, + { + "connectionEstablishedSeconds": 0.065951503, + "uploadSeconds": 0.000001775, + "downloadSeconds": 0.063964319 + }, + { + "connectionEstablishedSeconds": 0.065201946, + "uploadSeconds": 0.000001795, + "downloadSeconds": 0.063643639 + }, + { + "connectionEstablishedSeconds": 0.066076218, + "uploadSeconds": 0.000001848, + "downloadSeconds": 0.064510646 + }, + { + "connectionEstablishedSeconds": 0.060682481, + "uploadSeconds": 0.000002, + "downloadSeconds": 0.059199478 + }, + { + "connectionEstablishedSeconds": 0.065554049, + "uploadSeconds": 0.000001739, + "downloadSeconds": 0.06377536 + }, + { + "connectionEstablishedSeconds": 0.061208203, + "uploadSeconds": 0.00000177, + "downloadSeconds": 0.059550325 + }, + { + "connectionEstablishedSeconds": 0.067027502, + "uploadSeconds": 0.000001823, + "downloadSeconds": 0.065262971 + }, + { + "connectionEstablishedSeconds": 0.066147698, + "uploadSeconds": 0.000001906, + "downloadSeconds": 0.064408233 + }, + { + "connectionEstablishedSeconds": 0.066192563, + "uploadSeconds": 0.000001711, + "downloadSeconds": 0.064853112 + }, + { + "connectionEstablishedSeconds": 0.065939828, + "uploadSeconds": 0.000001766, + "downloadSeconds": 0.064260021 + }, + { + "connectionEstablishedSeconds": 0.06487606, + "uploadSeconds": 0.000001916, + "downloadSeconds": 0.063237738 + }, + { + "connectionEstablishedSeconds": 0.064049202, + "uploadSeconds": 0.000001889, + "downloadSeconds": 0.062357129 + }, + { + "connectionEstablishedSeconds": 0.065536679, + "uploadSeconds": 0.000001785, + "downloadSeconds": 0.064333056 + }, + { + "connectionEstablishedSeconds": 0.063045093, + "uploadSeconds": 0.000001888, + "downloadSeconds": 0.061440221 + }, + { + "connectionEstablishedSeconds": 0.06322189, + "uploadSeconds": 0.00000193, + "downloadSeconds": 0.06153135 + }, + { + "connectionEstablishedSeconds": 0.06471423, + "uploadSeconds": 0.000001819, + "downloadSeconds": 0.063194954 + }, + { + "connectionEstablishedSeconds": 0.065249297, + "uploadSeconds": 0.00000169, + "downloadSeconds": 0.064097755 + }, + { + "connectionEstablishedSeconds": 0.064081193, + "uploadSeconds": 7.64e-7, + "downloadSeconds": 0.062326683 + }, + { + "connectionEstablishedSeconds": 0.063041856, + "uploadSeconds": 0.000001814, + "downloadSeconds": 0.061309187 + }, + { + "connectionEstablishedSeconds": 0.063910362, + "uploadSeconds": 0.00000181, + "downloadSeconds": 0.062275784 + }, + { + "connectionEstablishedSeconds": 0.063506594, + "uploadSeconds": 0.000001843, + "downloadSeconds": 0.061753042 + }, + { + "connectionEstablishedSeconds": 0.066419848, + "uploadSeconds": 0.000001996, + "downloadSeconds": 0.064808717 + }, + { + "connectionEstablishedSeconds": 0.062470426, + "uploadSeconds": 0.000001741, + "downloadSeconds": 0.06096953 + }, + { + "connectionEstablishedSeconds": 0.064943312, + "uploadSeconds": 0.000001849, + "downloadSeconds": 0.063242568 + }, + { + "connectionEstablishedSeconds": 0.064688986, + "uploadSeconds": 0.000001694, + "downloadSeconds": 0.06291107 + }, + { + "connectionEstablishedSeconds": 0.064706476, + "uploadSeconds": 0.00000183, + "downloadSeconds": 0.06321239 + }, + { + "connectionEstablishedSeconds": 0.060864393, + "uploadSeconds": 7.13e-7, + "downloadSeconds": 0.059260479 + }, + { + "connectionEstablishedSeconds": 0.064634663, + "uploadSeconds": 0.00000181, + "downloadSeconds": 0.062899306 + }, + { + "connectionEstablishedSeconds": 0.062740938, + "uploadSeconds": 0.000001724, + "downloadSeconds": 0.061089935 + }, + { + "connectionEstablishedSeconds": 0.06110142, + "uploadSeconds": 0.000001824, + "downloadSeconds": 0.059406993 + }, + { + "connectionEstablishedSeconds": 0.065856369, + "uploadSeconds": 0.000001818, + "downloadSeconds": 0.064210017 + }, + { + "connectionEstablishedSeconds": 0.063945114, + "uploadSeconds": 7.78e-7, + "downloadSeconds": 0.06232278 + }, + { + "connectionEstablishedSeconds": 0.06562598, + "uploadSeconds": 0.000001739, + "downloadSeconds": 0.063622294 + }, + { + "connectionEstablishedSeconds": 0.066873176, + "uploadSeconds": 0.000001773, + "downloadSeconds": 0.065124502 + }, + { + "connectionEstablishedSeconds": 0.063249351, + "uploadSeconds": 0.000002101, + "downloadSeconds": 0.061409982 + }, + { + "connectionEstablishedSeconds": 0.063833002, + "uploadSeconds": 7.34e-7, + "downloadSeconds": 0.062095569 + }, + { + "connectionEstablishedSeconds": 0.064269477, + "uploadSeconds": 7.34e-7, + "downloadSeconds": 0.062764291 + }, + { + "connectionEstablishedSeconds": 0.063465935, + "uploadSeconds": 7.32e-7, + "downloadSeconds": 0.061807299 + }, + { + "connectionEstablishedSeconds": 0.0637097, + "uploadSeconds": 0.00000172, + "downloadSeconds": 0.062126378 + }, + { + "connectionEstablishedSeconds": 0.065199418, + "uploadSeconds": 0.000001855, + "downloadSeconds": 0.063405634 + }, + { + "connectionEstablishedSeconds": 0.063962776, + "uploadSeconds": 0.000001932, + "downloadSeconds": 0.062353148 + }, + { + "connectionEstablishedSeconds": 0.065688074, + "uploadSeconds": 7.1e-7, + "downloadSeconds": 0.064095358 + }, + { + "connectionEstablishedSeconds": 0.065177434, + "uploadSeconds": 0.000001761, + "downloadSeconds": 0.06355402 + }, + { + "connectionEstablishedSeconds": 0.065289624, + "uploadSeconds": 0.000001871, + "downloadSeconds": 0.063665141 + }, + { + "connectionEstablishedSeconds": 0.06637104, + "uploadSeconds": 0.000001787, + "downloadSeconds": 0.064671943 + }, + { + "connectionEstablishedSeconds": 0.062665683, + "uploadSeconds": 0.000001973, + "downloadSeconds": 0.06036064 + }, + { + "connectionEstablishedSeconds": 0.065424972, + "uploadSeconds": 0.000001703, + "downloadSeconds": 0.063783958 + }, + { + "connectionEstablishedSeconds": 0.064705635, + "uploadSeconds": 7.31e-7, + "downloadSeconds": 0.063094454 + } + ], + "implementation": "quic-go", + "version": "v0.34", + "transportStack": "quic-v1" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.126942223, + "uploadSeconds": 0.000002365, + "downloadSeconds": 0.063743985 + }, + { + "connectionEstablishedSeconds": 0.129295372, + "uploadSeconds": 0.00000192, + "downloadSeconds": 0.064682509 + }, + { + "connectionEstablishedSeconds": 0.129768923, + "uploadSeconds": 0.000001704, + "downloadSeconds": 0.065037798 + }, + { + "connectionEstablishedSeconds": 0.123600152, + "uploadSeconds": 0.000001813, + "downloadSeconds": 0.061774496 + }, + { + "connectionEstablishedSeconds": 0.128035321, + "uploadSeconds": 0.000001702, + "downloadSeconds": 0.064082694 + }, + { + "connectionEstablishedSeconds": 0.121026518, + "uploadSeconds": 0.000001726, + "downloadSeconds": 0.060509221 + }, + { + "connectionEstablishedSeconds": 0.126800344, + "uploadSeconds": 0.000002242, + "downloadSeconds": 0.063314286 + }, + { + "connectionEstablishedSeconds": 0.129647161, + "uploadSeconds": 0.000002486, + "downloadSeconds": 0.064824471 + }, + { + "connectionEstablishedSeconds": 0.123199402, + "uploadSeconds": 0.000001661, + "downloadSeconds": 0.061598863 + }, + { + "connectionEstablishedSeconds": 0.127989193, + "uploadSeconds": 0.000001733, + "downloadSeconds": 0.063972541 + }, + { + "connectionEstablishedSeconds": 0.126010653, + "uploadSeconds": 0.000001798, + "downloadSeconds": 0.062962346 + }, + { + "connectionEstablishedSeconds": 0.129831981, + "uploadSeconds": 0.000001649, + "downloadSeconds": 0.064948712 + }, + { + "connectionEstablishedSeconds": 0.125489475, + "uploadSeconds": 0.000001669, + "downloadSeconds": 0.062847671 + }, + { + "connectionEstablishedSeconds": 0.126238218, + "uploadSeconds": 0.000001634, + "downloadSeconds": 0.063051357 + }, + { + "connectionEstablishedSeconds": 0.129056283, + "uploadSeconds": 0.000001871, + "downloadSeconds": 0.064548455 + }, + { + "connectionEstablishedSeconds": 0.122463576, + "uploadSeconds": 0.000001873, + "downloadSeconds": 0.061220602 + }, + { + "connectionEstablishedSeconds": 0.129516166, + "uploadSeconds": 0.000002036, + "downloadSeconds": 0.064762367 + }, + { + "connectionEstablishedSeconds": 0.116596929, + "uploadSeconds": 0.000001673, + "downloadSeconds": 0.058290019 + }, + { + "connectionEstablishedSeconds": 0.141630184, + "uploadSeconds": 0.000001947, + "downloadSeconds": 0.063497261 + }, + { + "connectionEstablishedSeconds": 0.12986187, + "uploadSeconds": 0.000001712, + "downloadSeconds": 0.06490279 + }, + { + "connectionEstablishedSeconds": 0.128644074, + "uploadSeconds": 0.000001685, + "downloadSeconds": 0.064237667 + }, + { + "connectionEstablishedSeconds": 0.122887001, + "uploadSeconds": 0.000001889, + "downloadSeconds": 0.061421422 + }, + { + "connectionEstablishedSeconds": 0.127039579, + "uploadSeconds": 0.000001885, + "downloadSeconds": 0.063494302 + }, + { + "connectionEstablishedSeconds": 0.128683913, + "uploadSeconds": 0.000002124, + "downloadSeconds": 0.064358518 + }, + { + "connectionEstablishedSeconds": 0.128384975, + "uploadSeconds": 0.000001659, + "downloadSeconds": 0.064129054 + }, + { + "connectionEstablishedSeconds": 0.128997139, + "uploadSeconds": 0.000001702, + "downloadSeconds": 0.06447986 + }, + { + "connectionEstablishedSeconds": 0.12793287, + "uploadSeconds": 0.000001869, + "downloadSeconds": 0.06396775 + }, + { + "connectionEstablishedSeconds": 0.124082763, + "uploadSeconds": 0.000001698, + "downloadSeconds": 0.062029126 + }, + { + "connectionEstablishedSeconds": 0.126708355, + "uploadSeconds": 0.000001748, + "downloadSeconds": 0.063323382 + }, + { + "connectionEstablishedSeconds": 0.128975799, + "uploadSeconds": 0.000001654, + "downloadSeconds": 0.064501399 + }, + { + "connectionEstablishedSeconds": 0.1292131, + "uploadSeconds": 0.000001705, + "downloadSeconds": 0.064638372 + }, + { + "connectionEstablishedSeconds": 0.125226977, + "uploadSeconds": 0.000001689, + "downloadSeconds": 0.062704776 + }, + { + "connectionEstablishedSeconds": 0.130452951, + "uploadSeconds": 0.000001922, + "downloadSeconds": 0.065206671 + }, + { + "connectionEstablishedSeconds": 0.126270836, + "uploadSeconds": 0.000001778, + "downloadSeconds": 0.063104478 + }, + { + "connectionEstablishedSeconds": 0.126167525, + "uploadSeconds": 0.000001616, + "downloadSeconds": 0.063098974 + }, + { + "connectionEstablishedSeconds": 0.127841453, + "uploadSeconds": 0.000001811, + "downloadSeconds": 0.063930787 + }, + { + "connectionEstablishedSeconds": 0.128939264, + "uploadSeconds": 0.000002076, + "downloadSeconds": 0.064470581 + }, + { + "connectionEstablishedSeconds": 0.124303772, + "uploadSeconds": 0.000001842, + "downloadSeconds": 0.062183724 + }, + { + "connectionEstablishedSeconds": 0.126348586, + "uploadSeconds": 0.000001791, + "downloadSeconds": 0.063154844 + }, + { + "connectionEstablishedSeconds": 0.127755758, + "uploadSeconds": 0.000001785, + "downloadSeconds": 0.063894459 + }, + { + "connectionEstablishedSeconds": 0.129457672, + "uploadSeconds": 0.000002391, + "downloadSeconds": 0.064700609 + }, + { + "connectionEstablishedSeconds": 0.122909898, + "uploadSeconds": 0.000001746, + "downloadSeconds": 0.061491456 + }, + { + "connectionEstablishedSeconds": 0.123784186, + "uploadSeconds": 0.000001784, + "downloadSeconds": 0.061999664 + }, + { + "connectionEstablishedSeconds": 0.127851629, + "uploadSeconds": 0.000001679, + "downloadSeconds": 0.063985385 + }, + { + "connectionEstablishedSeconds": 0.12932324, + "uploadSeconds": 0.000001827, + "downloadSeconds": 0.064679131 + }, + { + "connectionEstablishedSeconds": 0.12660816, + "uploadSeconds": 0.000001793, + "downloadSeconds": 0.06332388 + }, + { + "connectionEstablishedSeconds": 0.120871705, + "uploadSeconds": 0.00000179, + "downloadSeconds": 0.060446085 + }, + { + "connectionEstablishedSeconds": 0.118100529, + "uploadSeconds": 0.00000173, + "downloadSeconds": 0.059087264 + }, + { + "connectionEstablishedSeconds": 0.126572056, + "uploadSeconds": 0.000001956, + "downloadSeconds": 0.063274223 + }, + { + "connectionEstablishedSeconds": 0.123841295, + "uploadSeconds": 0.000001938, + "downloadSeconds": 0.061978309 + }, + { + "connectionEstablishedSeconds": 0.127973095, + "uploadSeconds": 0.000001851, + "downloadSeconds": 0.064008529 + }, + { + "connectionEstablishedSeconds": 0.130283019, + "uploadSeconds": 0.000001647, + "downloadSeconds": 0.065152012 + }, + { + "connectionEstablishedSeconds": 0.128841959, + "uploadSeconds": 0.000001844, + "downloadSeconds": 0.064416521 + }, + { + "connectionEstablishedSeconds": 0.128233111, + "uploadSeconds": 0.000001944, + "downloadSeconds": 0.064136145 + }, + { + "connectionEstablishedSeconds": 0.12914781, + "uploadSeconds": 0.000001634, + "downloadSeconds": 0.064601974 + }, + { + "connectionEstablishedSeconds": 0.126026333, + "uploadSeconds": 0.000001726, + "downloadSeconds": 0.063072496 + }, + { + "connectionEstablishedSeconds": 0.125242444, + "uploadSeconds": 0.000001771, + "downloadSeconds": 0.06265885 + }, + { + "connectionEstablishedSeconds": 0.119356822, + "uploadSeconds": 0.00000268, + "downloadSeconds": 0.059637042 + }, + { + "connectionEstablishedSeconds": 0.121396427, + "uploadSeconds": 0.000002106, + "downloadSeconds": 0.060649707 + }, + { + "connectionEstablishedSeconds": 0.122918326, + "uploadSeconds": 0.000001778, + "downloadSeconds": 0.061468633 + }, + { + "connectionEstablishedSeconds": 0.130501829, + "uploadSeconds": 0.000001736, + "downloadSeconds": 0.064908113 + }, + { + "connectionEstablishedSeconds": 0.125249582, + "uploadSeconds": 0.000001861, + "downloadSeconds": 0.062594996 + }, + { + "connectionEstablishedSeconds": 0.123120777, + "uploadSeconds": 0.000002164, + "downloadSeconds": 0.061578881 + }, + { + "connectionEstablishedSeconds": 0.124396915, + "uploadSeconds": 0.000001703, + "downloadSeconds": 0.062208624 + }, + { + "connectionEstablishedSeconds": 0.126273983, + "uploadSeconds": 0.000001813, + "downloadSeconds": 0.063130063 + }, + { + "connectionEstablishedSeconds": 0.124430086, + "uploadSeconds": 0.000001687, + "downloadSeconds": 0.062228188 + }, + { + "connectionEstablishedSeconds": 0.132043221, + "uploadSeconds": 0.000001811, + "downloadSeconds": 0.065423374 + }, + { + "connectionEstablishedSeconds": 0.12127598, + "uploadSeconds": 0.000001624, + "downloadSeconds": 0.060656771 + }, + { + "connectionEstablishedSeconds": 0.127779055, + "uploadSeconds": 0.000001697, + "downloadSeconds": 0.063860988 + }, + { + "connectionEstablishedSeconds": 0.122487726, + "uploadSeconds": 0.000001862, + "downloadSeconds": 0.06127068 + }, + { + "connectionEstablishedSeconds": 0.126731134, + "uploadSeconds": 0.000001728, + "downloadSeconds": 0.063326428 + }, + { + "connectionEstablishedSeconds": 0.126230747, + "uploadSeconds": 0.00000168, + "downloadSeconds": 0.063123085 + }, + { + "connectionEstablishedSeconds": 0.128350478, + "uploadSeconds": 0.000001922, + "downloadSeconds": 0.064083463 + }, + { + "connectionEstablishedSeconds": 0.129744746, + "uploadSeconds": 0.000001907, + "downloadSeconds": 0.064915135 + }, + { + "connectionEstablishedSeconds": 0.126254335, + "uploadSeconds": 0.000001588, + "downloadSeconds": 0.063117523 + }, + { + "connectionEstablishedSeconds": 0.127972742, + "uploadSeconds": 0.000001828, + "downloadSeconds": 0.063975961 + }, + { + "connectionEstablishedSeconds": 0.121895822, + "uploadSeconds": 0.000001712, + "downloadSeconds": 0.060978954 + }, + { + "connectionEstablishedSeconds": 0.123748227, + "uploadSeconds": 0.000001643, + "downloadSeconds": 0.061931251 + }, + { + "connectionEstablishedSeconds": 0.127796747, + "uploadSeconds": 0.000001828, + "downloadSeconds": 0.063901984 + }, + { + "connectionEstablishedSeconds": 0.124894315, + "uploadSeconds": 0.000001677, + "downloadSeconds": 0.062428592 + }, + { + "connectionEstablishedSeconds": 0.12745025, + "uploadSeconds": 0.000002009, + "downloadSeconds": 0.06369987 + }, + { + "connectionEstablishedSeconds": 0.124998457, + "uploadSeconds": 0.000001752, + "downloadSeconds": 0.062803771 + }, + { + "connectionEstablishedSeconds": 0.129756553, + "uploadSeconds": 0.000001712, + "downloadSeconds": 0.064856409 + }, + { + "connectionEstablishedSeconds": 0.125216956, + "uploadSeconds": 0.000002201, + "downloadSeconds": 0.062558495 + }, + { + "connectionEstablishedSeconds": 0.122515436, + "uploadSeconds": 0.000002016, + "downloadSeconds": 0.061251861 + }, + { + "connectionEstablishedSeconds": 0.127974467, + "uploadSeconds": 0.000001656, + "downloadSeconds": 0.063976319 + }, + { + "connectionEstablishedSeconds": 0.127917455, + "uploadSeconds": 0.000001672, + "downloadSeconds": 0.063897681 + }, + { + "connectionEstablishedSeconds": 0.128319597, + "uploadSeconds": 0.000001954, + "downloadSeconds": 0.064106765 + }, + { + "connectionEstablishedSeconds": 0.128624204, + "uploadSeconds": 0.000001899, + "downloadSeconds": 0.064251524 + }, + { + "connectionEstablishedSeconds": 0.126486446, + "uploadSeconds": 0.000001841, + "downloadSeconds": 0.063203465 + }, + { + "connectionEstablishedSeconds": 0.129833791, + "uploadSeconds": 0.000001733, + "downloadSeconds": 0.064937319 + }, + { + "connectionEstablishedSeconds": 0.124898357, + "uploadSeconds": 0.000001724, + "downloadSeconds": 0.062520609 + }, + { + "connectionEstablishedSeconds": 0.12929984, + "uploadSeconds": 0.000001888, + "downloadSeconds": 0.064618047 + }, + { + "connectionEstablishedSeconds": 0.127874998, + "uploadSeconds": 0.000002, + "downloadSeconds": 0.063890819 + }, + { + "connectionEstablishedSeconds": 0.128142932, + "uploadSeconds": 0.000001718, + "downloadSeconds": 0.06405662 + }, + { + "connectionEstablishedSeconds": 0.124047196, + "uploadSeconds": 0.000001717, + "downloadSeconds": 0.062216621 + }, + { + "connectionEstablishedSeconds": 0.1249445, + "uploadSeconds": 0.000001788, + "downloadSeconds": 0.062462759 + }, + { + "connectionEstablishedSeconds": 0.126187799, + "uploadSeconds": 0.000001825, + "downloadSeconds": 0.063085401 + }, + { + "connectionEstablishedSeconds": 0.125372997, + "uploadSeconds": 0.000001757, + "downloadSeconds": 0.062630744 + }, + { + "connectionEstablishedSeconds": 0.124622638, + "uploadSeconds": 0.000001808, + "downloadSeconds": 0.061894104 + } + ], + "implementation": "rust-libp2p", + "version": "v0.52", + "transportStack": "tcp" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.062492165, + "uploadSeconds": 0.061112326, + "downloadSeconds": 0.000116715 + }, + { + "connectionEstablishedSeconds": 0.062649228, + "uploadSeconds": 0.061280622, + "downloadSeconds": 0.000080394 + }, + { + "connectionEstablishedSeconds": 0.064760828, + "uploadSeconds": 0.063351283, + "downloadSeconds": 0.000075496 + }, + { + "connectionEstablishedSeconds": 0.066180837, + "uploadSeconds": 0.064932222, + "downloadSeconds": 0.00008116 + }, + { + "connectionEstablishedSeconds": 0.065053382, + "uploadSeconds": 0.063823422, + "downloadSeconds": 0.000091261 + }, + { + "connectionEstablishedSeconds": 0.065101606, + "uploadSeconds": 0.063815129, + "downloadSeconds": 0.000092607 + }, + { + "connectionEstablishedSeconds": 0.062689717, + "uploadSeconds": 0.061288942, + "downloadSeconds": 0.000093534 + }, + { + "connectionEstablishedSeconds": 0.065046629, + "uploadSeconds": 0.063763816, + "downloadSeconds": 0.000081756 + }, + { + "connectionEstablishedSeconds": 0.062314766, + "uploadSeconds": 0.061037749, + "downloadSeconds": 0.000046607 + }, + { + "connectionEstablishedSeconds": 0.064858603, + "uploadSeconds": 0.063540237, + "downloadSeconds": 0.000079145 + }, + { + "connectionEstablishedSeconds": 0.064348321, + "uploadSeconds": 0.063027289, + "downloadSeconds": 0.000077306 + }, + { + "connectionEstablishedSeconds": 0.064959839, + "uploadSeconds": 0.063622551, + "downloadSeconds": 0.00004905 + }, + { + "connectionEstablishedSeconds": 0.063707615, + "uploadSeconds": 0.062420537, + "downloadSeconds": 0.000102342 + }, + { + "connectionEstablishedSeconds": 0.065048512, + "uploadSeconds": 0.063737865, + "downloadSeconds": 0.000118632 + }, + { + "connectionEstablishedSeconds": 0.064274475, + "uploadSeconds": 0.062903113, + "downloadSeconds": 0.000085883 + }, + { + "connectionEstablishedSeconds": 0.064577741, + "uploadSeconds": 0.063251792, + "downloadSeconds": 0.000076561 + }, + { + "connectionEstablishedSeconds": 0.065925377, + "uploadSeconds": 0.064583722, + "downloadSeconds": 0.000090743 + }, + { + "connectionEstablishedSeconds": 0.062300157, + "uploadSeconds": 0.06105258, + "downloadSeconds": 0.000135368 + }, + { + "connectionEstablishedSeconds": 0.064730107, + "uploadSeconds": 0.063349915, + "downloadSeconds": 0.000085658 + }, + { + "connectionEstablishedSeconds": 0.06515572, + "uploadSeconds": 0.063910665, + "downloadSeconds": 0.000090313 + }, + { + "connectionEstablishedSeconds": 0.065108686, + "uploadSeconds": 0.063750982, + "downloadSeconds": 0.000067266 + }, + { + "connectionEstablishedSeconds": 0.062007928, + "uploadSeconds": 0.060723595, + "downloadSeconds": 0.000072241 + }, + { + "connectionEstablishedSeconds": 0.065888524, + "uploadSeconds": 0.064580981, + "downloadSeconds": 0.000090292 + }, + { + "connectionEstablishedSeconds": 0.065236289, + "uploadSeconds": 0.063932549, + "downloadSeconds": 0.000089596 + }, + { + "connectionEstablishedSeconds": 0.065947026, + "uploadSeconds": 0.064630887, + "downloadSeconds": 0.000095345 + }, + { + "connectionEstablishedSeconds": 0.064336634, + "uploadSeconds": 0.062985158, + "downloadSeconds": 0.000074183 + }, + { + "connectionEstablishedSeconds": 0.062948996, + "uploadSeconds": 0.061767861, + "downloadSeconds": 0.000075181 + }, + { + "connectionEstablishedSeconds": 0.06109396, + "uploadSeconds": 0.059701938, + "downloadSeconds": 0.000071589 + }, + { + "connectionEstablishedSeconds": 0.064372236, + "uploadSeconds": 0.062974949, + "downloadSeconds": 0.000079756 + }, + { + "connectionEstablishedSeconds": 0.064453895, + "uploadSeconds": 0.063101378, + "downloadSeconds": 0.00009592 + }, + { + "connectionEstablishedSeconds": 0.06549708, + "uploadSeconds": 0.06415425, + "downloadSeconds": 0.000098662 + }, + { + "connectionEstablishedSeconds": 0.061722141, + "uploadSeconds": 0.060439927, + "downloadSeconds": 0.000067907 + }, + { + "connectionEstablishedSeconds": 0.062618168, + "uploadSeconds": 0.061334678, + "downloadSeconds": 0.000077256 + }, + { + "connectionEstablishedSeconds": 0.065047814, + "uploadSeconds": 0.06367261, + "downloadSeconds": 0.000091801 + }, + { + "connectionEstablishedSeconds": 0.063579779, + "uploadSeconds": 0.062226479, + "downloadSeconds": 0.000082145 + }, + { + "connectionEstablishedSeconds": 0.063011302, + "uploadSeconds": 0.061565533, + "downloadSeconds": 0.000086583 + }, + { + "connectionEstablishedSeconds": 0.065309634, + "uploadSeconds": 0.064046614, + "downloadSeconds": 0.000085699 + }, + { + "connectionEstablishedSeconds": 0.063779301, + "uploadSeconds": 0.063372405, + "downloadSeconds": 0.000136163 + }, + { + "connectionEstablishedSeconds": 0.064275774, + "uploadSeconds": 0.062967983, + "downloadSeconds": 0.000111519 + }, + { + "connectionEstablishedSeconds": 0.062869924, + "uploadSeconds": 0.061522136, + "downloadSeconds": 0.000099826 + }, + { + "connectionEstablishedSeconds": 0.065951048, + "uploadSeconds": 0.064701169, + "downloadSeconds": 0.000078351 + }, + { + "connectionEstablishedSeconds": 0.066478972, + "uploadSeconds": 0.065097486, + "downloadSeconds": 0.000082354 + }, + { + "connectionEstablishedSeconds": 0.065269249, + "uploadSeconds": 0.063912204, + "downloadSeconds": 0.000104537 + }, + { + "connectionEstablishedSeconds": 0.065817256, + "uploadSeconds": 0.06446906, + "downloadSeconds": 0.00007819 + }, + { + "connectionEstablishedSeconds": 0.064223987, + "uploadSeconds": 0.062801823, + "downloadSeconds": 0.000078383 + }, + { + "connectionEstablishedSeconds": 0.06476724, + "uploadSeconds": 0.063393313, + "downloadSeconds": 0.000099092 + }, + { + "connectionEstablishedSeconds": 0.063259049, + "uploadSeconds": 0.061967122, + "downloadSeconds": 0.000078373 + }, + { + "connectionEstablishedSeconds": 0.062528862, + "uploadSeconds": 0.06046343, + "downloadSeconds": 0.000076467 + }, + { + "connectionEstablishedSeconds": 0.066188334, + "uploadSeconds": 0.064863762, + "downloadSeconds": 0.000079565 + }, + { + "connectionEstablishedSeconds": 0.062887682, + "uploadSeconds": 0.061551332, + "downloadSeconds": 0.000076819 + }, + { + "connectionEstablishedSeconds": 0.066111253, + "uploadSeconds": 0.064702484, + "downloadSeconds": 0.000066659 + }, + { + "connectionEstablishedSeconds": 0.063300491, + "uploadSeconds": 0.061926982, + "downloadSeconds": 0.000083907 + }, + { + "connectionEstablishedSeconds": 0.06449862, + "uploadSeconds": 0.063121687, + "downloadSeconds": 0.000093747 + }, + { + "connectionEstablishedSeconds": 0.064823713, + "uploadSeconds": 0.063492443, + "downloadSeconds": 0.000084742 + }, + { + "connectionEstablishedSeconds": 0.065926331, + "uploadSeconds": 0.06454414, + "downloadSeconds": 0.000098276 + }, + { + "connectionEstablishedSeconds": 0.065139319, + "uploadSeconds": 0.063690364, + "downloadSeconds": 0.000077539 + }, + { + "connectionEstablishedSeconds": 0.065358817, + "uploadSeconds": 0.06400259, + "downloadSeconds": 0.00003313 + }, + { + "connectionEstablishedSeconds": 0.065301446, + "uploadSeconds": 0.064061379, + "downloadSeconds": 0.000077036 + }, + { + "connectionEstablishedSeconds": 0.063128633, + "uploadSeconds": 0.061784849, + "downloadSeconds": 0.000066813 + }, + { + "connectionEstablishedSeconds": 0.063143836, + "uploadSeconds": 0.061849758, + "downloadSeconds": 0.00007549 + }, + { + "connectionEstablishedSeconds": 0.062985418, + "uploadSeconds": 0.061620493, + "downloadSeconds": 0.000077547 + }, + { + "connectionEstablishedSeconds": 0.066465888, + "uploadSeconds": 0.064557997, + "downloadSeconds": 0.000080725 + }, + { + "connectionEstablishedSeconds": 0.063822981, + "uploadSeconds": 0.0624959, + "downloadSeconds": 0.000076361 + }, + { + "connectionEstablishedSeconds": 0.066168641, + "uploadSeconds": 0.064885029, + "downloadSeconds": 0.000082184 + }, + { + "connectionEstablishedSeconds": 0.065318529, + "uploadSeconds": 0.063980222, + "downloadSeconds": 0.000075709 + }, + { + "connectionEstablishedSeconds": 0.063808287, + "uploadSeconds": 0.062508188, + "downloadSeconds": 0.00007488 + }, + { + "connectionEstablishedSeconds": 0.063995944, + "uploadSeconds": 0.0627541, + "downloadSeconds": 0.000072214 + }, + { + "connectionEstablishedSeconds": 0.06397866, + "uploadSeconds": 0.062611512, + "downloadSeconds": 0.00006927 + }, + { + "connectionEstablishedSeconds": 0.065037845, + "uploadSeconds": 0.063947489, + "downloadSeconds": 0.000080016 + }, + { + "connectionEstablishedSeconds": 0.066120082, + "uploadSeconds": 0.064685778, + "downloadSeconds": 0.000082905 + }, + { + "connectionEstablishedSeconds": 0.062625315, + "uploadSeconds": 0.061221872, + "downloadSeconds": 0.000031938 + }, + { + "connectionEstablishedSeconds": 0.065900539, + "uploadSeconds": 0.06464932, + "downloadSeconds": 0.000077138 + }, + { + "connectionEstablishedSeconds": 0.064467677, + "uploadSeconds": 0.0630704, + "downloadSeconds": 0.000087459 + }, + { + "connectionEstablishedSeconds": 0.065558181, + "uploadSeconds": 0.064390576, + "downloadSeconds": 0.000088838 + }, + { + "connectionEstablishedSeconds": 0.064554054, + "uploadSeconds": 0.063124382, + "downloadSeconds": 0.000086044 + }, + { + "connectionEstablishedSeconds": 0.065518499, + "uploadSeconds": 0.0642783, + "downloadSeconds": 0.000069911 + }, + { + "connectionEstablishedSeconds": 0.066629516, + "uploadSeconds": 0.065206442, + "downloadSeconds": 0.000081926 + }, + { + "connectionEstablishedSeconds": 0.065656045, + "uploadSeconds": 0.064359504, + "downloadSeconds": 0.000044615 + }, + { + "connectionEstablishedSeconds": 0.063976017, + "uploadSeconds": 0.062635566, + "downloadSeconds": 0.000071372 + }, + { + "connectionEstablishedSeconds": 0.062951525, + "uploadSeconds": 0.061702677, + "downloadSeconds": 0.000078439 + }, + { + "connectionEstablishedSeconds": 0.063737264, + "uploadSeconds": 0.06236826, + "downloadSeconds": 0.00006622 + }, + { + "connectionEstablishedSeconds": 0.065378439, + "uploadSeconds": 0.064143514, + "downloadSeconds": 0.000085874 + }, + { + "connectionEstablishedSeconds": 0.063799799, + "uploadSeconds": 0.062465944, + "downloadSeconds": 0.000076315 + }, + { + "connectionEstablishedSeconds": 0.064016785, + "uploadSeconds": 0.062693022, + "downloadSeconds": 0.000073532 + }, + { + "connectionEstablishedSeconds": 0.066494306, + "uploadSeconds": 0.065370658, + "downloadSeconds": 0.000110275 + }, + { + "connectionEstablishedSeconds": 0.063535833, + "uploadSeconds": 0.062204885, + "downloadSeconds": 0.000096163 + }, + { + "connectionEstablishedSeconds": 0.060309504, + "uploadSeconds": 0.058998211, + "downloadSeconds": 0.000076909 + }, + { + "connectionEstablishedSeconds": 0.062002445, + "uploadSeconds": 0.060868854, + "downloadSeconds": 0.000067506 + }, + { + "connectionEstablishedSeconds": 0.06525739, + "uploadSeconds": 0.063977881, + "downloadSeconds": 0.000079046 + }, + { + "connectionEstablishedSeconds": 0.063392018, + "uploadSeconds": 0.062113137, + "downloadSeconds": 0.000079119 + }, + { + "connectionEstablishedSeconds": 0.065732927, + "uploadSeconds": 0.064370846, + "downloadSeconds": 0.000066241 + }, + { + "connectionEstablishedSeconds": 0.06651007, + "uploadSeconds": 0.065177715, + "downloadSeconds": 0.000134526 + }, + { + "connectionEstablishedSeconds": 0.064256641, + "uploadSeconds": 0.063039581, + "downloadSeconds": 0.000073272 + }, + { + "connectionEstablishedSeconds": 0.065119473, + "uploadSeconds": 0.06376839, + "downloadSeconds": 0.000074958 + }, + { + "connectionEstablishedSeconds": 0.062175277, + "uploadSeconds": 0.061104338, + "downloadSeconds": 0.000087541 + }, + { + "connectionEstablishedSeconds": 0.063139385, + "uploadSeconds": 0.06214719, + "downloadSeconds": 0.000078032 + }, + { + "connectionEstablishedSeconds": 0.064046091, + "uploadSeconds": 0.06271439, + "downloadSeconds": 0.000068561 + }, + { + "connectionEstablishedSeconds": 0.063052851, + "uploadSeconds": 0.062245386, + "downloadSeconds": 0.000045205 + }, + { + "connectionEstablishedSeconds": 0.064833757, + "uploadSeconds": 0.063268495, + "downloadSeconds": 0.000300286 + }, + { + "connectionEstablishedSeconds": 0.065363519, + "uploadSeconds": 0.064063992, + "downloadSeconds": 0.00007668 + } + ], + "implementation": "rust-libp2p", + "version": "v0.52", + "transportStack": "quic-v1" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.064520194, + "uploadSeconds": 0.062763047, + "downloadSeconds": 0.000311714 + }, + { + "connectionEstablishedSeconds": 0.061672534, + "uploadSeconds": 0.060131542, + "downloadSeconds": 0.000290564 + }, + { + "connectionEstablishedSeconds": 0.06559133, + "uploadSeconds": 0.064091439, + "downloadSeconds": 0.000220565 + }, + { + "connectionEstablishedSeconds": 0.06509549, + "uploadSeconds": 0.063602653, + "downloadSeconds": 0.000232934 + }, + { + "connectionEstablishedSeconds": 0.066234416, + "uploadSeconds": 0.064778126, + "downloadSeconds": 0.000224712 + }, + { + "connectionEstablishedSeconds": 0.063305258, + "uploadSeconds": 0.061815194, + "downloadSeconds": 0.000211531 + }, + { + "connectionEstablishedSeconds": 0.065295876, + "uploadSeconds": 0.063799653, + "downloadSeconds": 0.000215023 + }, + { + "connectionEstablishedSeconds": 0.066643606, + "uploadSeconds": 0.065195529, + "downloadSeconds": 0.000278385 + }, + { + "connectionEstablishedSeconds": 0.063005459, + "uploadSeconds": 0.061678785, + "downloadSeconds": 0.000260314 + }, + { + "connectionEstablishedSeconds": 0.065838078, + "uploadSeconds": 0.064328347, + "downloadSeconds": 0.000289925 + }, + { + "connectionEstablishedSeconds": 0.06564289, + "uploadSeconds": 0.064197027, + "downloadSeconds": 0.000239059 + }, + { + "connectionEstablishedSeconds": 0.064409611, + "uploadSeconds": 0.062990114, + "downloadSeconds": 0.000220292 + }, + { + "connectionEstablishedSeconds": 0.062809421, + "uploadSeconds": 0.061497011, + "downloadSeconds": 0.000217806 + }, + { + "connectionEstablishedSeconds": 0.063838736, + "uploadSeconds": 0.062350353, + "downloadSeconds": 0.000285214 + }, + { + "connectionEstablishedSeconds": 0.064723174, + "uploadSeconds": 0.063331722, + "downloadSeconds": 0.00020302 + }, + { + "connectionEstablishedSeconds": 0.064209506, + "uploadSeconds": 0.062743849, + "downloadSeconds": 0.000228847 + }, + { + "connectionEstablishedSeconds": 0.065077603, + "uploadSeconds": 0.063613483, + "downloadSeconds": 0.00028078 + }, + { + "connectionEstablishedSeconds": 0.062394046, + "uploadSeconds": 0.061067573, + "downloadSeconds": 0.000201108 + }, + { + "connectionEstablishedSeconds": 0.065299326, + "uploadSeconds": 0.063748553, + "downloadSeconds": 0.000242959 + }, + { + "connectionEstablishedSeconds": 0.064665813, + "uploadSeconds": 0.063258611, + "downloadSeconds": 0.000290005 + }, + { + "connectionEstablishedSeconds": 0.063905388, + "uploadSeconds": 0.062530847, + "downloadSeconds": 0.000234923 + }, + { + "connectionEstablishedSeconds": 0.06432057, + "uploadSeconds": 0.062942497, + "downloadSeconds": 0.000227728 + }, + { + "connectionEstablishedSeconds": 0.065251547, + "uploadSeconds": 0.063915261, + "downloadSeconds": 0.000286787 + }, + { + "connectionEstablishedSeconds": 0.065145683, + "uploadSeconds": 0.063710432, + "downloadSeconds": 0.00019077 + }, + { + "connectionEstablishedSeconds": 0.066127095, + "uploadSeconds": 0.064834648, + "downloadSeconds": 0.000209692 + }, + { + "connectionEstablishedSeconds": 0.062005086, + "uploadSeconds": 0.060587007, + "downloadSeconds": 0.000143414 + }, + { + "connectionEstablishedSeconds": 0.064123733, + "uploadSeconds": 0.062807069, + "downloadSeconds": 0.000197959 + }, + { + "connectionEstablishedSeconds": 0.062011479, + "uploadSeconds": 0.060655504, + "downloadSeconds": 0.000273931 + }, + { + "connectionEstablishedSeconds": 0.063505832, + "uploadSeconds": 0.062131307, + "downloadSeconds": 0.000204597 + }, + { + "connectionEstablishedSeconds": 0.063511408, + "uploadSeconds": 0.062059862, + "downloadSeconds": 0.000246621 + }, + { + "connectionEstablishedSeconds": 0.06440964, + "uploadSeconds": 0.062882752, + "downloadSeconds": 0.000228304 + }, + { + "connectionEstablishedSeconds": 0.060028443, + "uploadSeconds": 0.058494391, + "downloadSeconds": 0.00028323 + }, + { + "connectionEstablishedSeconds": 0.066110257, + "uploadSeconds": 0.064746388, + "downloadSeconds": 0.00023999 + }, + { + "connectionEstablishedSeconds": 0.065221789, + "uploadSeconds": 0.06388649, + "downloadSeconds": 0.000282664 + }, + { + "connectionEstablishedSeconds": 0.064010908, + "uploadSeconds": 0.062539179, + "downloadSeconds": 0.000293821 + }, + { + "connectionEstablishedSeconds": 0.066279266, + "uploadSeconds": 0.06482569, + "downloadSeconds": 0.000189668 + }, + { + "connectionEstablishedSeconds": 0.064467997, + "uploadSeconds": 0.062964242, + "downloadSeconds": 0.000205917 + }, + { + "connectionEstablishedSeconds": 0.063683088, + "uploadSeconds": 0.062621114, + "downloadSeconds": 0.000225339 + }, + { + "connectionEstablishedSeconds": 0.065295598, + "uploadSeconds": 0.063874133, + "downloadSeconds": 0.000301366 + }, + { + "connectionEstablishedSeconds": 0.066577362, + "uploadSeconds": 0.065280399, + "downloadSeconds": 0.000195606 + }, + { + "connectionEstablishedSeconds": 0.063268171, + "uploadSeconds": 0.061804848, + "downloadSeconds": 0.000296705 + }, + { + "connectionEstablishedSeconds": 0.065474833, + "uploadSeconds": 0.064150838, + "downloadSeconds": 0.000243106 + }, + { + "connectionEstablishedSeconds": 0.064503497, + "uploadSeconds": 0.063037301, + "downloadSeconds": 0.000240357 + }, + { + "connectionEstablishedSeconds": 0.063228496, + "uploadSeconds": 0.061711898, + "downloadSeconds": 0.0002308 + }, + { + "connectionEstablishedSeconds": 0.065222472, + "uploadSeconds": 0.063772095, + "downloadSeconds": 0.000225858 + }, + { + "connectionEstablishedSeconds": 0.064831753, + "uploadSeconds": 0.063397533, + "downloadSeconds": 0.000249322 + }, + { + "connectionEstablishedSeconds": 0.064904029, + "uploadSeconds": 0.063438406, + "downloadSeconds": 0.000198988 + }, + { + "connectionEstablishedSeconds": 0.064007547, + "uploadSeconds": 0.062655107, + "downloadSeconds": 0.000226498 + }, + { + "connectionEstablishedSeconds": 0.06389538, + "uploadSeconds": 0.062495956, + "downloadSeconds": 0.000296354 + }, + { + "connectionEstablishedSeconds": 0.065208755, + "uploadSeconds": 0.063847459, + "downloadSeconds": 0.000176159 + }, + { + "connectionEstablishedSeconds": 0.06254477, + "uploadSeconds": 0.061182311, + "downloadSeconds": 0.000191264 + }, + { + "connectionEstablishedSeconds": 0.065895003, + "uploadSeconds": 0.064422187, + "downloadSeconds": 0.000201304 + }, + { + "connectionEstablishedSeconds": 0.066959431, + "uploadSeconds": 0.06549081, + "downloadSeconds": 0.000201391 + }, + { + "connectionEstablishedSeconds": 0.065483631, + "uploadSeconds": 0.064122764, + "downloadSeconds": 0.000199658 + }, + { + "connectionEstablishedSeconds": 0.065869684, + "uploadSeconds": 0.064596755, + "downloadSeconds": 0.000252607 + }, + { + "connectionEstablishedSeconds": 0.065208161, + "uploadSeconds": 0.063724092, + "downloadSeconds": 0.000326259 + }, + { + "connectionEstablishedSeconds": 0.063874435, + "uploadSeconds": 0.062467287, + "downloadSeconds": 0.000189696 + }, + { + "connectionEstablishedSeconds": 0.062529457, + "uploadSeconds": 0.061205657, + "downloadSeconds": 0.000263333 + }, + { + "connectionEstablishedSeconds": 0.065449242, + "uploadSeconds": 0.064066552, + "downloadSeconds": 0.000276344 + }, + { + "connectionEstablishedSeconds": 0.064139182, + "uploadSeconds": 0.06264439, + "downloadSeconds": 0.000202631 + }, + { + "connectionEstablishedSeconds": 0.061921946, + "uploadSeconds": 0.060384157, + "downloadSeconds": 0.000226218 + }, + { + "connectionEstablishedSeconds": 0.066197629, + "uploadSeconds": 0.06483258, + "downloadSeconds": 0.000237098 + }, + { + "connectionEstablishedSeconds": 0.064473701, + "uploadSeconds": 0.063108909, + "downloadSeconds": 0.000208065 + }, + { + "connectionEstablishedSeconds": 0.06539491, + "uploadSeconds": 0.063917182, + "downloadSeconds": 0.00027215 + }, + { + "connectionEstablishedSeconds": 0.065071228, + "uploadSeconds": 0.063778824, + "downloadSeconds": 0.000238865 + }, + { + "connectionEstablishedSeconds": 0.064651975, + "uploadSeconds": 0.063283752, + "downloadSeconds": 0.000156891 + }, + { + "connectionEstablishedSeconds": 0.064982133, + "uploadSeconds": 0.063516095, + "downloadSeconds": 0.000200867 + }, + { + "connectionEstablishedSeconds": 0.062978826, + "uploadSeconds": 0.061688863, + "downloadSeconds": 0.000188278 + }, + { + "connectionEstablishedSeconds": 0.062295427, + "uploadSeconds": 0.060913366, + "downloadSeconds": 0.000255438 + }, + { + "connectionEstablishedSeconds": 0.064525031, + "uploadSeconds": 0.063123822, + "downloadSeconds": 0.000226088 + }, + { + "connectionEstablishedSeconds": 0.062325794, + "uploadSeconds": 0.061063754, + "downloadSeconds": 0.000218165 + }, + { + "connectionEstablishedSeconds": 0.064822543, + "uploadSeconds": 0.063304121, + "downloadSeconds": 0.000251781 + }, + { + "connectionEstablishedSeconds": 0.061440857, + "uploadSeconds": 0.059937803, + "downloadSeconds": 0.000269138 + }, + { + "connectionEstablishedSeconds": 0.065088219, + "uploadSeconds": 0.063709099, + "downloadSeconds": 0.00022092 + }, + { + "connectionEstablishedSeconds": 0.062920135, + "uploadSeconds": 0.061504746, + "downloadSeconds": 0.000207534 + }, + { + "connectionEstablishedSeconds": 0.065019389, + "uploadSeconds": 0.063622874, + "downloadSeconds": 0.000219459 + }, + { + "connectionEstablishedSeconds": 0.065977009, + "uploadSeconds": 0.064597124, + "downloadSeconds": 0.000250198 + }, + { + "connectionEstablishedSeconds": 0.062422976, + "uploadSeconds": 0.060975136, + "downloadSeconds": 0.000214674 + }, + { + "connectionEstablishedSeconds": 0.064642922, + "uploadSeconds": 0.063189755, + "downloadSeconds": 0.00029799 + }, + { + "connectionEstablishedSeconds": 0.065682327, + "uploadSeconds": 0.064287936, + "downloadSeconds": 0.000292814 + }, + { + "connectionEstablishedSeconds": 0.063473996, + "uploadSeconds": 0.062029369, + "downloadSeconds": 0.000231583 + }, + { + "connectionEstablishedSeconds": 0.063469822, + "uploadSeconds": 0.061954741, + "downloadSeconds": 0.000246131 + }, + { + "connectionEstablishedSeconds": 0.064851128, + "uploadSeconds": 0.063434178, + "downloadSeconds": 0.000213867 + }, + { + "connectionEstablishedSeconds": 0.062144428, + "uploadSeconds": 0.060606703, + "downloadSeconds": 0.000217533 + }, + { + "connectionEstablishedSeconds": 0.065986455, + "uploadSeconds": 0.064577873, + "downloadSeconds": 0.000206804 + }, + { + "connectionEstablishedSeconds": 0.064726192, + "uploadSeconds": 0.063332243, + "downloadSeconds": 0.000239735 + }, + { + "connectionEstablishedSeconds": 0.064632716, + "uploadSeconds": 0.063309348, + "downloadSeconds": 0.000265871 + }, + { + "connectionEstablishedSeconds": 0.066051432, + "uploadSeconds": 0.064603075, + "downloadSeconds": 0.000279868 + }, + { + "connectionEstablishedSeconds": 0.064319152, + "uploadSeconds": 0.062978197, + "downloadSeconds": 0.000267011 + }, + { + "connectionEstablishedSeconds": 0.065578875, + "uploadSeconds": 0.064210311, + "downloadSeconds": 0.000312327 + }, + { + "connectionEstablishedSeconds": 0.06249902, + "uploadSeconds": 0.061115234, + "downloadSeconds": 0.000208288 + }, + { + "connectionEstablishedSeconds": 0.064433692, + "uploadSeconds": 0.063065887, + "downloadSeconds": 0.000199075 + }, + { + "connectionEstablishedSeconds": 0.063908527, + "uploadSeconds": 0.062421652, + "downloadSeconds": 0.000192921 + }, + { + "connectionEstablishedSeconds": 0.065314004, + "uploadSeconds": 0.063971269, + "downloadSeconds": 0.000224887 + }, + { + "connectionEstablishedSeconds": 0.066661819, + "uploadSeconds": 0.065122878, + "downloadSeconds": 0.000303099 + }, + { + "connectionEstablishedSeconds": 0.062946918, + "uploadSeconds": 0.061544363, + "downloadSeconds": 0.000211652 + }, + { + "connectionEstablishedSeconds": 0.061860653, + "uploadSeconds": 0.060460049, + "downloadSeconds": 0.000195749 + }, + { + "connectionEstablishedSeconds": 0.065215099, + "uploadSeconds": 0.063931388, + "downloadSeconds": 0.000234829 + }, + { + "connectionEstablishedSeconds": 0.06453588, + "uploadSeconds": 0.06308244, + "downloadSeconds": 0.000227521 + }, + { + "connectionEstablishedSeconds": 0.06571602, + "uploadSeconds": 0.064277054, + "downloadSeconds": 0.000233697 + } + ], + "implementation": "rust-libp2p-quinn", + "version": "v0.52", + "transportStack": "quic-v1" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.185053145, + "downloadSeconds": 0.000042529 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.186749887, + "downloadSeconds": 0.000034788 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.177589981, + "downloadSeconds": 0.000034141 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.186222307, + "downloadSeconds": 0.000023625 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190720809, + "downloadSeconds": 0.000035193 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.193406136, + "downloadSeconds": 0.000035356 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.192963271, + "downloadSeconds": 0.00003445 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.195476643, + "downloadSeconds": 0.000036906 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.187020122, + "downloadSeconds": 0.000030902 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190978917, + "downloadSeconds": 0.000035416 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.18895168, + "downloadSeconds": 0.000030577 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.19280074, + "downloadSeconds": 0.000034784 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.194281643, + "downloadSeconds": 0.00003553 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.188287778, + "downloadSeconds": 0.000037338 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.195430346, + "downloadSeconds": 0.000037072 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.194384239, + "downloadSeconds": 0.000034565 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191915218, + "downloadSeconds": 0.000031388 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190814481, + "downloadSeconds": 0.000033409 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.188226132, + "downloadSeconds": 0.000031379 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.188944544, + "downloadSeconds": 0.000037297 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.192830669, + "downloadSeconds": 0.000031164 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191889106, + "downloadSeconds": 0.00003192 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.184959513, + "downloadSeconds": 0.000032864 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.19342802, + "downloadSeconds": 0.000032484 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.193531339, + "downloadSeconds": 0.000024694 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191605955, + "downloadSeconds": 0.000039426 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.188998617, + "downloadSeconds": 0.000031029 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.188507885, + "downloadSeconds": 0.00002276 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.196444295, + "downloadSeconds": 0.000025062 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.193288603, + "downloadSeconds": 0.000022276 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190196478, + "downloadSeconds": 0.000035304 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.19101996, + "downloadSeconds": 0.000031468 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.18771346, + "downloadSeconds": 0.000034425 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.192304997, + "downloadSeconds": 0.000033108 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.182804295, + "downloadSeconds": 0.000034492 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191296398, + "downloadSeconds": 0.000035555 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.183664688, + "downloadSeconds": 0.000034473 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.192932606, + "downloadSeconds": 0.000034101 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191965651, + "downloadSeconds": 0.00004048 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.193361465, + "downloadSeconds": 0.000037094 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.182595081, + "downloadSeconds": 0.000026521 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.193753749, + "downloadSeconds": 0.000031588 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191619186, + "downloadSeconds": 0.000034298 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.186816459, + "downloadSeconds": 0.00003413 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.19257261, + "downloadSeconds": 0.000033194 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.189630143, + "downloadSeconds": 0.000025527 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.182871119, + "downloadSeconds": 0.000035417 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.187070763, + "downloadSeconds": 0.000039682 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.182966939, + "downloadSeconds": 0.000034868 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.19029279, + "downloadSeconds": 0.000032821 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.189312151, + "downloadSeconds": 0.000023169 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191229498, + "downloadSeconds": 0.000030995 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.18908621, + "downloadSeconds": 0.000024805 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190969054, + "downloadSeconds": 0.000035044 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.182805951, + "downloadSeconds": 0.000035045 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.184211676, + "downloadSeconds": 0.00003118 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190939334, + "downloadSeconds": 0.00003687 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190777691, + "downloadSeconds": 0.000035732 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.187917115, + "downloadSeconds": 0.000034899 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190072014, + "downloadSeconds": 0.000039331 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191356984, + "downloadSeconds": 0.000036338 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191103454, + "downloadSeconds": 0.000035841 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.176751719, + "downloadSeconds": 0.000034908 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.19357032, + "downloadSeconds": 0.000027657 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.185481567, + "downloadSeconds": 0.000034332 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190641535, + "downloadSeconds": 0.000033533 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191202351, + "downloadSeconds": 0.000034829 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.186108976, + "downloadSeconds": 0.000023441 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191705913, + "downloadSeconds": 0.000023135 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.186858248, + "downloadSeconds": 0.000033264 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.186761576, + "downloadSeconds": 0.000037166 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191750803, + "downloadSeconds": 0.000025621 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.186545117, + "downloadSeconds": 0.000035984 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.182424793, + "downloadSeconds": 0.00003531 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.19095818, + "downloadSeconds": 0.00003541 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.193940523, + "downloadSeconds": 0.000034823 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.19126552, + "downloadSeconds": 0.000030258 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.192959396, + "downloadSeconds": 0.00003533 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191230252, + "downloadSeconds": 0.00003462 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191606432, + "downloadSeconds": 0.000035102 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190014888, + "downloadSeconds": 0.000029117 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190648226, + "downloadSeconds": 0.000025677 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.189448378, + "downloadSeconds": 0.000033677 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.195077934, + "downloadSeconds": 0.000034017 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.181657919, + "downloadSeconds": 0.000034153 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.189491676, + "downloadSeconds": 0.000027625 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.191770687, + "downloadSeconds": 0.000031336 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.189495974, + "downloadSeconds": 0.000034939 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190744158, + "downloadSeconds": 0.000036604 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.188132312, + "downloadSeconds": 0.000034402 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.177152609, + "downloadSeconds": 0.000035554 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.180191044, + "downloadSeconds": 0.000027139 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.188539768, + "downloadSeconds": 0.000035181 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.188009218, + "downloadSeconds": 0.000028091 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.190402823, + "downloadSeconds": 0.000034882 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.176183458, + "downloadSeconds": 0.000027937 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.185653132, + "downloadSeconds": 0.000035795 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.19374182, + "downloadSeconds": 0.000035146 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.180572218, + "downloadSeconds": 0.00003475 + }, + { + "connectionEstablishedSeconds": 0, + "uploadSeconds": 0.192778229, + "downloadSeconds": 0.00002868 + } + ], + "implementation": "https", + "version": "v0.1", + "transportStack": "tcp" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.255564771, + "uploadSeconds": 0.000058962, + "downloadSeconds": 0.124655922 + }, + { + "connectionEstablishedSeconds": 0.240628743, + "uploadSeconds": 0.000031327, + "downloadSeconds": 0.059283787 + }, + { + "connectionEstablishedSeconds": 0.246060026, + "uploadSeconds": 0.000032811, + "downloadSeconds": 0.120545382 + }, + { + "connectionEstablishedSeconds": 0.257898273, + "uploadSeconds": 0.000061307, + "downloadSeconds": 0.063628717 + }, + { + "connectionEstablishedSeconds": 0.256797484, + "uploadSeconds": 0.000015293, + "downloadSeconds": 0.126097157 + }, + { + "connectionEstablishedSeconds": 0.257655875, + "uploadSeconds": 0.000031895, + "downloadSeconds": 0.063533893 + }, + { + "connectionEstablishedSeconds": 0.256532527, + "uploadSeconds": 0.000034072, + "downloadSeconds": 0.063442454 + }, + { + "connectionEstablishedSeconds": 0.256347155, + "uploadSeconds": 0.000047138, + "downloadSeconds": 0.125774714 + }, + { + "connectionEstablishedSeconds": 0.259335178, + "uploadSeconds": 0.000049483, + "downloadSeconds": 0.063913947 + }, + { + "connectionEstablishedSeconds": 0.233717447, + "uploadSeconds": 0.00002658, + "downloadSeconds": 0.058006432 + }, + { + "connectionEstablishedSeconds": 0.258911012, + "uploadSeconds": 0.000050582, + "downloadSeconds": 0.126864314 + }, + { + "connectionEstablishedSeconds": 0.256092791, + "uploadSeconds": 0.00005145, + "downloadSeconds": 0.063076668 + }, + { + "connectionEstablishedSeconds": 0.253528586, + "uploadSeconds": 0.000035863, + "downloadSeconds": 0.12516235 + }, + { + "connectionEstablishedSeconds": 0.250931815, + "uploadSeconds": 0.000048435, + "downloadSeconds": 0.061765651 + }, + { + "connectionEstablishedSeconds": 0.258632992, + "uploadSeconds": 0.000051462, + "downloadSeconds": 0.126959835 + }, + { + "connectionEstablishedSeconds": 0.257017873, + "uploadSeconds": 0.000049839, + "downloadSeconds": 0.126077058 + }, + { + "connectionEstablishedSeconds": 0.259292194, + "uploadSeconds": 0.000050133, + "downloadSeconds": 0.127185628 + }, + { + "connectionEstablishedSeconds": 0.240883048, + "uploadSeconds": 0.000029202, + "downloadSeconds": 0.117895391 + }, + { + "connectionEstablishedSeconds": 0.238878753, + "uploadSeconds": 0.000055267, + "downloadSeconds": 0.116871413 + }, + { + "connectionEstablishedSeconds": 0.252530614, + "uploadSeconds": 0.000053341, + "downloadSeconds": 0.124574708 + }, + { + "connectionEstablishedSeconds": 0.248543388, + "uploadSeconds": 0.000035107, + "downloadSeconds": 0.061000007 + }, + { + "connectionEstablishedSeconds": 0.252642228, + "uploadSeconds": 0.000022627, + "downloadSeconds": 0.062691633 + }, + { + "connectionEstablishedSeconds": 0.244578188, + "uploadSeconds": 0.000031248, + "downloadSeconds": 0.120452768 + }, + { + "connectionEstablishedSeconds": 0.255823597, + "uploadSeconds": 0.000045341, + "downloadSeconds": 0.125369052 + }, + { + "connectionEstablishedSeconds": 0.255313133, + "uploadSeconds": 0.000054953, + "downloadSeconds": 0.123889423 + }, + { + "connectionEstablishedSeconds": 0.25583746, + "uploadSeconds": 0.000049329, + "downloadSeconds": 0.06339297 + }, + { + "connectionEstablishedSeconds": 0.256002126, + "uploadSeconds": 0.000057044, + "downloadSeconds": 0.126471927 + }, + { + "connectionEstablishedSeconds": 0.252109507, + "uploadSeconds": 0.00005592, + "downloadSeconds": 0.062519518 + }, + { + "connectionEstablishedSeconds": 0.251913238, + "uploadSeconds": 0.000028096, + "downloadSeconds": 0.123525763 + }, + { + "connectionEstablishedSeconds": 0.254943314, + "uploadSeconds": 0.000027106, + "downloadSeconds": 0.12496839 + }, + { + "connectionEstablishedSeconds": 0.247363092, + "uploadSeconds": 0.000046956, + "downloadSeconds": 0.122142147 + }, + { + "connectionEstablishedSeconds": 0.252327697, + "uploadSeconds": 0.000032412, + "downloadSeconds": 0.062109734 + }, + { + "connectionEstablishedSeconds": 0.25467206, + "uploadSeconds": 0.000051041, + "downloadSeconds": 0.062652737 + }, + { + "connectionEstablishedSeconds": 0.252011661, + "uploadSeconds": 0.000028809, + "downloadSeconds": 0.062551701 + }, + { + "connectionEstablishedSeconds": 0.256222493, + "uploadSeconds": 0.000049471, + "downloadSeconds": 0.063473614 + }, + { + "connectionEstablishedSeconds": 0.249629093, + "uploadSeconds": 0.000015106, + "downloadSeconds": 0.061868423 + }, + { + "connectionEstablishedSeconds": 0.256758085, + "uploadSeconds": 0.000046705, + "downloadSeconds": 0.126453964 + }, + { + "connectionEstablishedSeconds": 0.246384913, + "uploadSeconds": 0.000046164, + "downloadSeconds": 0.061167599 + }, + { + "connectionEstablishedSeconds": 0.253809944, + "uploadSeconds": 0.000046954, + "downloadSeconds": 0.06251466 + }, + { + "connectionEstablishedSeconds": 0.252680571, + "uploadSeconds": 0.00004862, + "downloadSeconds": 0.124903987 + }, + { + "connectionEstablishedSeconds": 0.260555268, + "uploadSeconds": 0.000024659, + "downloadSeconds": 0.06422256 + }, + { + "connectionEstablishedSeconds": 0.253972966, + "uploadSeconds": 0.000030325, + "downloadSeconds": 0.062968215 + }, + { + "connectionEstablishedSeconds": 0.251677426, + "uploadSeconds": 0.000058083, + "downloadSeconds": 0.123469886 + }, + { + "connectionEstablishedSeconds": 0.255464321, + "uploadSeconds": 0.000030361, + "downloadSeconds": 0.063452473 + }, + { + "connectionEstablishedSeconds": 0.257554731, + "uploadSeconds": 0.000047156, + "downloadSeconds": 0.126325713 + }, + { + "connectionEstablishedSeconds": 0.254332788, + "uploadSeconds": 0.000053547, + "downloadSeconds": 0.062627469 + }, + { + "connectionEstablishedSeconds": 0.24463752, + "uploadSeconds": 0.000029926, + "downloadSeconds": 0.060626808 + }, + { + "connectionEstablishedSeconds": 0.251500685, + "uploadSeconds": 0.000034964, + "downloadSeconds": 0.062436547 + }, + { + "connectionEstablishedSeconds": 0.248732914, + "uploadSeconds": 0.000031966, + "downloadSeconds": 0.061784867 + }, + { + "connectionEstablishedSeconds": 0.254063006, + "uploadSeconds": 0.000060283, + "downloadSeconds": 0.124453353 + }, + { + "connectionEstablishedSeconds": 0.254678345, + "uploadSeconds": 0.000029515, + "downloadSeconds": 0.063197481 + }, + { + "connectionEstablishedSeconds": 0.256487616, + "uploadSeconds": 0.000028327, + "downloadSeconds": 0.063529376 + }, + { + "connectionEstablishedSeconds": 0.254123118, + "uploadSeconds": 0.000030113, + "downloadSeconds": 0.124538531 + }, + { + "connectionEstablishedSeconds": 0.25159968, + "uploadSeconds": 0.000030301, + "downloadSeconds": 0.061926504 + }, + { + "connectionEstablishedSeconds": 0.25943308, + "uploadSeconds": 0.00002747, + "downloadSeconds": 0.064337808 + }, + { + "connectionEstablishedSeconds": 0.256212381, + "uploadSeconds": 0.000051275, + "downloadSeconds": 0.063474669 + }, + { + "connectionEstablishedSeconds": 0.253068728, + "uploadSeconds": 0.000031105, + "downloadSeconds": 0.062774459 + }, + { + "connectionEstablishedSeconds": 0.25281207, + "uploadSeconds": 0.000032473, + "downloadSeconds": 0.062257546 + }, + { + "connectionEstablishedSeconds": 0.245992583, + "uploadSeconds": 0.000047141, + "downloadSeconds": 0.060600227 + }, + { + "connectionEstablishedSeconds": 0.248401528, + "uploadSeconds": 0.000051407, + "downloadSeconds": 0.061628242 + }, + { + "connectionEstablishedSeconds": 0.254361874, + "uploadSeconds": 0.000032809, + "downloadSeconds": 0.063058271 + }, + { + "connectionEstablishedSeconds": 0.25985272, + "uploadSeconds": 0.000048011, + "downloadSeconds": 0.064490936 + }, + { + "connectionEstablishedSeconds": 0.251897611, + "uploadSeconds": 0.000045946, + "downloadSeconds": 0.062066764 + }, + { + "connectionEstablishedSeconds": 0.248299434, + "uploadSeconds": 0.000042741, + "downloadSeconds": 0.061555421 + }, + { + "connectionEstablishedSeconds": 0.240883312, + "uploadSeconds": 0.000043219, + "downloadSeconds": 0.117887156 + }, + { + "connectionEstablishedSeconds": 0.253741863, + "uploadSeconds": 0.00004853, + "downloadSeconds": 0.125259598 + }, + { + "connectionEstablishedSeconds": 0.259493548, + "uploadSeconds": 0.000050997, + "downloadSeconds": 0.064455196 + }, + { + "connectionEstablishedSeconds": 0.257220143, + "uploadSeconds": 0.000030118, + "downloadSeconds": 0.063426681 + }, + { + "connectionEstablishedSeconds": 0.246216063, + "uploadSeconds": 0.000028691, + "downloadSeconds": 0.060675077 + }, + { + "connectionEstablishedSeconds": 0.246821242, + "uploadSeconds": 0.000028037, + "downloadSeconds": 0.061043753 + }, + { + "connectionEstablishedSeconds": 0.249273925, + "uploadSeconds": 0.000046106, + "downloadSeconds": 0.061133894 + }, + { + "connectionEstablishedSeconds": 0.246100615, + "uploadSeconds": 0.000027492, + "downloadSeconds": 0.060683507 + }, + { + "connectionEstablishedSeconds": 0.254584769, + "uploadSeconds": 0.000029223, + "downloadSeconds": 0.063075631 + }, + { + "connectionEstablishedSeconds": 0.251221668, + "uploadSeconds": 0.000019521, + "downloadSeconds": 0.061797471 + }, + { + "connectionEstablishedSeconds": 0.261594006, + "uploadSeconds": 0.000047526, + "downloadSeconds": 0.064500959 + }, + { + "connectionEstablishedSeconds": 0.255117473, + "uploadSeconds": 0.000034003, + "downloadSeconds": 0.062865607 + }, + { + "connectionEstablishedSeconds": 0.259363593, + "uploadSeconds": 0.000025603, + "downloadSeconds": 0.064428592 + }, + { + "connectionEstablishedSeconds": 0.256991666, + "uploadSeconds": 0.000038121, + "downloadSeconds": 0.126587719 + }, + { + "connectionEstablishedSeconds": 0.256222985, + "uploadSeconds": 0.000034028, + "downloadSeconds": 0.063668828 + }, + { + "connectionEstablishedSeconds": 0.246441053, + "uploadSeconds": 0.000054022, + "downloadSeconds": 0.060693367 + }, + { + "connectionEstablishedSeconds": 0.250188094, + "uploadSeconds": 0.000047133, + "downloadSeconds": 0.122659442 + }, + { + "connectionEstablishedSeconds": 0.250006049, + "uploadSeconds": 0.000029392, + "downloadSeconds": 0.061585645 + }, + { + "connectionEstablishedSeconds": 0.257920889, + "uploadSeconds": 0.000032591, + "downloadSeconds": 0.063517178 + }, + { + "connectionEstablishedSeconds": 0.250465138, + "uploadSeconds": 0.000029506, + "downloadSeconds": 0.061617335 + }, + { + "connectionEstablishedSeconds": 0.245868712, + "uploadSeconds": 0.000027911, + "downloadSeconds": 0.060637803 + }, + { + "connectionEstablishedSeconds": 0.25524009, + "uploadSeconds": 0.000035514, + "downloadSeconds": 0.125044365 + }, + { + "connectionEstablishedSeconds": 0.261456952, + "uploadSeconds": 0.00005156, + "downloadSeconds": 0.064948587 + }, + { + "connectionEstablishedSeconds": 0.238494124, + "uploadSeconds": 0.000055281, + "downloadSeconds": 0.117753391 + }, + { + "connectionEstablishedSeconds": 0.254645427, + "uploadSeconds": 0.000029023, + "downloadSeconds": 0.063098551 + }, + { + "connectionEstablishedSeconds": 0.260883166, + "uploadSeconds": 0.000030938, + "downloadSeconds": 0.06422298 + }, + { + "connectionEstablishedSeconds": 0.245937147, + "uploadSeconds": 0.000052181, + "downloadSeconds": 0.120588066 + }, + { + "connectionEstablishedSeconds": 0.246092408, + "uploadSeconds": 0.000043654, + "downloadSeconds": 0.060575934 + }, + { + "connectionEstablishedSeconds": 0.252276353, + "uploadSeconds": 0.000052674, + "downloadSeconds": 0.062225078 + }, + { + "connectionEstablishedSeconds": 0.254035258, + "uploadSeconds": 0.000029773, + "downloadSeconds": 0.063026433 + }, + { + "connectionEstablishedSeconds": 0.244492974, + "uploadSeconds": 0.000048903, + "downloadSeconds": 0.060129062 + }, + { + "connectionEstablishedSeconds": 0.248731287, + "uploadSeconds": 0.000054764, + "downloadSeconds": 0.061207054 + }, + { + "connectionEstablishedSeconds": 0.25220207, + "uploadSeconds": 0.00002132, + "downloadSeconds": 0.062101733 + }, + { + "connectionEstablishedSeconds": 0.259540618, + "uploadSeconds": 0.000029737, + "downloadSeconds": 0.06402198 + }, + { + "connectionEstablishedSeconds": 0.259530792, + "uploadSeconds": 0.000036374, + "downloadSeconds": 0.064350389 + }, + { + "connectionEstablishedSeconds": 0.256305199, + "uploadSeconds": 0.000032371, + "downloadSeconds": 0.063607602 + } + ], + "implementation": "go-libp2p", + "version": "v0.27", + "transportStack": "tcp" + }, + { + "result": [ + { + "connectionEstablishedSeconds": 0.127014114, + "uploadSeconds": 0.0000599, + "downloadSeconds": 0.061673031 + }, + { + "connectionEstablishedSeconds": 0.131064058, + "uploadSeconds": 0.000050908, + "downloadSeconds": 0.062537019 + }, + { + "connectionEstablishedSeconds": 0.135060958, + "uploadSeconds": 0.000017065, + "downloadSeconds": 0.064952383 + }, + { + "connectionEstablishedSeconds": 0.130469846, + "uploadSeconds": 0.000049737, + "downloadSeconds": 0.063554424 + }, + { + "connectionEstablishedSeconds": 0.131299513, + "uploadSeconds": 0.000026493, + "downloadSeconds": 0.063977902 + }, + { + "connectionEstablishedSeconds": 0.130389784, + "uploadSeconds": 0.000040725, + "downloadSeconds": 0.063581044 + }, + { + "connectionEstablishedSeconds": 0.129796216, + "uploadSeconds": 0.000051097, + "downloadSeconds": 0.06321556 + }, + { + "connectionEstablishedSeconds": 0.124704159, + "uploadSeconds": 0.000049439, + "downloadSeconds": 0.059809119 + }, + { + "connectionEstablishedSeconds": 0.132066235, + "uploadSeconds": 0.000055003, + "downloadSeconds": 0.063481356 + }, + { + "connectionEstablishedSeconds": 0.131711288, + "uploadSeconds": 0.000027967, + "downloadSeconds": 0.06333515 + }, + { + "connectionEstablishedSeconds": 0.127610138, + "uploadSeconds": 0.000027948, + "downloadSeconds": 0.061228341 + }, + { + "connectionEstablishedSeconds": 0.126055326, + "uploadSeconds": 0.000021998, + "downloadSeconds": 0.06142716 + }, + { + "connectionEstablishedSeconds": 0.123515801, + "uploadSeconds": 0.000009845, + "downloadSeconds": 0.060132657 + }, + { + "connectionEstablishedSeconds": 0.124995443, + "uploadSeconds": 0.000030619, + "downloadSeconds": 0.060910578 + }, + { + "connectionEstablishedSeconds": 0.131803299, + "uploadSeconds": 0.00004698, + "downloadSeconds": 0.064321877 + }, + { + "connectionEstablishedSeconds": 0.132100006, + "uploadSeconds": 0.000031614, + "downloadSeconds": 0.064446827 + }, + { + "connectionEstablishedSeconds": 0.131765427, + "uploadSeconds": 0.000031545, + "downloadSeconds": 0.064305327 + }, + { + "connectionEstablishedSeconds": 0.131987682, + "uploadSeconds": 0.000047611, + "downloadSeconds": 0.063545341 + }, + { + "connectionEstablishedSeconds": 0.13084145, + "uploadSeconds": 0.000031347, + "downloadSeconds": 0.064606754 + }, + { + "connectionEstablishedSeconds": 0.126397034, + "uploadSeconds": 0.000055546, + "downloadSeconds": 0.060616997 + }, + { + "connectionEstablishedSeconds": 0.133111555, + "uploadSeconds": 0.000027453, + "downloadSeconds": 0.064002229 + }, + { + "connectionEstablishedSeconds": 0.130509598, + "uploadSeconds": 0.000024595, + "downloadSeconds": 0.063286999 + }, + { + "connectionEstablishedSeconds": 0.124489373, + "uploadSeconds": 0.000020358, + "downloadSeconds": 0.060647534 + }, + { + "connectionEstablishedSeconds": 0.130411284, + "uploadSeconds": 0.000032773, + "downloadSeconds": 0.063491236 + }, + { + "connectionEstablishedSeconds": 0.128244464, + "uploadSeconds": 0.000031167, + "downloadSeconds": 0.061581905 + }, + { + "connectionEstablishedSeconds": 0.134535364, + "uploadSeconds": 0.0000261, + "downloadSeconds": 0.064805122 + }, + { + "connectionEstablishedSeconds": 0.13128741, + "uploadSeconds": 0.000050089, + "downloadSeconds": 0.063958387 + }, + { + "connectionEstablishedSeconds": 0.131984212, + "uploadSeconds": 0.000048742, + "downloadSeconds": 0.063452836 + }, + { + "connectionEstablishedSeconds": 0.130849195, + "uploadSeconds": 0.000027516, + "downloadSeconds": 0.062873869 + }, + { + "connectionEstablishedSeconds": 0.132367723, + "uploadSeconds": 0.000028605, + "downloadSeconds": 0.063657122 + }, + { + "connectionEstablishedSeconds": 0.131658661, + "uploadSeconds": 0.000033672, + "downloadSeconds": 0.064163204 + }, + { + "connectionEstablishedSeconds": 0.12824671, + "uploadSeconds": 0.000054562, + "downloadSeconds": 0.061647757 + }, + { + "connectionEstablishedSeconds": 0.126312532, + "uploadSeconds": 0.000048885, + "downloadSeconds": 0.0607011 + }, + { + "connectionEstablishedSeconds": 0.131843825, + "uploadSeconds": 0.000051974, + "downloadSeconds": 0.063365075 + }, + { + "connectionEstablishedSeconds": 0.134680989, + "uploadSeconds": 0.00005269, + "downloadSeconds": 0.064523439 + }, + { + "connectionEstablishedSeconds": 0.131149962, + "uploadSeconds": 0.00002484, + "downloadSeconds": 0.063040136 + }, + { + "connectionEstablishedSeconds": 0.131163906, + "uploadSeconds": 0.00002525, + "downloadSeconds": 0.062826936 + }, + { + "connectionEstablishedSeconds": 0.131417191, + "uploadSeconds": 0.000033475, + "downloadSeconds": 0.063211569 + }, + { + "connectionEstablishedSeconds": 0.129321818, + "uploadSeconds": 0.000021761, + "downloadSeconds": 0.062047175 + }, + { + "connectionEstablishedSeconds": 0.133113708, + "uploadSeconds": 0.000042621, + "downloadSeconds": 0.064113658 + }, + { + "connectionEstablishedSeconds": 0.13301228, + "uploadSeconds": 0.000047067, + "downloadSeconds": 0.063916395 + }, + { + "connectionEstablishedSeconds": 0.12935223, + "uploadSeconds": 0.000055131, + "downloadSeconds": 0.06210632 + }, + { + "connectionEstablishedSeconds": 0.127551422, + "uploadSeconds": 0.000028851, + "downloadSeconds": 0.062295024 + }, + { + "connectionEstablishedSeconds": 0.126331834, + "uploadSeconds": 0.000045101, + "downloadSeconds": 0.061509655 + }, + { + "connectionEstablishedSeconds": 0.131532682, + "uploadSeconds": 0.000052301, + "downloadSeconds": 0.062588573 + }, + { + "connectionEstablishedSeconds": 0.127919054, + "uploadSeconds": 0.000026387, + "downloadSeconds": 0.062280304 + }, + { + "connectionEstablishedSeconds": 0.129176435, + "uploadSeconds": 0.000052084, + "downloadSeconds": 0.062872466 + }, + { + "connectionEstablishedSeconds": 0.128833594, + "uploadSeconds": 0.000031408, + "downloadSeconds": 0.06280984 + }, + { + "connectionEstablishedSeconds": 0.131885794, + "uploadSeconds": 0.000048593, + "downloadSeconds": 0.063311591 + }, + { + "connectionEstablishedSeconds": 0.127375808, + "uploadSeconds": 0.000049019, + "downloadSeconds": 0.061146478 + }, + { + "connectionEstablishedSeconds": 0.12153029, + "uploadSeconds": 0.0000186, + "downloadSeconds": 0.059066564 + }, + { + "connectionEstablishedSeconds": 0.126343007, + "uploadSeconds": 0.000023853, + "downloadSeconds": 0.061518531 + }, + { + "connectionEstablishedSeconds": 0.130463081, + "uploadSeconds": 0.000024353, + "downloadSeconds": 0.062718483 + }, + { + "connectionEstablishedSeconds": 0.130155148, + "uploadSeconds": 0.00003375, + "downloadSeconds": 0.062584006 + }, + { + "connectionEstablishedSeconds": 0.127377421, + "uploadSeconds": 0.000050033, + "downloadSeconds": 0.061144804 + }, + { + "connectionEstablishedSeconds": 0.132263716, + "uploadSeconds": 0.000053572, + "downloadSeconds": 0.064441815 + }, + { + "connectionEstablishedSeconds": 0.130906676, + "uploadSeconds": 0.000050526, + "downloadSeconds": 0.062900437 + }, + { + "connectionEstablishedSeconds": 0.132053669, + "uploadSeconds": 0.000020333, + "downloadSeconds": 0.063625907 + }, + { + "connectionEstablishedSeconds": 0.126343969, + "uploadSeconds": 0.000048602, + "downloadSeconds": 0.061562747 + }, + { + "connectionEstablishedSeconds": 0.13059195, + "uploadSeconds": 0.000038032, + "downloadSeconds": 0.06359932 + }, + { + "connectionEstablishedSeconds": 0.125306765, + "uploadSeconds": 0.000025331, + "downloadSeconds": 0.06024974 + }, + { + "connectionEstablishedSeconds": 0.131732246, + "uploadSeconds": 0.000054432, + "downloadSeconds": 0.063232591 + }, + { + "connectionEstablishedSeconds": 0.135945769, + "uploadSeconds": 0.000030859, + "downloadSeconds": 0.064563121 + }, + { + "connectionEstablishedSeconds": 0.130211557, + "uploadSeconds": 0.000045455, + "downloadSeconds": 0.063471773 + }, + { + "connectionEstablishedSeconds": 0.131806838, + "uploadSeconds": 0.00004764, + "downloadSeconds": 0.063356395 + }, + { + "connectionEstablishedSeconds": 0.126735568, + "uploadSeconds": 0.000050096, + "downloadSeconds": 0.060697868 + }, + { + "connectionEstablishedSeconds": 0.131880335, + "uploadSeconds": 0.000049507, + "downloadSeconds": 0.064224812 + }, + { + "connectionEstablishedSeconds": 0.128441843, + "uploadSeconds": 0.000047943, + "downloadSeconds": 0.06163169 + }, + { + "connectionEstablishedSeconds": 0.132509961, + "uploadSeconds": 0.000028055, + "downloadSeconds": 0.06452755 + }, + { + "connectionEstablishedSeconds": 0.125300073, + "uploadSeconds": 0.000028357, + "downloadSeconds": 0.060982066 + }, + { + "connectionEstablishedSeconds": 0.128716768, + "uploadSeconds": 0.00004992, + "downloadSeconds": 0.061736618 + }, + { + "connectionEstablishedSeconds": 0.129722375, + "uploadSeconds": 0.000027386, + "downloadSeconds": 0.063147505 + }, + { + "connectionEstablishedSeconds": 0.132837561, + "uploadSeconds": 0.000049241, + "downloadSeconds": 0.063550104 + }, + { + "connectionEstablishedSeconds": 0.133588995, + "uploadSeconds": 0.00003146, + "downloadSeconds": 0.065113178 + }, + { + "connectionEstablishedSeconds": 0.125069476, + "uploadSeconds": 0.000043879, + "downloadSeconds": 0.060026593 + }, + { + "connectionEstablishedSeconds": 0.128337827, + "uploadSeconds": 0.000030024, + "downloadSeconds": 0.062603579 + }, + { + "connectionEstablishedSeconds": 0.129434388, + "uploadSeconds": 0.00002842, + "downloadSeconds": 0.062977058 + }, + { + "connectionEstablishedSeconds": 0.131637561, + "uploadSeconds": 0.000052806, + "downloadSeconds": 0.064200689 + }, + { + "connectionEstablishedSeconds": 0.128330334, + "uploadSeconds": 0.000027132, + "downloadSeconds": 0.061569876 + }, + { + "connectionEstablishedSeconds": 0.130216018, + "uploadSeconds": 0.000029266, + "downloadSeconds": 0.063386904 + }, + { + "connectionEstablishedSeconds": 0.127663856, + "uploadSeconds": 0.000025337, + "downloadSeconds": 0.062249422 + }, + { + "connectionEstablishedSeconds": 0.130767875, + "uploadSeconds": 0.000048326, + "downloadSeconds": 0.062960272 + }, + { + "connectionEstablishedSeconds": 0.13139533, + "uploadSeconds": 0.000045884, + "downloadSeconds": 0.063091639 + }, + { + "connectionEstablishedSeconds": 0.132284539, + "uploadSeconds": 0.000046307, + "downloadSeconds": 0.064433543 + }, + { + "connectionEstablishedSeconds": 0.128954497, + "uploadSeconds": 0.000046395, + "downloadSeconds": 0.061946524 + }, + { + "connectionEstablishedSeconds": 0.13195501, + "uploadSeconds": 0.000028593, + "downloadSeconds": 0.064321822 + }, + { + "connectionEstablishedSeconds": 0.129169046, + "uploadSeconds": 0.000051974, + "downloadSeconds": 0.062097421 + }, + { + "connectionEstablishedSeconds": 0.131516378, + "uploadSeconds": 0.000018617, + "downloadSeconds": 0.064170442 + }, + { + "connectionEstablishedSeconds": 0.126709992, + "uploadSeconds": 0.000047803, + "downloadSeconds": 0.061721005 + }, + { + "connectionEstablishedSeconds": 0.134914003, + "uploadSeconds": 0.000027086, + "downloadSeconds": 0.064980719 + }, + { + "connectionEstablishedSeconds": 0.130706472, + "uploadSeconds": 0.000028876, + "downloadSeconds": 0.062787784 + }, + { + "connectionEstablishedSeconds": 0.132152472, + "uploadSeconds": 0.000058598, + "downloadSeconds": 0.063518087 + }, + { + "connectionEstablishedSeconds": 0.132736855, + "uploadSeconds": 0.000040063, + "downloadSeconds": 0.06371304 + }, + { + "connectionEstablishedSeconds": 0.125053099, + "uploadSeconds": 0.000049355, + "downloadSeconds": 0.060821904 + }, + { + "connectionEstablishedSeconds": 0.130546318, + "uploadSeconds": 0.000049924, + "downloadSeconds": 0.062680299 + }, + { + "connectionEstablishedSeconds": 0.119719828, + "uploadSeconds": 0.0000306, + "downloadSeconds": 0.058134544 + }, + { + "connectionEstablishedSeconds": 0.126296963, + "uploadSeconds": 0.000025112, + "downloadSeconds": 0.060554586 + }, + { + "connectionEstablishedSeconds": 0.128162133, + "uploadSeconds": 0.000048249, + "downloadSeconds": 0.061574806 + }, + { + "connectionEstablishedSeconds": 0.13229105, + "uploadSeconds": 0.00005374, + "downloadSeconds": 0.063552066 + }, + { + "connectionEstablishedSeconds": 0.129765991, + "uploadSeconds": 0.000046291, + "downloadSeconds": 0.063203821 + } + ], + "implementation": "go-libp2p", + "version": "v0.27", + "transportStack": "quic-v1" + } + ], + "parameters": { + "uploadBytes": 1, + "downloadBytes": 1 + } + } + ], + "pings": { + "unit": "s", + "results": [ + 0.0615, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.0615, + 0.061399999999999996, + 0.0616, + 0.0615, + 0.061399999999999996, + 0.061799999999999994, + 0.0615, + 0.061399999999999996, + 0.0615, + 0.061399999999999996, + 0.061399999999999996, + 0.0616, + 0.061399999999999996, + 0.061399999999999996, + 0.0616, + 0.061399999999999996, + 0.0615, + 0.062, + 0.061399999999999996, + 0.0625, + 0.061399999999999996, + 0.061399999999999996, + 0.0616, + 0.061799999999999994, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.062200000000000005, + 0.061399999999999996, + 0.0615, + 0.0627, + 0.062200000000000005, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.0615, + 0.061399999999999996, + 0.0615, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.0619, + 0.061399999999999996, + 0.061399999999999996, + 0.0615, + 0.061399999999999996, + 0.0615, + 0.061799999999999994, + 0.0615, + 0.061399999999999996, + 0.062299999999999994, + 0.061399999999999996, + 0.061700000000000005, + 0.061399999999999996, + 0.062, + 0.0616, + 0.061399999999999996, + 0.061399999999999996, + 0.0615, + 0.061399999999999996, + 0.0616, + 0.0615, + 0.061399999999999996, + 0.0616, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.0615, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996, + 0.061399999999999996 + ] + }, + "iperf": { + "unit": "bit/s", + "results": [ + 3330000000, + 3340000000, + 3330000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3330000000, + 3330000000, + 3330000000, + 3330000000, + 3330000000, + 3330000000, + 3340000000, + 3330000000, + 3340000000, + 3340000000, + 3330000000, + 3330000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3340000000, + 3300000000, + 3290000000, + 3280000000, + 3280000000, + 3280000000, + 3320000000, + 3290000000, + 3350000000, + 3350000000, + 3350000000, + 3350000000, + 3350000000, + 3350000000, + 3350000000, + 3350000000, + 3350000000, + 3350000000, + 3350000000, + 3350000000, + 3350000000, + 3330000000, + 2830000000 + ] + } +} \ No newline at end of file diff --git a/perf/runner/package-lock.json b/perf/runner/package-lock.json new file mode 100644 index 000000000..20894f50c --- /dev/null +++ b/perf/runner/package-lock.json @@ -0,0 +1,650 @@ +{ + "name": "runner", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "runner", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "yargs": "^17.7.1" + }, + "devDependencies": { + "@types/node": "^18.15.11", + "@types/yargs": "^17.0.24", + "ts-node": "^10.9.1", + "typescript": "^5.0.4" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + } + }, + "dependencies": { + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "@types/node": { + "version": "18.15.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + }, + "typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + } + } +} diff --git a/perf/runner/package.json b/perf/runner/package.json new file mode 100644 index 000000000..bc320c2ec --- /dev/null +++ b/perf/runner/package.json @@ -0,0 +1,20 @@ +{ + "name": "runner", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "ts-node src/index.ts" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "@types/node": "^18.15.11", + "@types/yargs": "^17.0.24", + "ts-node": "^10.9.1", + "typescript": "^5.0.4" + }, + "dependencies": { + "yargs": "^17.7.1" + } +} diff --git a/perf/runner/src/benchmark-result-type.ts b/perf/runner/src/benchmark-result-type.ts new file mode 100644 index 000000000..34d1088ef --- /dev/null +++ b/perf/runner/src/benchmark-result-type.ts @@ -0,0 +1,47 @@ +export type BenchmarkResults = { + benchmarks: Benchmark[], + pings: PingResults, + iperf: IperfResults, + // For referencing this schema in JSON + "$schema"?: string +}; + +export type PingResults = { + unit: "s", + results: number[] +}; + +export type IperfResults = { + unit: "bit/s", + results: number[] +}; + +export type Benchmark = { + name: string, + unit: "bit/s" | "s", + results: Result[], + parameters: +} + +export type Parameters = { + uploadBytes: number, + downloadBytes: number, +} + +export type Result = { + implementation: string, + transportStack: string, + version: string + result: ResultValue[], +}; + +export type ResultValue = { + connectionEstablishedSeconds: number, + uploadSeconds: number, + downloadSeconds: number, +}; + +export type Comparison = { + name: string, + result: number, +} diff --git a/perf/runner/src/index.ts b/perf/runner/src/index.ts new file mode 100644 index 000000000..83be24c9f --- /dev/null +++ b/perf/runner/src/index.ts @@ -0,0 +1,238 @@ +import { execSync } from 'child_process'; +import { versions } from './versions'; +import yargs from 'yargs'; +import fs from 'fs'; +import { BenchmarkResults, Benchmark, Result, IperfResults, PingResults, ResultValue } from './benchmark-result-type'; + +async function main(clientPublicIP: string, serverPublicIP: string) { + const pings = runPing(clientPublicIP, serverPublicIP); + const iperf = runIPerf(clientPublicIP, serverPublicIP); + + copyAndBuildPerfImplementations(serverPublicIP); + copyAndBuildPerfImplementations(clientPublicIP); + + const benchmarks = [ + runBenchmarkAcrossVersions({ + name: "Single Connection throughput – Upload 100 MiB", + clientPublicIP, + serverPublicIP, + uploadBytes: 100 << 20, + downloadBytes: 0, + unit: "bit/s", + iterations: 5, + }), + runBenchmarkAcrossVersions({ + name: "Single Connection throughput – Download 100 MiB", + clientPublicIP, + serverPublicIP, + uploadBytes: 0, + downloadBytes: 100 << 20, + unit: "bit/s", + iterations: 5, + }), + runBenchmarkAcrossVersions({ + name: "Connection establishment + 1 byte round trip latencies", + clientPublicIP, + serverPublicIP, + uploadBytes: 1, + downloadBytes: 1, + unit: "s", + iterations: 100, + }), + ]; + + const benchmarkResults: BenchmarkResults = { + benchmarks, + pings, + iperf, + }; + + // Save results to benchmark-results.json + fs.writeFileSync('./benchmark-results.json', JSON.stringify(benchmarkResults, null, 2)); + + console.error("== done"); +} + +function runPing(clientPublicIP: string, serverPublicIP: string): PingResults { + console.error(`= run 100 pings from client to server`); + + const cmd = `ssh -o StrictHostKeyChecking=no ec2-user@${clientPublicIP} 'ping -c 100 ${serverPublicIP}'`; + const stdout = execCommand(cmd).toString(); + + // Extract the time from each ping + const lines = stdout.split('\n'); + const times = lines + .map(line => { + const match = line.match(/time=(.*) ms/); + return match ? parseFloat(match[1]) / 1000 : null; // Convert from ms to s + }) + .filter((time): time is number => time !== null); // Remove any null values and ensure that array contains only numbers + + return { unit: "s", results: times } +} + +function runIPerf(clientPublicIP: string, serverPublicIP: string): IperfResults { + console.error(`= run 60 iPerf UDP from client to server`); + + const killCMD = `ssh -o StrictHostKeyChecking=no ec2-user@${serverPublicIP} 'kill $(cat pidfile); rm pidfile; rm server.log || true'`; + const killSTDOUT = execCommand(killCMD); + console.error(killSTDOUT); + + const serverCMD = `ssh -o StrictHostKeyChecking=no ec2-user@${serverPublicIP} 'nohup iperf3 -s > server.log 2>&1 & echo \$! > pidfile '`; + const serverSTDOUT = execCommand(serverCMD); + console.error(serverSTDOUT); + + const cmd = `ssh -o StrictHostKeyChecking=no ec2-user@${clientPublicIP} 'iperf3 -c ${serverPublicIP} -u -b 25g -t 60'`; + const stdout = execSync(cmd).toString(); + + // Extract the bitrate from each relevant line + const lines = stdout.split('\n'); + const bitrates = lines + .map(line => { + const match = line.match(/(\d+(?:\.\d+)?) (\w)bits\/sec/); // Matches and captures the number and unit before "bits/sec" + if (match) { + const value = parseFloat(match[1]); + const unit = match[2]; + // Convert value to bits/sec + const multiplier = unit === 'G' ? 1e9 : unit === 'M' ? 1e6 : unit === 'K' ? 1e3 : 1; + return value * multiplier; + } + return null; + }) + .filter((bitrate): bitrate is number => bitrate !== null); // Remove any null values + + return { unit: "bit/s", results: bitrates} +} + +interface ArgsRunBenchmarkAcrossVersions { + name: string, + clientPublicIP: string; + serverPublicIP: string; + uploadBytes: number, + downloadBytes: number, + unit: "bit/s" | "s", + iterations: number, +} + +function runBenchmarkAcrossVersions(args: ArgsRunBenchmarkAcrossVersions): Benchmark { + console.error(`= Benchmark ${args.name}`) + + const results: Result[] = []; + + for (const version of versions) { + console.error(`== Version ${version.implementation}/${version.id}`) + + console.error(`=== Starting server ${version.implementation}/${version.id}`); + + const killCMD = `ssh -o StrictHostKeyChecking=no ec2-user@${args.serverPublicIP} 'kill $(cat pidfile); rm pidfile; rm server.log || true'`; + const killSTDOUT = execCommand(killCMD); + console.error(killSTDOUT); + + const serverCMD = `ssh -o StrictHostKeyChecking=no ec2-user@${args.serverPublicIP} 'nohup ./impl/${version.implementation}/${version.id}/perf --run-server --server-address 0.0.0.0:4001 > server.log 2>&1 & echo \$! > pidfile '`; + const serverSTDOUT = execCommand(serverCMD); + console.error(serverSTDOUT); + + for (const transportStack of version.transportStacks) { + const result = runClient({ + clientPublicIP: args.clientPublicIP, + serverPublicIP: args.serverPublicIP, + id: version.id, + implementation: version.implementation, + transportStack: transportStack, + uploadBytes: args.uploadBytes, + downloadBytes: args.downloadBytes, + iterations: args.iterations, + }); + + results.push({ + result, + implementation: version.implementation, + version: version.id, + transportStack: transportStack, + }); + } + }; + + return { + name: args.name, + unit: args.unit, + results, + parameters: { + uploadBytes: args.uploadBytes, + downloadBytes: args.downloadBytes, + } + }; +} + +interface ArgsRunBenchmark { + clientPublicIP: string; + serverPublicIP: string; + serverAddress?: string; + id: string, + implementation: string, + transportStack: string, + uploadBytes: number, + downloadBytes: number, + iterations: number, +} + +function runClient(args: ArgsRunBenchmark): ResultValue[] { + console.error(`=== Starting client ${args.implementation}/${args.id}/${args.transportStack}`); + + const perfCMD = `./impl/${args.implementation}/${args.id}/perf --server-address ${args.serverPublicIP}:4001 --transport ${args.transportStack} --upload-bytes ${args.uploadBytes} --download-bytes ${args.downloadBytes}` + const cmd = `ssh -o StrictHostKeyChecking=no ec2-user@${args.clientPublicIP} 'for i in {1..${args.iterations}}; do ${perfCMD}; done'` + + const stdout = execCommand(cmd); + + const lines = stdout.toString().trim().split('\n'); + + const combined: ResultValue[]= []; + + for (const line of lines) { + const result = JSON.parse(line) as ResultValue; + combined.push(result); + } + + return combined; +} + +function execCommand(cmd: string): string { + try { + const stdout = execSync(cmd, { + encoding: 'utf8', + stdio: [process.stdin, 'pipe', process.stderr], + }); + return stdout; + } catch (error) { + console.error((error as Error).message); + process.exit(1); + } +} + +function copyAndBuildPerfImplementations(ip: string) { + console.error(`= Building implementations on ${ip}`); + + const stdout = execCommand(`rsync -avz --progress --filter=':- .gitignore' -e "ssh -o StrictHostKeyChecking=no" ../impl ec2-user@${ip}:/home/ec2-user`); + console.error(stdout.toString()); + + const stdout2 = execCommand(`ssh -o StrictHostKeyChecking=no ec2-user@${ip} 'cd impl && make'`); + console.error(stdout2.toString()); +} + +const argv = yargs + .options({ + 'client-public-ip': { + type: 'string', + demandOption: true, + description: 'Client public IP address', + }, + 'server-public-ip': { + type: 'string', + demandOption: true, + description: 'Server public IP address', + }, + }) + .command('help', 'Print usage information', yargs.help) + .parseSync(); + +main(argv['client-public-ip'] as string, argv['server-public-ip'] as string); diff --git a/perf/runner/src/versions.ts b/perf/runner/src/versions.ts new file mode 100644 index 000000000..a06bac962 --- /dev/null +++ b/perf/runner/src/versions.ts @@ -0,0 +1,33 @@ +export type Version = { + id: string, + implementation: "go-libp2p" | "js-libp2p" | "nim-libp2p" | "rust-libp2p" | "rust-libp2p-quinn" | "zig-libp2p" | "https" | "quic-go", + transportStacks: string[], +} + +export const versions: Array = [ + { + id: "v0.34", + implementation: "quic-go", + transportStacks: ["quic-v1"] + }, + { + id: "v0.52", + implementation: "rust-libp2p", + transportStacks: ["tcp", "quic-v1"] + }, + { + id: "v0.52", + implementation: "rust-libp2p-quinn", + transportStacks: ["quic-v1"] + }, + { + id: "v0.1", + implementation: "https", + transportStacks: ["tcp"] + }, + { + id: "v0.27", + implementation: "go-libp2p", + transportStacks: ["tcp", "quic-v1"] + }, +] diff --git a/perf/runner/tsconfig.json b/perf/runner/tsconfig.json new file mode 100644 index 000000000..183dbe70f --- /dev/null +++ b/perf/runner/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2018", + "module": "commonjs", + "outDir": "./dist", + "strict": true, + "resolveJsonModule": true, + "esModuleInterop": true + }, + "include": [ + "./src/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/perf/terraform/.gitignore b/perf/terraform/.gitignore new file mode 100644 index 000000000..80795e780 --- /dev/null +++ b/perf/terraform/.gitignore @@ -0,0 +1,34 @@ +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +!configs/remote/terraform_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc diff --git a/perf/terraform/configs/README.md b/perf/terraform/configs/README.md new file mode 100644 index 000000000..97ce004a4 --- /dev/null +++ b/perf/terraform/configs/README.md @@ -0,0 +1,13 @@ +# Configs + +The terraform configs defined in this directory are used to provision the infrastructure for the libp2p perf tests. + +The configs are named after the type of backend they use. The defaults for what parts of infrastructure they provision differ between the two. + +## local + +Terraform state in this configuration will be stored locally. The defaults are configured for a single performance benchmark run, i.e. `terraform apply` will bring up short-lived infrastructure only. It will skip long-lived infrastructure like the clean-up Lambda and the instance launch template. + +## remote + +Terraform state here will be stored remotely in an S3 bucket. `terraform apply` will only bring up the long-lived infrastructure needed to run the performance benchmarks It will skip short-lived infrastructure like launching EC2 instances. diff --git a/perf/terraform/configs/local/.terraform.lock.hcl b/perf/terraform/configs/local/.terraform.lock.hcl new file mode 100644 index 000000000..32564df51 --- /dev/null +++ b/perf/terraform/configs/local/.terraform.lock.hcl @@ -0,0 +1,46 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/archive" { + version = "2.3.0" + hashes = [ + "h1:NaDbOqAcA9d8DiAS5/6+5smXwN3/+twJGb3QRiz6pNw=", + "h1:OmE1tPjiST8iQp6fC0N3Xzur+q2RvgvD7Lz0TpKSRBw=", + "zh:0869128d13abe12b297b0cd13b8767f10d6bf047f5afc4215615aabc39c2eb4f", + "zh:481ed837d63ba3aa45dd8736da83e911e3509dee0e7961bf5c00ed2644f807b3", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:9f08fe2977e2166849be24fb9f394e4d2697414d463f7996fd0d7beb4e19a29c", + "zh:9fe566deeafd460d27999ca0bbfd85426a5fcfcb40007b23884deb76da127b6f", + "zh:a1bd9a60925d9769e0da322e4523330ee86af9dc2e770cba1d0247a999ef29cb", + "zh:bb4094c8149f74308b22a87e1ac19bcccca76e8ef021b571074d9bccf1c0c6f0", + "zh:c8984c9def239041ce41ec8e19bbd76a49e74ed2024ff736dad60429dee89bcc", + "zh:ea4bb5ae73db1de3a586e62f39106f5e56770804a55aa5e6b4f642df973e0e75", + "zh:f44a9d596ecc3a8c5653f56ba0cd202ad93b49f76767f4608daf7260b813289e", + "zh:f5c5e6cc9f7f070020ab7d95fcc9ed8e20d5cf219978295a71236e22cbb6d508", + "zh:fd2273f51dcc8f43403bf1e425ba9db08a57c3ddcba5ad7a51742ccde21ca611", + ] +} + +provider "registry.terraform.io/hashicorp/aws" { + version = "4.67.0" + constraints = "4.67.0" + hashes = [ + "h1:5Zfo3GfRSWBaXs4TGQNOflr1XaYj6pRnVJLX5VAjFX4=", + "h1:dCRc4GqsyfqHEMjgtlM1EympBcgTmcTkWaJmtd91+KA=", + "zh:0843017ecc24385f2b45f2c5fce79dc25b258e50d516877b3affee3bef34f060", + "zh:19876066cfa60de91834ec569a6448dab8c2518b8a71b5ca870b2444febddac6", + "zh:24995686b2ad88c1ffaa242e36eee791fc6070e6144f418048c4ce24d0ba5183", + "zh:4a002990b9f4d6d225d82cb2fb8805789ffef791999ee5d9cb1fef579aeff8f1", + "zh:559a2b5ace06b878c6de3ecf19b94fbae3512562f7a51e930674b16c2f606e29", + "zh:6a07da13b86b9753b95d4d8218f6dae874cf34699bca1470d6effbb4dee7f4b7", + "zh:768b3bfd126c3b77dc975c7c0e5db3207e4f9997cf41aa3385c63206242ba043", + "zh:7be5177e698d4b547083cc738b977742d70ed68487ce6f49ecd0c94dbf9d1362", + "zh:8b562a818915fb0d85959257095251a05c76f3467caa3ba95c583ba5fe043f9b", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9c385d03a958b54e2afd5279cd8c7cbdd2d6ca5c7d6a333e61092331f38af7cf", + "zh:b3ca45f2821a89af417787df8289cb4314b273d29555ad3b2a5ab98bb4816b3b", + "zh:da3c317f1db2469615ab40aa6baba63b5643bae7110ff855277a1fb9d8eb4f2c", + "zh:dc6430622a8dc5cdab359a8704aec81d3825ea1d305bbb3bbd032b1c6adfae0c", + "zh:fac0d2ddeadf9ec53da87922f666e1e73a603a611c57bcbc4b86ac2821619b1d", + ] +} diff --git a/perf/terraform/configs/local/terraform.tf b/perf/terraform/configs/local/terraform.tf new file mode 100644 index 000000000..22c745f5a --- /dev/null +++ b/perf/terraform/configs/local/terraform.tf @@ -0,0 +1,121 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "4.67.0" + } + } +} + +locals { + tags = { + Project = "perf" + } +} + +provider "aws" { + alias = "us-west-2" + region = "us-west-2" + default_tags { + tags = local.tags + } +} + +provider "aws" { + alias = "us-east-1" + region = "us-east-1" + default_tags { + tags = local.tags + } +} + + +variable "ci_enabled" { + type = bool + description = "Whether or not to create resources required to automate the setup in CI (e.g. IAM user, cleanup Lambda)" + default = false +} + +variable "long_lived_enabled" { + type = bool + description = "Whether or not to create long lived resources (in CI, used across runs; e.g. VPCs)" + default = false +} + +variable "short_lived_enabled" { + type = bool + description = "Whether or not to create short lived resources (in CI, specific to each run; e.g. EC2 instances)" + default = true +} + +module "ci" { + count = var.ci_enabled ? 1 : 0 + + source = "../../modules/ci" + + regions = ["us-west-2", "us-east-1"] + tags = local.tags + + providers = { + aws = aws.us-west-2 + } +} + +module "long_lived_server" { + count = var.long_lived_enabled ? 1 : 0 + + source = "../../modules/long_lived" + + region = "us-west-2" + ami = "ami-0747e613a2a1ff483" + + providers = { + aws = aws.us-west-2 + } +} + +module "long_lived_client" { + count = var.long_lived_enabled ? 1 : 0 + + source = "../../modules/long_lived" + + region = "us-east-1" + ami = "ami-06e46074ae430fba6" + + providers = { + aws = aws.us-east-1 + } +} + +module "short_lived_server" { + count = var.short_lived_enabled ? 1 : 0 + + source = "../../modules/short_lived" + + providers = { + aws = aws.us-west-2 + } + + depends_on = [module.long_lived_server] +} + +module "short_lived_client" { + count = var.short_lived_enabled ? 1 : 0 + + source = "../../modules/short_lived" + + providers = { + aws = aws.us-east-1 + } + + depends_on = [module.long_lived_client] +} + +output "client_ip" { + value = var.short_lived_enabled ? module.short_lived_client[0].public_ip : null +} + +output "server_ip" { + value = var.short_lived_enabled ? module.short_lived_server[0].public_ip : null +} + diff --git a/perf/terraform/configs/remote/.terraform.lock.hcl b/perf/terraform/configs/remote/.terraform.lock.hcl new file mode 100644 index 000000000..e490491e1 --- /dev/null +++ b/perf/terraform/configs/remote/.terraform.lock.hcl @@ -0,0 +1,44 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/archive" { + version = "2.3.0" + hashes = [ + "h1:NaDbOqAcA9d8DiAS5/6+5smXwN3/+twJGb3QRiz6pNw=", + "zh:0869128d13abe12b297b0cd13b8767f10d6bf047f5afc4215615aabc39c2eb4f", + "zh:481ed837d63ba3aa45dd8736da83e911e3509dee0e7961bf5c00ed2644f807b3", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:9f08fe2977e2166849be24fb9f394e4d2697414d463f7996fd0d7beb4e19a29c", + "zh:9fe566deeafd460d27999ca0bbfd85426a5fcfcb40007b23884deb76da127b6f", + "zh:a1bd9a60925d9769e0da322e4523330ee86af9dc2e770cba1d0247a999ef29cb", + "zh:bb4094c8149f74308b22a87e1ac19bcccca76e8ef021b571074d9bccf1c0c6f0", + "zh:c8984c9def239041ce41ec8e19bbd76a49e74ed2024ff736dad60429dee89bcc", + "zh:ea4bb5ae73db1de3a586e62f39106f5e56770804a55aa5e6b4f642df973e0e75", + "zh:f44a9d596ecc3a8c5653f56ba0cd202ad93b49f76767f4608daf7260b813289e", + "zh:f5c5e6cc9f7f070020ab7d95fcc9ed8e20d5cf219978295a71236e22cbb6d508", + "zh:fd2273f51dcc8f43403bf1e425ba9db08a57c3ddcba5ad7a51742ccde21ca611", + ] +} + +provider "registry.terraform.io/hashicorp/aws" { + version = "4.67.0" + constraints = "4.67.0" + hashes = [ + "h1:5Zfo3GfRSWBaXs4TGQNOflr1XaYj6pRnVJLX5VAjFX4=", + "zh:0843017ecc24385f2b45f2c5fce79dc25b258e50d516877b3affee3bef34f060", + "zh:19876066cfa60de91834ec569a6448dab8c2518b8a71b5ca870b2444febddac6", + "zh:24995686b2ad88c1ffaa242e36eee791fc6070e6144f418048c4ce24d0ba5183", + "zh:4a002990b9f4d6d225d82cb2fb8805789ffef791999ee5d9cb1fef579aeff8f1", + "zh:559a2b5ace06b878c6de3ecf19b94fbae3512562f7a51e930674b16c2f606e29", + "zh:6a07da13b86b9753b95d4d8218f6dae874cf34699bca1470d6effbb4dee7f4b7", + "zh:768b3bfd126c3b77dc975c7c0e5db3207e4f9997cf41aa3385c63206242ba043", + "zh:7be5177e698d4b547083cc738b977742d70ed68487ce6f49ecd0c94dbf9d1362", + "zh:8b562a818915fb0d85959257095251a05c76f3467caa3ba95c583ba5fe043f9b", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9c385d03a958b54e2afd5279cd8c7cbdd2d6ca5c7d6a333e61092331f38af7cf", + "zh:b3ca45f2821a89af417787df8289cb4314b273d29555ad3b2a5ab98bb4816b3b", + "zh:da3c317f1db2469615ab40aa6baba63b5643bae7110ff855277a1fb9d8eb4f2c", + "zh:dc6430622a8dc5cdab359a8704aec81d3825ea1d305bbb3bbd032b1c6adfae0c", + "zh:fac0d2ddeadf9ec53da87922f666e1e73a603a611c57bcbc4b86ac2821619b1d", + ] +} diff --git a/perf/terraform/configs/remote/terraform.tf b/perf/terraform/configs/remote/terraform.tf new file mode 120000 index 000000000..e51ea571a --- /dev/null +++ b/perf/terraform/configs/remote/terraform.tf @@ -0,0 +1 @@ +../local/terraform.tf \ No newline at end of file diff --git a/perf/terraform/configs/remote/terraform_override.tf b/perf/terraform/configs/remote/terraform_override.tf new file mode 100644 index 000000000..e12102fb0 --- /dev/null +++ b/perf/terraform/configs/remote/terraform_override.tf @@ -0,0 +1,19 @@ +terraform { + backend "s3" { + bucket = "libp2p-terraform-state" + key = "github.com/libp2p/test-plans/perf/terraform/configs/remote/terraform.tfstate" + region = "us-west-2" + } +} + +variable "ci_enabled" { + default = true +} + +variable "long_lived_enabled" { + default = true +} + +variable "short_lived_enabled" { + default = false +} diff --git a/perf/terraform/modules/ci/cleanup.tf b/perf/terraform/modules/ci/cleanup.tf new file mode 100644 index 000000000..27e7bcedc --- /dev/null +++ b/perf/terraform/modules/ci/cleanup.tf @@ -0,0 +1,107 @@ +data "archive_file" "cleanup" { + type = "zip" + source_file = "${path.module}/files/cleanup.py" + output_path = "${path.module}/files/cleanup.zip" +} + +resource "aws_lambda_function" "cleanup" { + filename = data.archive_file.cleanup.output_path + source_code_hash = data.archive_file.cleanup.output_base64sha256 + function_name = "perf-cleanup" + role = aws_iam_role.cleanup.arn + handler = "cleanup.lambda_handler" + runtime = "python3.9" + memory_size = 128 + timeout = 30 + + environment { + variables = { + REGIONS = jsonencode(var.regions) + TAGS = jsonencode(var.tags) + MAX_AGE_MINUTES = 50 + } + } +} + +resource "aws_cloudwatch_log_group" "cleanup" { + name = "/aws/lambda/${aws_lambda_function.cleanup.function_name}" + retention_in_days = 7 +} + +resource "aws_cloudwatch_event_rule" "cleanup" { + name = "perf-cleanup-rule" + schedule_expression = "cron(37 * * * ? *)" # 00:37, 01:37, 02:37, ..., 23:37 +} + +resource "aws_cloudwatch_event_target" "cleanup" { + rule = aws_cloudwatch_event_rule.cleanup.name + arn = aws_lambda_function.cleanup.arn +} + +resource "aws_lambda_permission" "cleanup" { + statement_id = "AllowExecutionFromCloudWatch" + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.cleanup.function_name + principal = "events.amazonaws.com" + source_arn = aws_cloudwatch_event_rule.cleanup.arn +} + +data "aws_iam_policy_document" "cleanup_assume_role" { + statement { + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["lambda.amazonaws.com"] + } + } +} + +resource "aws_iam_role" "cleanup" { + name = "perf-cleanup-lambda-role" + assume_role_policy = data.aws_iam_policy_document.cleanup_assume_role.json +} + +data "aws_iam_policy_document" "cleanup" { + statement { + actions = ["ec2:DescribeInstances", "ec2:DescribeTags", "ec2:DescribeKeyPairs"] + resources = ["*"] + effect = "Allow" + } + + statement { + actions = ["ec2:TerminateInstances", "ec2:DeleteKeyPair"] + resources = ["*"] + effect = "Allow" + + dynamic "condition" { + for_each = var.tags + + content { + test = "StringEquals" + variable = "ec2:ResourceTag/${condition.key}" + values = [condition.value] + } + } + } +} + +resource "aws_iam_role_policy" "cleanup" { + name = "perf-cleanup-lamda-policy" + role = aws_iam_role.cleanup.name + policy = data.aws_iam_policy_document.cleanup.json +} + +data "aws_iam_policy_document" "cleanup_logging" { + statement { + actions = ["logs:CreateLogStream", "logs:PutLogEvents"] + resources = ["${aws_cloudwatch_log_group.cleanup.arn}*"] + effect = "Allow" + } +} + +resource "aws_iam_role_policy" "cleanup_logging" { + name = "perf-lambda-logging" + role = aws_iam_role.cleanup.name + policy = data.aws_iam_policy_document.cleanup_logging.json +} diff --git a/perf/terraform/modules/ci/files/.gitignore b/perf/terraform/modules/ci/files/.gitignore new file mode 100644 index 000000000..47066beae --- /dev/null +++ b/perf/terraform/modules/ci/files/.gitignore @@ -0,0 +1,2 @@ +# generated ZIP for AWS Lambda +cleanup.zip diff --git a/perf/terraform/modules/ci/files/cleanup.json b/perf/terraform/modules/ci/files/cleanup.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/perf/terraform/modules/ci/files/cleanup.json @@ -0,0 +1 @@ +{} diff --git a/perf/terraform/modules/ci/files/cleanup.py b/perf/terraform/modules/ci/files/cleanup.py new file mode 100644 index 000000000..4cb2f483a --- /dev/null +++ b/perf/terraform/modules/ci/files/cleanup.py @@ -0,0 +1,45 @@ +import boto3 +import os +import json +import datetime + +regions = json.loads(os.environ['REGIONS']) # Assuming this is a JSON array +tags = json.loads(os.environ['TAGS']) # Assuming this is a JSON object +max_age_minutes = int(os.environ['MAX_AGE_MINUTES']) # Assuming this is an integer + +# TODO: Find and delete unused key pairs +def lambda_handler(event, context): + # iterate over all regions + for region in regions: + ec2 = boto3.client('ec2', region_name=region) + + now = datetime.datetime.now(datetime.timezone.utc) + + filters = [{'Name': 'instance-state-name', 'Values': ['running']}] + filters = filters + [{ + 'Name': 'tag:' + k, + 'Values': [v] + } for k, v in tags.items()] + + response = ec2.describe_instances(Filters=filters) + + instances = [] + + for reservation in response['Reservations']: + for instance in reservation['Instances']: + launch_time = instance['LaunchTime'] + instance_id = instance['InstanceId'] + + print( + f'Instance ID: {instance_id} has been running since {launch_time}.') + + if launch_time < now - datetime.timedelta(minutes=max_age_minutes): + print( + f'Instance ID: {instance_id} has been running for more than {max_age_minutes} minutes.') + instances.append(instance_id) + + if instances: + ec2.terminate_instances(InstanceIds=instances) + print(f'Terminating instances: {instances}') + + ec2.describe_ diff --git a/perf/terraform/modules/ci/files/cleanup.sh b/perf/terraform/modules/ci/files/cleanup.sh new file mode 100755 index 000000000..e540775c2 --- /dev/null +++ b/perf/terraform/modules/ci/files/cleanup.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# This script can be used to test the cleanup lambda. +# It requires the AWS CLI and SAM CLI to be installed. +# You can get SAM CLI at https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html + +sam local invoke Cleanup --template cleanup.yml --event cleanup.json diff --git a/perf/terraform/modules/ci/files/cleanup.yml b/perf/terraform/modules/ci/files/cleanup.yml new file mode 100644 index 000000000..21336ff6f --- /dev/null +++ b/perf/terraform/modules/ci/files/cleanup.yml @@ -0,0 +1,19 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: An AWS Lambda application. + +Resources: + Cleanup: + Type: AWS::Serverless::Function + Properties: + Handler: cleanup.lambda_handler + Runtime: python3.9 + CodeUri: . + Environment: + Variables: + REGIONS: '["us-west-2", "us-east-1"]' + TAGS: '{"Project":"perf", "Name":"node"}' + MAX_AGE_MINUTES: '30' + Policies: + - AmazonEC2FullAccess + Timeout: 30 diff --git a/perf/terraform/modules/ci/main.tf b/perf/terraform/modules/ci/main.tf new file mode 100644 index 000000000..6237e3306 --- /dev/null +++ b/perf/terraform/modules/ci/main.tf @@ -0,0 +1,38 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "4.67.0" + } + } +} + +variable "tags" { + type = map(string) + description = "Tags that the perf resources are tagged with" +} + +variable "regions" { + type = list(string) + description = "Regions that the perf resources are created in" +} + +resource "aws_iam_user" "perf" { + name = "perf" +} + +# TODO: Make the policy more restrictive; it needs to be able to create/destroy instances and key pairs +data "aws_iam_policy_document" "perf" { + statement { + actions = ["ec2:*"] + resources = ["*"] + effect = "Allow" + } +} + +resource "aws_iam_user_policy" "perf" { + name = "perf" + user = aws_iam_user.perf.name + + policy = data.aws_iam_policy_document.perf.json +} diff --git a/perf/terraform/modules/long_lived/files/user-data.sh b/perf/terraform/modules/long_lived/files/user-data.sh new file mode 100644 index 000000000..d1026af3d --- /dev/null +++ b/perf/terraform/modules/long_lived/files/user-data.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +sudo yum install make -y + +sudo yum -y install iperf3 + +# Bump UDP receive buffer size. See https://github.com/quic-go/quic-go/wiki/UDP-Receive-Buffer-Size. +sudo sysctl -w net.core.rmem_max=2500000 + +sudo yum update -y +sudo yum install docker -y +sudo systemctl enable docker +sudo systemctl start docker +sudo usermod -aG docker ec2-user diff --git a/perf/terraform/modules/long_lived/main.tf b/perf/terraform/modules/long_lived/main.tf new file mode 100644 index 000000000..7fbc9588b --- /dev/null +++ b/perf/terraform/modules/long_lived/main.tf @@ -0,0 +1,111 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "4.67.0" + } + } +} + +variable "region" { + description = "The AWS region of the provider" +} + +variable "ami" { + description = "The Amazon Machine Image to use" +} + +locals { + availability_zone = "${var.region}a" +} + +resource "aws_vpc" "perf" { + cidr_block = "10.0.0.0/16" +} + +resource "aws_subnet" "perf" { + vpc_id = aws_vpc.perf.id + cidr_block = "10.0.0.0/16" + availability_zone = local.availability_zone + map_public_ip_on_launch = true +} + +resource "aws_internet_gateway" "perf" { + vpc_id = aws_vpc.perf.id +} + +resource "aws_route_table" "perf" { + vpc_id = aws_vpc.perf.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.perf.id + } +} + +resource "aws_route_table_association" "perf" { + subnet_id = aws_subnet.perf.id + route_table_id = aws_route_table.perf.id +} + +resource "aws_security_group" "restricted_inbound" { + name = "restricted_inbound" + description = "Allow SSH and port 4001 inbound traffic (TCP and UDP), allow all outbound traffic" + vpc_id = aws_vpc.perf.id + + # ICMP + ingress { + from_port = -1 + to_port = -1 + protocol = "icmp" + cidr_blocks = ["0.0.0.0/0"] + } + + # SSH (TCP) + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 1 + to_port = 65535 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 1 + to_port = 65535 + protocol = "udp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_launch_template" "perf" { + name = "perf-node" + image_id = var.ami + instance_type = "m5n.8xlarge" + + # Debug via: + # - /var/log/cloud-init.log and + # - /var/log/cloud-init-output.log + user_data = filebase64("${path.module}/files/user-data.sh") + + instance_initiated_shutdown_behavior = "terminate" + + network_interfaces { + subnet_id = aws_subnet.perf.id + security_groups = [aws_security_group.restricted_inbound.id] + delete_on_termination = true + } +} diff --git a/perf/terraform/modules/short_lived/files/.gitignore b/perf/terraform/modules/short_lived/files/.gitignore new file mode 100644 index 000000000..d53e7f9d3 --- /dev/null +++ b/perf/terraform/modules/short_lived/files/.gitignore @@ -0,0 +1,3 @@ +# generated SSH key +perf +perf.pub diff --git a/perf/terraform/modules/short_lived/main.tf b/perf/terraform/modules/short_lived/main.tf new file mode 100644 index 000000000..17782a51c --- /dev/null +++ b/perf/terraform/modules/short_lived/main.tf @@ -0,0 +1,29 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "4.67.0" + } + } +} + +resource "aws_key_pair" "perf" { + key_name_prefix = "perf-" + public_key = file("${path.module}/files/perf.pub") +} + +resource "aws_instance" "perf" { + tags = { + Name = "perf-node" + } + + launch_template { + name = "perf-node" + } + + key_name = aws_key_pair.perf.key_name +} + +output "public_ip" { + value = aws_instance.perf.public_ip +}