I've read all files in order for 30 minutes, they are from many different popular repos, it's not a fair random sample but it's easy to search and I didn't thought it would make a difference.
Applicable:
- 38: func(a, b T) int { return cmp.Compare(a.d, b.d) }
- 27: func(a, b T) int { if a.d < b.d { return constX } if a.d > b.d { return constY } return 0 }
- 10: func(a, b T) int { return strings.Compare(a.d, b.d) }
- 7: func(a, b T) int { return cmp.Compare(a.InlinableGetter(), b.InlinableGetter()) }
- 4: func(a, b T) int { if a.InlinableGetter() < b.InlinableGetter() { return constX } if a.InlinableGetter() > b.InlinableGetter() { return constY } return 0 }
- 3: cmp.Compare
- 1: func (a, b T) int { return int(a.d) - int(b.d) } // no-op conv; type T int
We could cheat:
- 13: func(a, b T) int { return bytes.Compare(a.d, b.d) }
Maybe but I don't care right now:
- 3: func(a, b T) int { if reversed { return cmp.Compare(a.d, b.d) } return cmp.Compare(b.d, a.d) }
- 2: func(a, b T) int { if a.InlinableGetterWhichSprintfAConstantPrefix() < b.InlinableGetterWhichSprintfAConstantPrefix() { return constX } if a.InlinableGetterWhichSprintfAConstantPrefix() > b.InlinableGetterWhichSprintfAConstantPrefix() { return constY } return 0 }
Non-Applicable:
- 46: Sort by a secondary keys on equality
- 6: func(a, b []T) int { if a[const] < b[const] { return constX } if a[const] > a[const] { return constY } return 0 }
- 6: Complex Logic
- 5: func(a, b T) int { return cmp.Compare(a.aMap[k], b.aMap[k]) }
- 3: runtimeClosure
- 3: slices.Compare
- 3: func(a, b T) int { if reversed { return cmp.Compare(a.aMap[k], b.aMap[k]) } return cmp.Compare(b.aMap[k], a.aMap[k]) }
- 2: func(a, b T) int { if a.d.Less(b.d) { return constX } if b.d.Less(a.d) { return constY } return 0 }
- 2: does io (fetch from DB)
- 1: func(a, b T) int { return strings.Compare(a.avail - a.free, b.avail - b.free) }
- 1: func(a, b T) int { return cmp.Compare(a.StringConcatMultipleFields(), b.StringConcatMultipleFields()) }
Data not conveyed in the results:
- The compare function is not always a literal, sometimes it's a method used as a function: slices.SortFunc(s, type.CmpMethod)
- The selectors are varied and different, altho it is not much harder to do a solved pointer path extractor.
- I have never seen a 3 indirects pointer path.
Notes:
- func(a, b T) int { if a.d < b.d { return constX } if a.d > a.d { return constY } return 0 } // Good candidate for a modernizer.
- cmp.Compare // this is not a mistake, is NaN handling different ? idk why someone wouldn't use slices.Sort.
- I have seen - to invert the result of cmp.Compare a single time ! Swapping a and b is more common. It ended up not being listed in Applicable because they also used cmp.Or so it is « Sort by a secondary keys on equality ».
- About « we could cheat » we could lie when we generate the pointer path `pointerPath[T, string]{...}` rather than `pointerPath[T, []byte]{...}` and optimize these too.
- Surprisingly the 2 ifs 3 returns form was never written differently (I write it -1 0 1 myself).
Conclusion
If we only match {cmp,bytes,strings}.Compare(a.pointerPath, b.pointerPath) we will optimize 64% of the optimizable slices.SortFunc, 37% of all slices.SortFunc.
If we also match the 2 ifs 3 returns form the numbers go to 94% and 54%.
This detection should run after inlining, most getters end up returning a single field.