Skip to content
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

net: lookup: avoid creating a new goroutine if context is canceled and lookupIPAddr isn't actually resolving #59203

Open
KeiichiHirobe opened this issue Mar 23, 2023 · 2 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@KeiichiHirobe
Copy link
Contributor

KeiichiHirobe commented Mar 23, 2023

Hello,

I've read

go/src/net/lookup.go

Lines 333 to 347 in 0aa14fc

case <-ctx.Done():
// Our context was canceled. If we are the only
// goroutine looking up this key, then drop the key
// from the lookupGroup and cancel the lookup.
// If there are other goroutines looking up this key,
// let the lookup continue uncanceled, and let later
// lookups with the same key share the result.
// See issues 8602, 20703, 22724.
if r.getLookupGroup().ForgetUnshared(lookupKey) {
lookupGroupCancel()
go dnsWaitGroupDone(ch, func() {})
} else {
go dnsWaitGroupDone(ch, lookupGroupCancel)
}
ctxErr := ctx.Err()
and #22724.

I think It's preferable to avoid creating a new goroutine for waiting on a result whenever possible. If the context is canceled and lookupIPAddr isn't actually resolving, there's no need to wait for the result using a new goroutine.

This is how we can achieve this:

  1. Add method ForgetNonFirstChan to internal/singleflight.Group, which signature is
// ForgetNonFirstChan tells the singleflight to forget about a channel if it is not
// for the first invocation for a key.
// Returns whether the channel was forgotten or not.
func (g *Group) ForgetNonFirstChan(key string, ch chan Result) bool 
  1. At lookupIPAddr, when context canceled, call ForgetNonFirstChan and if it returns true, we don't need to wait for the result, and call cancelFn immediately without making a new goroutine.

For example, suppose there is a situation where the first call of LookupIPAddr takes a long time, and then calls for name resolution for the same hostname are made n times with a timeout of 5 seconds. Previously, even after 5 seconds had passed, n+1 goroutines were required, but after my modification, only one goroutine is required.

I wrote a draft implementation on Gerrit

FYI:
I changed the data structure that holds the channels from a slice to a map. This was done to improve the search(ForgetNonFirstChan needs searching) complexity from O(N) to O(1).

@gopherbot gopherbot added this to the Proposal milestone Mar 23, 2023
@gopherbot
Copy link

Change https://go.dev/cl/478895 mentions this issue: net: avoid creating a new goroutine if context is canceled and lookupIPAddr isn't actually resolving

@ianlancetaylor
Copy link
Contributor

I can't see any reason for this to be a proposal, so taking it out of the proposal process.

@ianlancetaylor ianlancetaylor changed the title proposal: net : lookup: avoid creating a new goroutine if context is canceled and lookupIPAddr isn't actually resolving net: lookup: avoid creating a new goroutine if context is canceled and lookupIPAddr isn't actually resolving Mar 24, 2023
@ianlancetaylor ianlancetaylor added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. and removed Proposal labels Mar 24, 2023
@ianlancetaylor ianlancetaylor modified the milestones: Proposal, Backlog Mar 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

3 participants