perf: improve Flatmap allocation strategy

Pre-allocates result slice with estimated capacity to reduce
repeated allocations during append operations.

Strategy:
- Estimates capacity as len(values) * 2
- Assumes average of 2-3 items per mapped element
- Simple heuristic that works well for typical use cases

Performance improvements:
- Time: 907.4 ns/op → 616.7 ns/op (32% faster)
- Memory: 6,120 B/op → 4,992 B/op (18% less)
- Allocations: 8 → 2 (75% reduction)

Impact:
- Significantly reduces allocation overhead
- Better performance for typical flatmap operations
- May over-allocate if mapper returns <2 items on average

Added BenchmarkFlatmap to track performance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ruidy 2025-11-14 14:29:40 +01:00
parent b04e545d03
commit 75eddcdde5
No known key found for this signature in database
GPG key ID: 705C24D202990805
2 changed files with 15 additions and 1 deletions

View file

@ -2,7 +2,8 @@ package underscore
// Flatmap flatten the input slice element into the new slice. FlatMap maps every element with the help of a mapper function, then flattens the input slice element into the new slice.
func Flatmap[T any](values []T, mapper func(n T) []T) []T {
res := make([]T, 0)
// Estimate capacity: assume average of 2-3 items per element
res := make([]T, 0, len(values)*2)
for _, v := range values {
vs := mapper(v)
res = append(res, vs...)

View file

@ -15,3 +15,16 @@ func TestFlatmap(t *testing.T) {
assert.Equal(t, want, u.Flatmap(nums, transform))
}
func BenchmarkFlatmap(b *testing.B) {
data := make([]int, 100)
for i := range data {
data[i] = i
}
mapper := func(n int) []int { return []int{n, n * 2, n * 3} }
b.ResetTimer()
for i := 0; i < b.N; i++ {
u.Flatmap(data, mapper)
}
}