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

Merged
merged 1 commit into from
Aug 20, 2025

Conversation

jhawthorn
Copy link
Member

@jhawthorn jhawthorn commented Aug 20, 2025

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!

@jhawthorn jhawthorn merged commit 5c96bbf into ruby:master Aug 20, 2025
86 checks passed
@jhawthorn jhawthorn deleted the getnameinfo_wont_block branch August 20, 2025 18:04
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