Skip to content

Commit 1f992c8

Browse files
Vildan SafinEnigma228322
authored andcommitted
perf(chunk): Use min instead branch
1 parent a17e3ac commit 1f992c8

2 files changed

Lines changed: 102 additions & 10 deletions

File tree

benchmark/core_slice_bench_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,3 +1013,91 @@ func BenchmarkFromSlicePtrOr(b *testing.B) {
10131013
})
10141014
}
10151015
}
1016+
1017+
func BenchmarkChunkIntSmallDataSmallChunk(b *testing.B) {
1018+
data := make([]int, 100)
1019+
for i := range data {
1020+
data[i] = i
1021+
}
1022+
b.ResetTimer()
1023+
for i := 0; i < b.N; i++ {
1024+
_ = lo.Chunk(data, 3)
1025+
}
1026+
}
1027+
1028+
func BenchmarkChunkIntSmallDataLargeChunk(b *testing.B) {
1029+
data := make([]int, 100)
1030+
for i := range data {
1031+
data[i] = i
1032+
}
1033+
b.ResetTimer()
1034+
for i := 0; i < b.N; i++ {
1035+
_ = lo.Chunk(data, 50)
1036+
}
1037+
}
1038+
1039+
func BenchmarkChunkIntMediumDataSmallChunk(b *testing.B) {
1040+
data := make([]int, 10_000)
1041+
for i := range data {
1042+
data[i] = i
1043+
}
1044+
b.ResetTimer()
1045+
for i := 0; i < b.N; i++ {
1046+
_ = lo.Chunk(data, 7)
1047+
}
1048+
}
1049+
1050+
func BenchmarkChunkIntMediumDataLargeChunk(b *testing.B) {
1051+
data := make([]int, 10_000)
1052+
for i := range data {
1053+
data[i] = i
1054+
}
1055+
b.ResetTimer()
1056+
for i := 0; i < b.N; i++ {
1057+
_ = lo.Chunk(data, 1024)
1058+
}
1059+
}
1060+
1061+
func BenchmarkChunkIntLargeDataSmallChunk(b *testing.B) {
1062+
data := make([]int, 1_000_000)
1063+
for i := range data {
1064+
data[i] = i
1065+
}
1066+
b.ResetTimer()
1067+
for i := 0; i < b.N; i++ {
1068+
_ = lo.Chunk(data, 13)
1069+
}
1070+
}
1071+
1072+
func BenchmarkChunkIntLargeDataLargeChunk(b *testing.B) {
1073+
data := make([]int, 1_000_000)
1074+
for i := range data {
1075+
data[i] = i
1076+
}
1077+
b.ResetTimer()
1078+
for i := 0; i < b.N; i++ {
1079+
_ = lo.Chunk(data, 8192)
1080+
}
1081+
}
1082+
1083+
func BenchmarkChunkStringMediumDataSmallChunk(b *testing.B) {
1084+
data := make([]string, 10_000)
1085+
for i := range data {
1086+
data[i] = "some string"
1087+
}
1088+
b.ResetTimer()
1089+
for i := 0; i < b.N; i++ {
1090+
_ = lo.Chunk(data, 7)
1091+
}
1092+
}
1093+
1094+
func BenchmarkChunkStringMediumDataLargeChunk(b *testing.B) {
1095+
data := make([]string, 10_000)
1096+
for i := range data {
1097+
data[i] = "some string"
1098+
}
1099+
b.ResetTimer()
1100+
for i := 0; i < b.N; i++ {
1101+
_ = lo.Chunk(data, 1024)
1102+
}
1103+
}

slice.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -357,24 +357,28 @@ func Chunk[T any, Slice ~[]T](collection Slice, size int) []Slice {
357357
}
358358

359359
chunksNum := len(collection) / size
360+
extraChunk := 0
360361
if len(collection)%size != 0 {
361-
chunksNum++
362+
extraChunk++
362363
}
363364

364-
result := make([]Slice, 0, chunksNum)
365-
366-
for i := 0; i < chunksNum; i++ {
367-
last := (i + 1) * size
368-
if last > len(collection) {
369-
last = len(collection)
370-
}
365+
result := make([]Slice, 0, chunksNum+extraChunk)
371366

367+
i := 0
368+
for ; i < chunksNum; i++ {
372369
// Copy chunk in a new slice, to prevent memory leak and free memory from initial collection.
373-
newSlice := make(Slice, last-i*size)
374-
copy(newSlice, collection[i*size:last])
370+
newSlice := make(Slice, size)
371+
copy(newSlice, collection[i*size:(i+1)*size])
375372
result = append(result, newSlice)
376373
}
377374

375+
if extraChunk > 0 {
376+
lastStart := i * size
377+
lastChunk := make(Slice, len(collection)-lastStart)
378+
copy(lastChunk, collection[lastStart:])
379+
result = append(result, lastChunk)
380+
}
381+
378382
return result
379383
}
380384

0 commit comments

Comments
 (0)