-
Notifications
You must be signed in to change notification settings - Fork 1k
Conversation
91d33f3
to
bc9e9d3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good start 😄
internal/gps/result.go
Outdated
@@ -10,6 +10,10 @@ import ( | |||
"path/filepath" | |||
) | |||
|
|||
// NumDepTreeWorkers determines the number of | |||
// WriteDepTree worker goroutines | |||
var NumDepTreeWorkers = 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add this as a parameter to WriteDepTree()
. We've avoided package global state in gps so far, and want to continue that trend 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
np, I was unsure if you wanted to change the func signature :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep! we haven't stabilized the API yet, so there's no obligation to keep it the same.
internal/gps/result.go
Outdated
worksz := len(projects) | ||
|
||
workChan := make(chan LockedProject, worksz) | ||
doneChan := make(chan error, worksz) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's create some local tuple type here for this message - something like
type done struct {
root ProjectRoot
err error
}
so that we don't have to shoehorn all that information into the error, and we can pass back up the lower-level errors unmodified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, no problem, I didn't want to add too much complexity, didn't know to which extent you want this to be modified. I get your point, will do :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for sure, that's how we figure these things out 😄
internal/gps/result.go
Outdated
projects := l.Projects() | ||
worksz := len(projects) | ||
|
||
workChan := make(chan LockedProject, worksz) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so, my default position is that there are only two correct values for channel sizes: 0, and 1. while we could do it this way, it's creating problems elsewhere (like early termination, noted below). i think a refactored implementation that uses unbuffered channels would give us tighter control over such things.
internal/gps/result.go
Outdated
close(workChan) | ||
|
||
for i := 0; i < worksz; i++ { | ||
err := <-doneChan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as-written, this could interleave poorly:
- one goroutine sends experiences and sends an error while other(s) still writing
- control receives the error, and begins
os.RemoveAll()
- other goroutine(s) are trying to write to dirs that are disappearing from underneath them
additionally, it's also crucial that we guarantee the worker goroutines have terminated by the time the WriteDepTree()
func returns.
switching to an unbuffered channel approach will, i think, make it easier to do the necessary flow control here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so, what you are saying is basically this:
we should always wait for all worker routines to finish
if some routine reports an error, note the error and wait for others to finish
return a fmt.Errorf filled with info of all errs (gathered from the tuples received - if any)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will refactor and make another pr tomorrow and we can discuss further :)
bc9e9d3
to
d010acc
Compare
@sdboyer While doing the refactor I kinda got the idea that If you can see what I wanted to do with Or should the tree := gps.NewDepTree(gps.DepTreeConfig{
Basedir: "...",
Lock: ...,
SourceManager: ...,
})
err := tree.Write(true, 2) // stripVendor, workerCount
... Or do you just want to leave it as it is, but it would be ugly? I hope you can see what I'm getting at |
yes, i see the general idea of what you're going for. as long as we're talking about the signature design, it's worth noting that we'll also need to consider that the we have a few options, not all mutually exclusive:
i'm actually inclined to stick with 3+4, because i don't see us adding much more in the way of params to this in the future, and we have to balance the convenience of this one method with cluttering the overall |
I see. |
(sorry, I realize this is pulling a 180 on the concurrency thing) probably start with just plain fixed, and then maybe we make some adjustments based on GOMAXPROCS. if you think that splitting it up into some smaller funcs will help, then sure, go for it. as long as they're not exported, there's no general rules design rules in place - we can discuss the design as you go. |
87bc95f
to
74dedc7
Compare
@sdboyer when you have time could you look at the latest update |
Defered workChan close Removed commented out code Decoupled concurrency code from the WriteDepTree func to workerPool All errors are now being reported and WriteDepTree decides how to act (currently calls removeAll) Broken down WriteDepTree to child functions in order to receive feedback if on the right track Fixed accidental err race condition gps.WriteDepTree now writes vendor/ tree in parallel with configurable number of worker routines
74dedc7
to
d8fd115
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for delayed response! looks like we're heading in a better direction, but we're still missing semantics for aborting early in the event of an error on any individual attempt.
note that whatever approach you take should ideally also be easy to extend with a context.Context()
for explicit cancellation semantics, later.
sorry, this ended up being finished up in another PR 😢 |
Fixes #895
gps.WriteDepTree
now writes vendor/ tree concurrently withconfigurable number of worker routines.
Added
BenchmarkCreateVendorTreeParallel
benchmark whichruns 1/3 faster than when running sequentially.
Your feedback is welcome.
I added
NumDepTreeWorkers
as a global at this point will change it based on the feedback.