Skip to content

No benchmark tests #120

Description

@sumanjeet0012

Summary

py-multiaddr has no benchmark suite. Core hot-path operations — string parsing, byte (de)serialization, string formatting, protocol iteration, and encapsulation/decapsulation — have no performance baseline, so regressions in these paths can land silently and there's no data to guide optimization work.

Motivation

  • Regression detection: These operations run on every multiaddr construction/comparison in downstream users (py-libp2p, etc.), often in tight loops (peer discovery, DHT routing tables, connection dialing). A silent slowdown in Multiaddr.__init__ or to_bytes() would only surface as vague "things feel slower" reports from consumers.
  • Informed optimization: Without a baseline, it's not possible to tell whether a proposed optimization (e.g. caching parsed components, avoiding repeated bytes conversions) actually helps.
  • CI gating: A benchmark suite is a prerequisite for eventually wiring up pytest-benchmark's comparison/fail-on-regression features in CI, so future PRs that touch parsing/serialization internals can be checked automatically rather than by manual review.
  • Parity with intent of the library: Multiaddr is meant to be a lightweight, frequently-constructed value type; performance of construction and serialization is part of its core contract, not an afterthought.

Current Behavior

No benchmark tests exist. The only way to gauge performance today is manual, ad hoc timing during development.

Proposed Solution

Add a new dev dependency, pytest-benchmark, and a tests/test_benchmarks.py covering the core operations:

import pytest
from multiaddr import Multiaddr
 
BENCH_ADDR = "/ip4/1.2.3.4/tcp/80/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fkaDs"
 
@pytest.mark.benchmark
def test_bench_from_string(benchmark):
    benchmark(Multiaddr, BENCH_ADDR)
 
@pytest.mark.benchmark
def test_bench_to_string(benchmark):
    ma = Multiaddr(BENCH_ADDR)
    benchmark(str, ma)
 
@pytest.mark.benchmark
def test_bench_to_bytes(benchmark):
    ma = Multiaddr(BENCH_ADDR)
    benchmark(ma.to_bytes)
 
@pytest.mark.benchmark
def test_bench_protocols(benchmark):
    ma = Multiaddr(BENCH_ADDR)
    benchmark(lambda: list(ma.protocols()))
 
@pytest.mark.benchmark
def test_bench_encapsulate(benchmark):
    ma1 = Multiaddr("/ip4/1.2.3.4")
    ma2 = Multiaddr("/tcp/80")
    benchmark(ma1.encapsulate, ma2)
 
@pytest.mark.benchmark
def test_bench_decapsulate(benchmark):
    ma = Multiaddr("/ip4/1.2.3.4/tcp/80")
    benchmark(ma.decapsulate, "/tcp/80")

Covers, at minimum:

  • Parsing: string → Multiaddr (from_string path)
  • Formatting: Multiaddr → string (__str__)
  • Serialization: Multiaddr → bytes (to_bytes)
  • Iteration: enumerating protocol components
  • Composition: encapsulate / decapsulate

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions