You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Converting ipv6 address to string representation using getnameinfo() is wrong. #76402
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2018-02-12.20:12:56.838>created_at=<Date2017-12-05.09:54:54.420>labels= ['3.7', 'library', 'performance']
title='Converting ipv6 address to string representation using getnameinfo() is wrong.'updated_at=<Date2018-02-12.20:12:56.838>user='https://github.com/socketpair'
recvfrom from multicast socket is painfull slow. In fact, it returns sender address in form:
('fe80::941f:f6ff:fe04:c560%qwe', 42133, 0, 78)
which is superfluous, since interface-name part (%qwe) is not actually used. Actually, scopeid (78) signify interface/scope/zone_id. This tuple can be used for .sendto() either with this interface-name-part or without.
The problem is in the performance. For each recvrfom(), getnameinfo() internally converts interface index to interface name using three syscalls, i.e. socket(), getsockopt()?, close() , which slows down receiving (I have not measured result, but see additional syscalls in strace).
In order to convert from tuple to string-based full address one may use getnameinfo():
As you can see, initial interface is ignored (but without my patch it is also validated uselessly):
What do you mean? Can you give results for a benchmark of your choice? How much does your PR speed it up?
socketpair commented on Dec 20, 2017
socketpairmannequin
MannequinAuthor
More actions
Original (not patched) python:
In [1]s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
In [2]: s.bind(('ff02::1de:c0db', 1234, 0, 2))
In [3]: timeit s.getsockname()
The slowest run took 12.06 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 3.8 µs per loop
In [5]: d = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
In [6]: d.bind(('::', 1235, 0, 0))
In [7]: timeit d.getsockname()
The slowest run took 23.18 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 532 ns per loop
On patched version, times for both cases should be the same exactly (i.e. 532 ns)
socketpair commented on Dec 20, 2017
socketpairmannequin
MannequinAuthor
More actions
So it may affect applications, that work with UDP and .recvfrom()
The PR looks good, but I don't have the capacity right now to merge it. Ill need some time for research to double check if it's ok to drop scope id. Will try to find it in the next few days.
New changeset 47c0b1f by Yury Selivanov (Коренберг Марк) in branch 'master': bpo-32221: makeipaddr(): remove interface part + speedup (GH-4724) 47c0b1f
Two tests fail on MacOS X now (newly added tests). I'm reverting the change for now. If you figure this out, please re-submit a PR for a quick approval.
Traceback (most recent call last):
File "/Users/yury/dev/pydev/cpython/Lib/test/test_socket.py", line 1612, in test_getaddrinfo_ipv6_scopeid
ifindex = socket.if_nametoindex(test_interface)
OSError: no interface with this name
New changeset 0ceb717 by Yury Selivanov in branch 'master':
Revert "bpo-32221: makeipaddr(): remove interface part + speedup (GH-4724)" (bpo-5394) 0ceb717
Activity
socketpair commentedon Dec 5, 2017
#4724
recvfromfrom multicast socket is painfull slow. In fact, it returns sender address in form:('fe80::941f:f6ff:fe04:c560%qwe', 42133, 0, 78)which is superfluous, since interface-name part (
%qwe) is not actually used. Actually, scopeid (78) signify interface/scope/zone_id. This tuple can be used for.sendto()either with this interface-name-part or without.The problem is in the performance. For each
recvrfom(),getnameinfo()internally converts interface index to interface name using three syscalls, i.e.socket(), getsockopt()?, close(), which slows down receiving (I have not measured result, but see additional syscalls instrace).In order to convert from tuple to string-based full address one may use
getnameinfo():As you can see, initial interface is ignored (but without my patch it is also validated uselessly):
socketpair commentedon Dec 14, 2017
Please look at my PR
pitrou commentedon Dec 18, 2017
What do you mean? Can you give results for a benchmark of your choice? How much does your PR speed it up?
socketpair commentedon Dec 20, 2017
Original (not patched) python:
On patched version, times for both cases should be the same exactly (i.e. 532 ns)
socketpair commentedon Dec 20, 2017
So it may affect applications, that work with UDP and .recvfrom()
pitrou commentedon Dec 20, 2017
Wow. That's a heavy price to pay indeed.
Unfortunately I'm not competent on IPv6. I'm cc-ing other core developers so that they may chime in.
socketpair commentedon Dec 20, 2017
After my patch:
1st1 commentedon Dec 20, 2017
I thought the improvements were way bigger than 200nsec, no?
socketpair commentedon Dec 21, 2017
No, Improvement for typical case (not scoped IPv6 addresses) was not the target, but fortunatelly it also sped up.
1st1 commentedon Dec 21, 2017
The PR looks good, but I don't have the capacity right now to merge it. Ill need some time for research to double check if it's ok to drop scope id. Will try to find it in the next few days.
socketpair commentedon Dec 29, 2017
So, PR is ready. Please review.
1st1 commentedon Dec 29, 2017
I understand, however I still don't have time for it at the moment. If another core dev wants to take initiative, please by all means do.
I can/will take another look at this after January 15.
1st1 commentedon Jan 27, 2018
New changeset 47c0b1f by Yury Selivanov (Коренберг Марк) in branch 'master':
bpo-32221: makeipaddr(): remove interface part + speedup (GH-4724)
47c0b1f
1st1 commentedon Jan 27, 2018
Merged. Thanks, Mark!
1st1 commentedon Jan 28, 2018
Mark,
Two tests fail on MacOS X now (newly added tests). I'm reverting the change for now. If you figure this out, please re-submit a PR for a quick approval.
======================================================================
ERROR: test_getaddrinfo_ipv6_scopeid (test.test_socket.GeneralModuleTests)
----------------------------------------------------------------------
======================================================================
ERROR: test_getnameinfo_ipv6_scopeid (test.test_socket.GeneralModuleTests)
----------------------------------------------------------------------
1st1 commentedon Jan 28, 2018
New changeset 0ceb717 by Yury Selivanov in branch 'master':
Revert "bpo-32221: makeipaddr(): remove interface part + speedup (GH-4724)" (bpo-5394)
0ceb717
1st1 commentedon Jan 28, 2018
Mark, I think this still land in beta-2. Please try to figure out what's going on on Mac OS (I have no time to take care of this myself).
1st1 commentedon Feb 12, 2018
New changeset 7766b96 by Yury Selivanov (Коренберг Марк) in branch 'master':
bpo-32221: makeipaddr(): remove interface part + speedup (GH-5449) (bpo-5449)
7766b96
1st1 commentedon Feb 12, 2018
New changeset 0442599 by Yury Selivanov (Miss Islington (bot)) in branch '3.7':
bpo-32221: makeipaddr(): remove interface part + speedup (GH-5449) (GH-5449) (bpo-5641)
0442599