Goroutine性能

huangapple go评论77阅读模式
英文:

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 (
	&quot;fmt&quot;
	&quot;time&quot;
)

var sumA int
var sumB int

func fSumA() {
	for i := 0; i &lt; 1000000; i++ {
		sumA += i
	}
}

func fSumB() {
	for i := 0; i &lt; 1000000; i++ {
		sumB += i
	}
}

func main() {
	start := time.Now()
	fSumA()
	fSumB()
	sum := sumA + sumB
	fmt.Println(&quot;Elapsed time&quot;, time.Since(start))
	fmt.Println(&quot;Sum&quot;, 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 (
	&quot;fmt&quot;
	&quot;sync&quot;
	&quot;time&quot;
)

var wg sync.WaitGroup

var sumA int
var sumB int

func fSumA() {
	for i := 0; i &lt; 1000000; i++ {
		sumA += i
	}
	wg.Done()
}

func fSumB() {
	for i := 0; i &lt; 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(&quot;Elapsed time&quot;, time.Since(start))
	fmt.Println(&quot;Sum&quot;, 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 (
	&quot;sync&quot;
	&quot;testing&quot;
)

var GlobalInt int

func BenchmarkCount(b *testing.B) {
	var a, c int
	count(&amp;a, b.N)
	count(&amp;c, b.N)
	GlobalInt = a + c // make sure the result is actually used
}

func count(a *int, max int) {
	for i := 0; i &lt; max; i++ {
		*a += i
	}
}

var wg sync.WaitGroup

func BenchmarkCountConcurrent(b *testing.B) {
	var a, c int
	wg.Add(2)
	go countCon(&amp;a, b.N)
	go countCon(&amp;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 &lt; 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.

huangapple
  • 本文由 发表于 2017年8月2日 01:20:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/45444108.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定