Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doubt about goroutine with GOMAXPROCS limitation with benchmarking test #41905

Closed
andreleoni opened this issue Oct 10, 2020 · 4 comments
Closed

Comments

@andreleoni
Copy link

What version of Go are you using (go version)?

$ go version go1.15 linux/amd64

Does this issue reproduce with the latest release?

I don't know.

What operating system and processor architecture are you using (go env)?

go env Output

GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/andre/.cache/go-build"
GOENV="/home/andre/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/andre/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/andre/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/andre/Documents/golang-parallel/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build117438849=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I am trying to realize a benchmarking between the usage of GOROUTINE with One or Four processors, but my desired behavior is not being reproduced.

I ran this benchmarking.

package main

import (
	"runtime"
	"sync"
	"testing"
	"time"
)

const arraySize = 10

func BenchmarkOneProcessor(t *testing.B) {
	runtime.GOMAXPROCS(1)

	t.Run("Parallel", func(t *testing.B) {
		t.Helper()

		executionParallel("one")
	})

	t.Run("Sync", func(t *testing.B) {
		t.Helper()

		executionSequential("one")
	})
}

func BenchmarkManyProcessors(t *testing.B) {
	runtime.GOMAXPROCS(4)

	t.Run("Parallel", func(t *testing.B) {
		t.Helper()

		executionParallel("more")
	})

	t.Run("Sync", func(t *testing.B) {
		t.Helper()

		executionSequential("more")
	})
}

func doSomeExternalServiceAction() {
	time.Sleep(10 * time.Millisecond)
}

func executionParallel(s string) {
	var wg sync.WaitGroup
	i := 1

	for i < arraySize {
		wg.Add(1)

		go func(wg *sync.WaitGroup, i int) {
			defer wg.Done()

			doSomeExternalServiceAction()
		}(&wg, i)

		i++
	}

	wg.Wait()
}

func executionSequential(s string) {
	i := 1

	for i < arraySize {
		func() {
			doSomeExternalServiceAction()
		}()

		i++
	}
}

What did you expect to see?

The result of BenchmarkManyProcessors/Parallel-4 being faster than the BenchmarkOneProcessor/Parallel-4.

What did you see instead?

The result of BenchmarkOneProcessor is equal to the execution of many processors.

goos: linux
goarch: amd64
pkg: golang-parallel
BenchmarkOneProcessor/Parallel-4         	1000000000	         0.0102 ns/op
BenchmarkOneProcessor/Sync-4             	1000000000	         0.0916 ns/op
BenchmarkManyProcessors/Parallel-4       	1000000000	         0.0102 ns/op
BenchmarkManyProcessors/Sync-4           	1000000000	         0.0916 ns/op
PASS
ok  	golang-parallel	1.990s
@AlexRouSg
Copy link
Contributor

Try changing your benchmarks to look like:

for n := 0; n < t.N; n++ {
    executionParallel("more")
}

@andreleoni
Copy link
Author

Thanks for the answer @AlexRouSg , so, I think that my doubt is related with the time that is executed the benchmarkers...

For example, If I have 4 processors, I should run this much faster than with only one processor.

Anyway, your suggestion left my test better, thank you very much

@AlexRouSg
Copy link
Contributor

AlexRouSg commented Oct 10, 2020

Sorry forgot to add, run with go test -cpu=1,4 instead of using runtime.GOMAXPROCS(4)
Also replace time.Sleep with actual work

e.g. I get

BenchmarkProcessor
BenchmarkProcessor/Parallel
BenchmarkProcessor/Parallel           	     352	   3326453 ns/op	      16 B/op	       1 allocs/op
BenchmarkProcessor/Parallel-2         	     709	   1948884 ns/op	      16 B/op	       1 allocs/op
BenchmarkProcessor/Parallel-4         	     676	   1896059 ns/op	      35 B/op	       1 allocs/op
BenchmarkProcessor/Sync
BenchmarkProcessor/Sync               	     355	   3292156 ns/op	       0 B/op	       0 allocs/op
BenchmarkProcessor/Sync-2             	     363	   3317786 ns/op	       0 B/op	       0 allocs/op
BenchmarkProcessor/Sync-4             	     348	   3721790 ns/op	       0 B/op	       0 allocs/op

@andreleoni
Copy link
Author

andreleoni commented Oct 11, 2020

Thank you for the explanations.
I will write an article about it.

I realized that depending of the registers counter, create many goroutines is only more expensive for the server to execute.

I think with that, I can continue with my studies.

Again, thank you for your time to explain. it would take me a long time to get to know -cpu from go test command.

@golang golang locked and limited conversation to collaborators Oct 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants