Skip to content

Conversation

@picnixz
Copy link
Member

@picnixz picnixz commented Nov 22, 2025

I think this patch should cover the cases. I'm unsure whether this will break more stuff or not but I do know that using < and __lt__ return different boolean results which can break many things.

@serhiy-storchaka I really want a second eye here so PTAL whenever you've got time. TiA!

@picnixz picnixz force-pushed the fix/ipaddress/instance-checks-141647 branch from bd5eeda to ca36ea4 Compare November 22, 2025 15:34
Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

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

Please make benchmarks for equality and order comparison.

raise ValueError("Address negative or too large for IPv6")


def _check_ip_version(a, b):
Copy link
Member

Choose a reason for hiding this comment

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

Would not moving this code to a function add an overhead for fast operators?

Copy link
Member Author

Choose a reason for hiding this comment

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

I will check how much overhead I'm getting.

Copy link
Contributor

Choose a reason for hiding this comment

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

why the benchmark is faster its interesting...

Copy link
Member Author

@picnixz picnixz Nov 29, 2025

Choose a reason for hiding this comment

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

It's likely noise. Benchmarks weren't run on an idle system.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's likely noise. Benchmarks weren't run on an idle system.

thank you~

@picnixz
Copy link
Member Author

picnixz commented Nov 29, 2025

So I'm a bit surprised but here are the numbers:

+---------------------------------------------+---------------+-----------------------+
| Benchmark                                   | ipaddress-ref | ipaddress-new         |
+=============================================+===============+=======================+
| address.__eq__[1.2.3.4,5.6.7.8]             | 39.7 ns       | 41.0 ns: 1.03x slower |
+---------------------------------------------+---------------+-----------------------+
| interface.__eq__[192.0.2.0/32,192.0.2.0/32] | 242 ns        | 264 ns: 1.09x slower  |
+---------------------------------------------+---------------+-----------------------+
| interface.__lt__[192.0.2.0/32,192.0.8.0/32] | 344 ns        | 317 ns: 1.09x faster  |
+---------------------------------------------+---------------+-----------------------+
| interface.__eq__[192.0.2.0/32,192.0.2.0/24] | 253 ns        | 245 ns: 1.03x faster  |
+---------------------------------------------+---------------+-----------------------+
| interface.__lt__[192.0.8.0/32,192.0.8.0/32] | 389 ns        | 362 ns: 1.07x faster  |
+---------------------------------------------+---------------+-----------------------+
| network.__lt__[192.0.2.0/32,192.0.8.0/32]   | 160 ns        | 167 ns: 1.04x slower  |
+---------------------------------------------+---------------+-----------------------+
| network.__eq__[192.0.8.0/32,192.0.2.0/24]   | 80.4 ns       | 76.4 ns: 1.05x faster |
+---------------------------------------------+---------------+-----------------------+
| network.__eq__[192.0.2.0/24,192.0.2.0/24]   | 140 ns        | 134 ns: 1.05x faster  |
+---------------------------------------------+---------------+-----------------------+
| network.__lt__[192.0.2.0/24,192.0.2.0/24]   | 173 ns        | 166 ns: 1.04x faster  |
+---------------------------------------------+---------------+-----------------------+
| mixed.__lt__[5.6.7.8,1.2.3.4/32]            | 416 ns        | 387 ns: 1.07x faster  |
+---------------------------------------------+---------------+-----------------------+
| mixed.__lt__[5.6.7.8/32,5.6.7.8/32]         | 372 ns        | 398 ns: 1.07x slower  |
+---------------------------------------------+---------------+-----------------------+
| Geometric mean                              | (ref)         | 1.00x faster          |
+---------------------------------------------+---------------+-----------------------+

This benchmark uses the _check_ip_version additional call and Python 3.14 from uv (since the changes are only in pure Python, it's fine to switch branches). I've also tried those "slower" cases but it's really within the real of noise IMO.

Benchmark script
import ipaddress
import itertools
import operator

import pyperf

seen = set()

def bench_eq(runner, label, x, y, seen):
    name = f"{label}.__eq__[{x},{y}]"
    if name not in seen:
        runner.bench_func(name, operator.__eq__, x, y)
        seen.add(name)

def bench_lt(runner, label, x, y, seen):
    name = f"{label}.__lt__[{x},{y}]"
    if name not in seen:
        runner.bench_func(name, operator.__lt__, x, y)
        seen.add(name)


if __name__ == "__main__":
    runner = pyperf.Runner()
    args = runner.parse_args()
    seen = set()

    for x, y in itertools.combinations_with_replacement(
        [
            ipaddress.IPv4Address("1.2.3.4"),
            ipaddress.IPv4Address("5.6.7.8"),
        ], 2
    ):
        bench_eq(runner, "address", x, y, seen)
        bench_lt(runner, "address", x, y, seen)

    for x, y in itertools.combinations_with_replacement(
        [
            ipaddress.IPv4Interface("192.0.2.0"),
            ipaddress.IPv4Interface("192.0.8.0"),
            ipaddress.IPv4Interface("192.0.2.0/24"),
            ipaddress.IPv4Interface("192.0.8.0/32"),
        ], 2
    ):
        bench_eq(runner, "interface", x, y, seen)
        bench_lt(runner, "interface", x, y, seen)

    for x, y in itertools.combinations_with_replacement(
        [
            ipaddress.IPv4Network("192.0.2.0"),
            ipaddress.IPv4Network("192.0.8.0"),
            ipaddress.IPv4Network("192.0.2.0/24"),
            ipaddress.IPv4Network("192.0.8.0/32"),
        ], 2
    ):
        bench_eq(runner, "network", x, y, seen)
        bench_lt(runner, "network", x, y, seen)

    for x, y in itertools.combinations_with_replacement(
        [
            ipaddress.IPv4Address("1.2.3.4"),
            ipaddress.IPv4Address("5.6.7.8"),
            ipaddress.IPv4Interface("1.2.3.4"),
            ipaddress.IPv4Interface("5.6.7.8"),
            ipaddress.IPv4Interface("1.2.3.4/24"),
            ipaddress.IPv4Interface("5.6.7.8/32"),
        ], 2
    ):
        bench_lt(runner, "mixed", x, y, seen)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants