Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
December 29, 2022 04:24 pm GMT

Optimizing Go code with GCCGO for improved performance

One day, my teacher asked me why Go compiled program has terrible perfomance and he kept mentioning about how a good compiler should behave.

Tldr; Check out my demo!

It is using gccgo -O3 -o cool main.go instead of go build main.go.

Basically, you will find that some code could run faster by changing the compiler instead of rewriting the code.

So, we want to turn our code into its peak performance despite getting bugs.

Super gopher

Consider the following code...

package mainimport (    "errors"    "fmt")const limA = 2000type EulerSolution struct {    first   int    second  int    third   int    fourth  int    culprit int}func intPow(n, m int) int {    if m == 0 {        return 1    }    result := n    for i := 2; i <= m; i++ {        result *= n    }    return result}func computeEuler() (EulerSolution, error) {    for e := 1; e < limA; e++ {        for a := 1; a < e; a++ {            var a5 = intPow(a, 5)            for b := 1; b <= a; b++ {                var b5 = intPow(b, 5)                for c := 1; c < b; c++ {                    var c5 = intPow(c, 5)                    for d := 1; d < c; d++ {                        var d5 = intPow(d, 5)                        var e5 = intPow(e, 5)                        var got int = a5 + b5 + c5 + d5                        if got == e5 {                            return EulerSolution{                                first:   a,                                second:  b,                                third:   c,                                fourth:  d,                                culprit: e,                            }, nil                        }                    }                }            }        }    }    return EulerSolution{}, errors.New("Euler solution")}

We know that this code is poorly written. Let's write the another function that produce similar result.

func computeBeastEuler() (EulerSolution, error) {    for e := 1; e < limA; e++ {        var e5 = intPow(e, 5)        for a := 1; a < e; a++ {            var a5 = intPow(a, 5)            for b := 1; b <= a; b++ {                var b5 = intPow(b, 5)                for c := 1; c < b; c++ {                    var c5 = intPow(c, 5)                    for d := 1; d < c; d++ {                        var d5 = intPow(d, 5)                        var got int = a5 + b5 + c5 + d5                        if got == e5 {                            return EulerSolution{                                first:   a,                                second:  b,                                third:   c,                                fourth:  d,                                culprit: e,                            }, nil                        }                    }                }            }        }    }    return EulerSolution{}, errors.New("Euler solution")}

Much better, now we want to prove that the new function, computeBeastEuler, is faster.

go test -bench main_test.go -v=== RUN   Test_computeEuler=== RUN   Test_computeEuler/empty--- PASS: Test_computeEuler (4.19s)    --- PASS: Test_computeEuler/empty (4.19s)=== RUN   Test_computeBeastEuler=== RUN   Test_computeBeastEuler/empty--- PASS: Test_computeBeastEuler (2.51s)    --- PASS: Test_computeBeastEuler/empty (2.51s)PASSok      go-beast-demo   6.705s

It is better, and we expect our go build to do the optimization for us.

go build main.gotime ./main {133 110 84 27 144}real    0m4.371s...

Well, it is not what we expected. The problem is that Go compiler is not focusing on optimization by default. It only focuses on compilation speed.

Now, let me talk about another compiler that will help us get the faster program using the same code.

Let's install gccgo to our machine. Make sure that you are not using Darwin OS!

git clone --branch devel/gccgo git://gcc.gnu.org/git/gcc.git gccgomkdir objdircd objdir../gccgo/configure --prefix=/opt/gccgo --enable-languages=c,c++,go --with-ld=/opt/gold/bin/ldmakemake install

References:
gccgo

Anyway, you might run into some problems with its prerequisites for the compiler.

cd gccgo./contrib/download_prerequisites

The script will download all you need for the gccgo.

Instead, we can just use a dockerfile to help us set up the environment for our new compiler.

# Download base image ubuntu 20.04FROM ubuntu:20.04# Disable Prompt During Packages InstallationARG DEBIAN_FRONTEND=noninteractive# Update Ubuntu Software repositoryRUN apt updateRUN apt-get update -yRUN apt-get install -y gccgoWORKDIR /go/appCOPY . .RUN gccgo -O3 -o cool main.goCMD ["./cool"]

References:
gcc optimize

Inside the container, let's do the benchmarking again!

docker compose builddocker run -it go-beast-mode_app bash

Inside my container, here is what I got.

time ./cool{133 110 84 27 144}real    0m0.906suser    0m0.583ssys     0m0.028s

It is even 2x faster than our computeBeastEuler in time.

In fact, Go can compile blazingly fast, but the trade-off is the lost of performance. If we want to optimize our Go program, then this is an example of what you could try. It will be compiled slower, but the performance is greatly increased along with the slight increase in memory usage.


Original Link: https://dev.to/parmcoder/optimizing-go-code-with-gccgo-for-improved-performance-2d3d

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To