Improve multi stop plan unit generation#39
Conversation
eb7497f to
c21c0cf
Compare
merschformann
left a comment
There was a problem hiding this comment.
In which state is this? 🤔
|
@merschformann I want to do some further benchmarking. I'll ping you all again once that is done |
1466b49 to
fcbc3d3
Compare
|
🤔 linter |
|
Waiting on #47 to fix some benchmark tests |
fcbc3d3 to
78decc8
Compare
merschformann
left a comment
There was a problem hiding this comment.
Looks good. Just left some thoughts, nothing blocking at all. Should we finally merge this?
| @@ -109,10 +113,13 @@ func SolutionMoveStopsGenerator( | |||
| } | |||
|
|
|||
| // TODO: we can reuse the stopPositions slice from m | |||
There was a problem hiding this comment.
I think you can remove the TODO now, right?
| ) | ||
| } | ||
|
|
||
| func recSequenceGenerator( |
There was a problem hiding this comment.
Maybe we can leave a comment on the func or fully write out the rec as recursive? I was confused for a minute trying to understand what this func now records. 😅
Or am I missing a point here? 🤔
| if len(sequence) == len(stops) { | ||
| if atomic.AddInt64(maxSequences, -1) >= 0 { | ||
| yield(slices.Clone(sequence)) | ||
| nStops := len(stops) |
There was a problem hiding this comment.
Technically, this can be moved down a bit, right? Not that it will matter much though. 😹
| stopOrder = stopOrder[:1] | ||
| stopOrder[0] = stopIdx |
There was a problem hiding this comment.
It kind of makes sense that this is faster (I assume). I wonder whether it would make sense to introduce a helper func to make the intention more obvious. Something like:
func recycleSlice(s *[]int, n int) {
*s = (*s)[:n]
}Then again, this may defeat the purpose. 😅
Adding comments all over the place like this is probably also not great:
// we recycle the slice instead of creating a new one for performance reasons
stopOrder = stopOrder[:1]
stopOrder[0] = stopIdxI suppose in a performance driven code-base it's fine like it is. What do you think @dirkschumacher ?
There was a problem hiding this comment.
Just FYI: a quick benchmark on the func approach yields this to me, but double check me as I am a bit side-tracked right now:
goos: linux
goarch: amd64
pkg: xxx
cpu: AMD Ryzen 7 5800H with Radeon Graphics
BenchmarkRecycleInline-16 1000000000 1.877 ns/op 8 B/op 0 allocs/op
BenchmarkRecycleFunction-16 1000000000 1.164 ns/op 8 B/op 0 allocs/op
BenchmarkRecycleNew-16 91827982 12.27 ns/op 16 B/op 1 allocs/op
PASSBased on this code:
package recycle_slice_test
import "testing"
func recycleSlice(s *[]int, n int) {
*s = (*s)[:n]
}
func BenchmarkRecycleInline(b *testing.B) {
slice := make([]int, b.N)
value := 20
for i := 0; i < b.N; i++ {
slice = slice[:1]
slice[0] = value
}
}
func BenchmarkRecycleFunction(b *testing.B) {
slice := make([]int, b.N)
value := 20
for i := 0; i < b.N; i++ {
recycleSlice(&slice, 1)
slice[0] = value
}
}
func BenchmarkRecycleNew(b *testing.B) {
slice := make([]int, b.N)
value := 20
for i := 0; i < b.N; i++ {
slice = make([]int, 1)
slice[0] = value
}
}There was a problem hiding this comment.
I personally find
stopOrder = stopOrder[:1]
stopOrder[0] = stopIdxrelatively clear without a comment.
Explored a bit to reduce some overhead when generating sequences for move generation. In addition this has the effect that we don't spawn go routines so deep in the search.
Below are two smaller benchmark tests. The full set I cannot yet run until #47 is fixed, but this already captures some of the benefits here as it's mostly about allocations.