Skip to content

perf: optimize Zip and ZipBy functions#818

Merged
samber merged 1 commit intosamber:masterfrom
d-enk:perf-zip
Feb 25, 2026
Merged

perf: optimize Zip and ZipBy functions#818
samber merged 1 commit intosamber:masterfrom
d-enk:perf-zip

Conversation

@d-enk
Copy link
Contributor

@d-enk d-enk commented Feb 25, 2026

  • Replace Nth() with NthOrEmpty() to avoid unnecessary error allocation on miss
  • Change make(0, size) + append to make(size) + direct assignment
  • Use uint for loop indices
  • Remove temporary variables in ZipBy functions

This reduces overhead from append operations and structure creation, similar to the Zip5Copy2 optimization pattern.

Reduces code size: +174/-242 lines

- Replace Nth() with NthOrEmpty() to avoid unnecessary error allocation on miss
- Change make(0, size) + append to make(size) + direct assignment
- Use uint for loop indices
- Remove temporary variables in ZipBy functions

This reduces overhead from append operations and structure creation,
similar to the Zip5Copy2 optimization pattern.

Reduces code size: +174/-242 lines
@d-enk
Copy link
Contributor Author

d-enk commented Feb 25, 2026

There is probably no need for this

But to improve performance, you can do something like this

func Zip5My2[A, B, C, D, E any](a []A, b []B, c []C, d []D, e []E) []Tuple5[A, B, C, D, E] {
	minSize, maxSize := MinMax(len(a), len(b), len(c), len(d), len(e))

	result := make([]Tuple5[A, B, C, D, E], maxSize)

	index := uint(0)

	_ = a[minSize-1]
	_ = b[minSize-1]
	_ = c[minSize-1]
	_ = d[minSize-1]
	_ = e[minSize-1]

	_ = result[minSize-1]

	for ; index < minSize; index++ {
		result[index].A = a[index]
		result[index].B = b[index]
		result[index].C = c[index]
		result[index].D = d[index]
		result[index].E = e[index]
	}

	for ; index < maxSize; index++ {
		result[index].A = NthOrEmpty(a, index)
		result[index].B = NthOrEmpty(b, index)
		result[index].C = NthOrEmpty(c, index)
		result[index].D = NthOrEmpty(d, index)
		result[index].E = NthOrEmpty(e, index)
	}

	return result
}

@samber
Copy link
Owner

samber commented Feb 25, 2026

Why do you mount this into memory?

	_ = a[minSize-1]
	_ = b[minSize-1]
	_ = c[minSize-1]
	_ = d[minSize-1]
	_ = e[minSize-1]

	_ = result[minSize-1]

Is there a Go optimization behind?

@samber samber merged commit b9c84bc into samber:master Feb 25, 2026
1 check passed
@d-enk
Copy link
Contributor Author

d-enk commented Feb 25, 2026

Yeap, it eliminates bounds checking in the next cycle

@samber
Copy link
Owner

samber commented Feb 25, 2026

Yes, feel free to create a PR if you see a performance improvement.

(with proper comments to explain the optimizations please!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants