Skip to content

Instantly share code, notes, and snippets.

@arturo-source
Created March 11, 2024 10:03
Show Gist options
  • Save arturo-source/63f9226e9c874460574142d5a770a14f to your computer and use it in GitHub Desktop.
Save arturo-source/63f9226e9c874460574142d5a770a14f to your computer and use it in GitHub Desktop.
Golang array map, concurrency problem
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