Skip to content

Conversation

@mxinden
Copy link
Member

@mxinden mxinden commented May 26, 2023

Description

libp2p performance benchmarking

This project includes the following components:

  • terraform/: a Terraform scripts to provision infrastructure
  • impl/: implementations of the libp2p perf protocol 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.

See perf/README.md and overarching tracking issue #63.

Continuation of #163.

Outstanding work in this pull request:

  • Remove libp2p specific concepts (e.g. multiaddr) e.g. to no longer require the https example to parse a multiaddr.
  • Rename public ssh key
  • Remove --n-times flag from binaries. Potentially introduce --n-parallel-requests flag in the future. Multiple sequential runs are now done in the runner implementation.
  • Transfer and run binaries instead of docker images / containers. Or build on the machines.
  • Configurable Server port. See feat(perf): add (provision, build, run) tooling  #163.
  • Consider adding benchmark parameters to output json file. See feat(perf): add (provision, build, run) tooling  #163 (review).
  • Move to TLS only (for now). Easier to compare with HTTPs and no additional security protocol negotiation.
  • Remove the need for static peer IDs, i.e. remove --secret-key-seed.

### Outstanding work for future pull requests:
Outstanding / follow-up work tracked in #63.

Comment on lines 65 to 69
type customReader struct {
downloadBytes uint64
uploadBytes uint64
position uint64
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just copy-paste the perf implementation we have in the v0.27 folder? The Read implementation here looks quite complicated.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The impl/go-libp2p/v0.27 implementation leverages the io.Writer interface on network.Stream interface. I don't know how to have the Go std http library provide an object that implements io.Writer interface for an HTTP request. Instead all the methods that I am aware of require passing an io.Reader for an outgoing HTTP request, i.e. client.Post and http.NewRequest.

@marten-seemann are you aware of an alternative?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a comment below.

if c.position < 8 {
binary.BigEndian.PutUint64(p, c.downloadBytes)
c.position += 8
return 8, nil
Copy link
Contributor

@MarcoPolo MarcoPolo Jun 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't correct. You're assuming the input slice is always at least 8 bytes.

Use io.MultiReader to combine a bytes.NewReader(<buf-with-u64-download-bytes>) and a zeroReader.

The zeroReader could look something like:

type zeroReader struct {
    n int64
}

func (z *zeroReader) Read(p []byte) (int, error) {
    if z.n <= 0 {
        return 0, io.EOF
    }

    for i := range p {
        if z.n <= 0 {
            return i, nil
        }

        p[i] = 0
        z.n--
    }

    return len(p), nil
}

Copy link
Member Author

@mxinden mxinden Jun 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't aware of io.MultiReader. That simplifies things. Thanks!

Fixed with 2296d8c. Note that I am still using copy instead of zeroing every byte individually in the (maybe premature) hope that Go can optimize some of it. Let me know in case you prefer individual zeroing for each byte instead @MarcoPolo.

Edit:

Slight change of plan, instead of 2296d8c I merged @marten-seemann's suggestion through #201.

@MarcoPolo
Copy link
Contributor

Looks good mod last comment about the reader.

Copy link
Contributor

@marten-seemann marten-seemann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, let's ship it!
There's a few follow-up items to this PR, but what we have here is an excellent basis to start iterating on.

Thank you for this clean setup @mxinden, I'm really happy how this turned out

@mxinden mxinden merged commit 53ff8b5 into master Jun 22, 2023
mxinden added a commit that referenced this pull request Jun 23, 2023
mxinden added a commit that referenced this pull request Jun 23, 2023
mxinden added a commit to mxinden/perf that referenced this pull request Jun 23, 2023
Instead of exposing the time to establish a connection, the time to upload the
bytes and the time to download the bytes, expose a single time including all
three.

The rational here is, that differentiation of the three is flawed. E.g. when
does one stop the upload timer and start the download timer? When the last byte
is sent? When the last byte is flushed? When the first byte is received?

See libp2p/test-plans#184 (review)
for past discussion.
marten-seemann pushed a commit to quic-go/perf that referenced this pull request Jun 23, 2023
Instead of exposing the time to establish a connection, the time to upload the
bytes and the time to download the bytes, expose a single time including all
three.

The rational here is, that differentiation of the three is flawed. E.g. when
does one stop the upload timer and start the download timer? When the last byte
is sent? When the last byte is flushed? When the first byte is received?

See libp2p/test-plans#184 (review)
for past discussion.
mergify bot pushed a commit to libp2p/rust-libp2p that referenced this pull request Jun 26, 2023
Instead of exposing the time to establish a connection, the time to upload the bytes and the time to download the bytes, expose a single time including all three.

The rational here is, that differentiation of the three is flawed. E.g. when does one stop the upload timer and start the download timer? When the last byte is sent? When the last byte is flushed? When the first byte is received?

See libp2p/test-plans#184 (review) for past discussion.

Pull-Request: #4105.


  
Co-Authored-By: Max Inden <[email protected]>
@mxinden mxinden deleted the perf branch June 26, 2023 08:53
codemaestro64 pushed a commit to codemaestro64/test-plans that referenced this pull request Oct 28, 2025
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.

Co-authored-by: Marco Munizaga <[email protected]>
Co-authored-by: Marten Seemann <[email protected]>
Co-authored-by: Piotr Galar <[email protected]>
codemaestro64 pushed a commit to codemaestro64/test-plans that referenced this pull request Oct 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants