Skip to content

Avoid spawning thread for trivial getnameinfo calls #14277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jhawthorn
Copy link
Member

When calling getnameinfo we spawn a thread because it may do a slow, blocking reverse-DNS lookup. Spawning a thread is relatively fast (~20µs on my Linux machine) but still an order of magnitude slower than when getnameinfo is simply translating to a numeric IP or port, which, at least in my tests on Linux, doesn't even make a syscall.

This commit adds a fast path for when reverse DNS isn't required: either host isn't being fetched or NI_NUMERICHOST is set AND either the service name isn't required or NI_NUMERICSERV is set. The service name should only need to read /etc/services, which should be fast-ish, but is still I/O so I kept the existing behaviour (it could be on a network fs I guess).

I tested with:

s = TCPSocket.open("www.ruby-lang.org", 80)
500_000.times { Socket.unpack_sockaddr_in(s.getpeername) }

Before: 12.935s
After: 0.338s

When calling getnameinfo we spawn a thread because it may do a slow,
blocking reverse-DNS lookup. Spawning a thread is relatively fast (~20µs
on my Linux machine) but still an order of magnitude slower than when
getnameinfo is simply translating to a numeric IP or port, which, at
least in my tests on Linux, doesn't even make a syscall.

This commit adds a fast path for when reverse DNS isn't required: either
host isn't being fetched or NI_NUMERICHOST is set AND either the
service name isn't required or NI_NUMERICSERV is set. The service name
should only need to read /etc/services, which should be fast-ish, but
is still I/O so I kept the existing behaviour (it could be on a network
fs I guess).

I tested with:

    s = TCPSocket.open("www.ruby-lang.org", 80)
    500_000.times { Socket.unpack_sockaddr_in(s.getpeername) }

Before: 12.935s
After: 0.338s
@jhawthorn jhawthorn requested a review from mame August 20, 2025 03:56
Copy link
Member

@mame mame left a comment

Choose a reason for hiding this comment

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

I was thinking I should do this. Looks good, thanks!

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.

2 participants