英文:
Goroutine performance
问题
我开始学习Go语言,它很有趣也很容易。但是在使用goroutine时,我没有看到性能上的明显改进。
如果我尝试在两个函数中连续两次添加100万个数字:
package main
import (
"fmt"
"time"
)
var sumA int
var sumB int
func fSumA() {
for i := 0; i < 1000000; i++ {
sumA += i
}
}
func fSumB() {
for i := 0; i < 1000000; i++ {
sumB += i
}
}
func main() {
start := time.Now()
fSumA()
fSumB()
sum := sumA + sumB
fmt.Println("Elapsed time", time.Since(start))
fmt.Println("Sum", sum)
}
这需要5毫秒。
当我尝试使用两个goroutine做同样的事情时:
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
var sumA int
var sumB int
func fSumA() {
for i := 0; i < 1000000; i++ {
sumA += i
}
wg.Done()
}
func fSumB() {
for i := 0; i < 1000000; i++ {
sumB += i
}
wg.Done()
}
func main() {
start := time.Now()
wg.Add(2)
go fSumA()
go fSumB()
wg.Wait()
sum := sumA + sumB
fmt.Println("Elapsed time", time.Since(start))
fmt.Println("Sum", sum)
}
我得到了差不多相同的结果,5毫秒。我的电脑是MacBook Pro(Core 2 Duo)。我没有看到任何性能改进。也许是处理器的原因?
英文:
I have started to learn Go, it's fun and easy. But working with goroutines I have seen little benefit in performance.
If I try to sequentially add 1 million numbers two times in 2 functions:
package main
import (
"fmt"
"time"
)
var sumA int
var sumB int
func fSumA() {
for i := 0; i < 1000000; i++ {
sumA += i
}
}
func fSumB() {
for i := 0; i < 1000000; i++ {
sumB += i
}
}
func main() {
start := time.Now()
fSumA()
fSumB()
sum := sumA + sumB
fmt.Println("Elapsed time", time.Since(start))
fmt.Println("Sum", sum)
}
It takes 5 ms.
MacBook-Pro-de-Pedro:hello pedro$ ./bin/hello
Elapsed time 5.724406ms
Suma total 999999000000
MacBook-Pro-de-Pedro:hello pedro$ ./bin/hello
Elapsed time 5.358165ms
Suma total 999999000000
MacBook-Pro-de-Pedro:hello pedro$ ./bin/hello
Elapsed time 5.042528ms
Suma total 999999000000
MacBook-Pro-de-Pedro:hello pedro$ ./bin/hello
Elapsed time 5.469628ms
Suma total 999999000000
When I try to do the same thing with 2 goroutines:
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
var sumA int
var sumB int
func fSumA() {
for i := 0; i < 1000000; i++ {
sumA += i
}
wg.Done()
}
func fSumB() {
for i := 0; i < 1000000; i++ {
sumB += i
}
wg.Done()
}
func main() {
start := time.Now()
wg.Add(2)
go fSumA()
go fSumB()
wg.Wait()
sum := sumA + sumB
fmt.Println("Elapsed time", time.Since(start))
fmt.Println("Sum", sum)
}
I get more or less the same result, 5 ms. My computer is a MacBook pro (Core 2 Duo). I don't see any performance improvement. Maybe is the processor?
MacBook-Pro-de-Pedro:hello pedro$ ./bin/hello
Elapsed time 5.258415ms
Suma total 999999000000
MacBook-Pro-de-Pedro:hello pedro$ ./bin/hello
Elapsed time 5.528498ms
Suma total 999999000000
MacBook-Pro-de-Pedro:hello pedro$ ./bin/hello
Elapsed time 5.273565ms
Suma total 999999000000
MacBook-Pro-de-Pedro:hello pedro$ ./bin/hello
Elapsed time 5.539224ms
Suma total 999999000000
答案1
得分: 3
以下是对你提供的内容的中文翻译:
这里是如何使用Golang自带的基准测试工具进行测试的:
创建一个测试Go文件(例如main_test.go
)。
注意:文件的结尾必须是
_test.go
。
将以下代码复制到文件中,或者创建自己的基准测试代码:
package main
import (
"sync"
"testing"
)
var GlobalInt int
func BenchmarkCount(b *testing.B) {
var a, c int
count(&a, b.N)
count(&c, b.N)
GlobalInt = a + c // 确保结果实际被使用
}
func count(a *int, max int) {
for i := 0; i < max; i++ {
*a += i
}
}
var wg sync.WaitGroup
func BenchmarkCountConcurrent(b *testing.B) {
var a, c int
wg.Add(2)
go countCon(&a, b.N)
go countCon(&c, b.N)
wg.Wait()
GlobalInt = a + c // 确保结果实际被使用
}
func countCon(a *int, max int) {
for i := 0; i < max; i++ {
*a += i
}
wg.Done()
}
使用以下命令运行测试:
go test -bench .
在我的Mac上的结果为:
$ go test -bench .
BenchmarkCount-8 500000000 3.50 ns/op
BenchmarkCountConcurrent-8 2000000000 1.98 ns/op
PASS
ok MyPath/MyPackage 6.309s
最重要的值是每次操作的时间(time/op),数值越小越好。这里正常计数为3.5 ns/op,并发计数为1.98 ns/op。
编辑:
你可以在golang的测试和基准测试文档中了解更多信息。
英文:
Here how you can test this with the golangs own benchmark tool:
Create a test go file (e.g. main_test.go
).
> Note: _test.go
has to be the file ending!
Copy the following code there or create your own Benchmarks:
package main
import (
"sync"
"testing"
)
var GlobalInt int
func BenchmarkCount(b *testing.B) {
var a, c int
count(&a, b.N)
count(&c, b.N)
GlobalInt = a + c // make sure the result is actually used
}
func count(a *int, max int) {
for i := 0; i < max; i++ {
*a += i
}
}
var wg sync.WaitGroup
func BenchmarkCountConcurrent(b *testing.B) {
var a, c int
wg.Add(2)
go countCon(&a, b.N)
go countCon(&c, b.N)
wg.Wait()
GlobalInt = a + c // make sure the result is actually used
}
func countCon(a *int, max int) {
for i := 0; i < max; i++ {
*a += i
}
wg.Done()
}
Run with:
go test -bench .
Result on my Mac:
$ go test -bench .
BenchmarkCount-8 500000000 3.50 ns/op
BenchmarkCountConcurrent-8 2000000000 1.98 ns/op
PASS
ok MyPath/MyPackage 6.309s
Most important value is the time/op. The smaller the better. Here 3.5 ns/op for normal counting, 1.98 ns/op for concurrent counting.
EDIT:
Here you can read up on golang Testing and Benchmark.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论