-
-
Save arturo-source/63f9226e9c874460574142d5a770a14f to your computer and use it in GitHub Desktop.
Golang array map, concurrency problem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"sync" | |
"time" | |
) | |
func Map[T1, T2 any](arr []T1, f func(item T1, index int) T2) []T2 { | |
arrT2 := make([]T2, len(arr)) | |
for i, t := range arr { | |
t2 := f(t, i) | |
arrT2[i] = t2 | |
} | |
return arrT2 | |
} | |
func MapConcurrent[T1, T2 any](arr []T1, f func(item T1, index int) T2) []T2 { | |
var wg sync.WaitGroup | |
wg.Add(len(arr)) | |
arrT2 := make([]T2, len(arr)) | |
for i, t := range arr { | |
go func() { | |
t2 := f(t, i) | |
arrT2[i] = t2 | |
wg.Done() | |
}() | |
} | |
wg.Wait() | |
return arrT2 | |
} | |
func MapConcurrentWorkerPool[T1, T2 any](arr []T1, f func(item T1, index int) T2) []T2 { | |
arrT2 := make([]T2, len(arr)) | |
const N_WORKERS = 10 | |
type indexT1 struct { | |
index int | |
t1 T1 | |
} | |
type indexT2 struct { | |
index int | |
t2 T2 | |
} | |
inputs := make(chan indexT1, N_WORKERS) | |
results := make(chan indexT2, N_WORKERS) | |
var wg sync.WaitGroup | |
wg.Add(N_WORKERS) | |
worker := func() { | |
for t1 := range inputs { | |
t2 := f(t1.t1, t1.index) | |
results <- indexT2{t1.index, t2} | |
} | |
wg.Done() | |
} | |
for range N_WORKERS { | |
go worker() | |
} | |
go func() { | |
wg.Wait() | |
close(results) | |
}() | |
go func() { | |
for i, t := range arr { | |
inputs <- indexT1{i, t} | |
} | |
close(inputs) | |
}() | |
for t2 := range results { | |
arrT2[t2.index] = t2.t2 | |
} | |
return arrT2 | |
} | |
type Number struct { | |
a int | |
} | |
func main() { | |
const n = 10000000 | |
arr := make([]Number, 0, n) | |
for i := range n { | |
arr = append(arr, Number{i}) | |
} | |
returnInt := func(t Number, index int) int { | |
return t.a | |
} | |
func() { | |
defer timer("normal map")() | |
Map(arr, returnInt) | |
}() | |
func() { | |
defer timer("infinite goroutines map")() | |
MapConcurrent(arr, returnInt) | |
}() | |
func() { | |
defer timer("worker pool map")() | |
MapConcurrentWorkerPool(arr, returnInt) | |
}() | |
} | |
func timer(name string) func() { | |
start := time.Now() | |
return func() { | |
fmt.Printf("%s took %v\n", name, time.Since(start)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment