我正在学习并尝试 Golang 中的
WaitGroup
功能。这是我的代码:
package main
import (
"atomic"
"http"
"log"
"sync"
"time"
)
func makeRequest(n int) {
wg := sync.WaitGroup{}
count := atomic.Int32{}
wg.Add(n)
s := time.Now()
for j := 0; j < n; j++ {
go myGoRoutine(&wg, &count)
}
wg.Wait()
log.Printf("Time Elapsed: %v for %d iterations", time.Since(s), n)
}
func myGoRoutine(wg *sync.WaitGroup, count *atomic.Int32) {
defer wg.Done()
_, err := http.Get("https://jsonplaceholder.typicode.com/todos/1")
if err != nil {
log.Printf("Error: %v", err.Error())
}
count.Add(1)
}
func main() {
cases := []int{1, 10, 100, 1000, 10000}
for _, c := range cases {
makeRequest(c)
}
}
这是输出:
2023/12/28 07:31:34 Time Elapsed: 936.169917ms for 1 iterations
2023/12/28 07:31:34 Time Elapsed: 16.452041ms for 10 iterations
2023/12/28 07:31:34 Time Elapsed: 37.336667ms for 100 iterations
2023/12/28 07:31:36 Time Elapsed: 2.037294792s for 1000 iterations
2023/12/28 07:32:23 Time Elapsed: 47.1717935s for 10000 iterations
由于所有 API 调用都是同时发生的,因此我预计所有 5 种情况所花费的时间即使不相同,也会相似。前 3 种情况确实如此,但 1000 次 API 调用需要 2 秒,10000 次 API 调用需要超过 45 秒。
我对 Golang 中的
WaitGroup
的理解才刚刚几天。很可能我在代码中犯了错误或者我的基本理解不正确。不管怎样,我将不胜感激任何帮助。
func BenchmarkTest_makeRequest(b *testing.B) {
tests := []struct {
makeRequest func(n int)
}{
{
makeRequest: makeRequestWithGoRoutine,
},
{
makeRequest: makeRequestWithoutGoRoutine,
},
{
makeRequest: makeRequestWithoutFunctionCall,
},
}
for _, tt := range tests {
b.Run("test", func(b *testing.B) {
tt.makeRequest(b.N)
})
}
}
BenchmarkTest_makeRequest/test-12 5522967 206.9 ns/op
BenchmarkTest_makeRequest/test#01-12 79312916 15.42 ns/op
BenchmarkTest_makeRequest/test#02-12 163376266 6.478 ns/op
time.Sleep(time.Millisecond * 10)
。参考号如何人为提高CPU使用率func BenchmarkTest_makeRequestWithHighLoad(b *testing.B) {
tests := []struct {
makeRequest func(n int)
}{
{
makeRequest: makeRequestWithGoRoutine,
},
{
makeRequest: makeRequestWithoutGoRoutine,
},
}
for _, tt := range tests {
b.Run("test", func(b *testing.B) {
tt.makeRequest(b.N)
})
}
}
BenchmarkTest_makeRequestWithHighLoad/test-12 2819386 409.7 ns/op
BenchmarkTest_makeRequestWithHighLoad/test#01-12 100 10787388 ns/op
func myGoRoutine(wg *sync.WaitGroup, count *int32) {
defer wg.Done()
atomic.AddInt32(count, 1)
}
func myGoRoutineWithHighLoad(wg *sync.WaitGroup, count *int32) {
defer wg.Done()
time.Sleep(time.Millisecond * 10)
atomic.AddInt32(count, 1)
}
func makeRequestWithGoRoutine(n int) {
wg := sync.WaitGroup{}
var count int32
wg.Add(n)
for j := 0; j < n; j++ {
// go myGoRoutine(&wg, &count)
go myGoRoutineWithHighLoad(&wg, &count)
}
wg.Wait()
}
func makeRequestWithoutGoRoutine(n int) {
wg := sync.WaitGroup{}
var count int32
wg.Add(n)
for j := 0; j < n; j++ {
// myGoRoutine(&wg, &count)
myGoRoutineWithHighLoad(&wg, &count)
}
wg.Wait()
}
func makeRequestWithoutFunctionCall(n int) {
wg := sync.WaitGroup{}
var count int32
wg.Add(n)
for j := 0; j < n; j++ {
count++
wg.Done()
}
wg.Wait()
}