Skip to content

Optimization options

Jonathan Van der Cruysse edited this page Jan 10, 2017 · 2 revisions

Options

Enabling compiler optimizations is actually pretty easy. The process consists of passing one or two additional flags to the compiler. Here's a list of common optimization options.

  • -O0: no optimizations whatsoever
  • -O1: simple optimizations
  • -O2: conservative (intra-procedural) optimizations
  • -O3: aggressive (inter-procedural) optimizations
  • -g: retain constructs that are intended for debugging, such as assertions
  • -Og: shorthand for -O1 -g

By default, ecsc will use the -Og optimization level. Once any of the above optimization options are given, ecsc will no longer make this assumption. Therefore, providing only -O0/-O1/-O2/-O3 gives ecsc permission to remove debugging code (since -g was not given). Analogously, using -g only will keep ecsc from removing debugging code, but it will also keep ecsc from applying any optimizations, as no optimization level was given.

Examples

Here's a short example that compares the different optimization options. Your mileage may vary, as run-time performance depends on lots of different factors: your hardware, the JIT, the program that is compiled, etc.

tests/cs/fractal$ mkdir -p bin
tests/cs/fractal$ mcs Fractal.cs -out:bin/Fractal.exe
tests/cs/fractal$ time mono bin/Fractal.exe
Mandelbrot:6839743 Julia:6449238

real    0m0.224s
user    0m0.220s
sys     0m0.000s
tests/cs/fractal$ ecsc Fractal.cs -platform clr -Og
tests/cs/fractal$ time mono bin/Fractal.exe
Mandelbrot:6839743 Julia:6449238

real    0m0.215s
user    0m0.208s
sys     0m0.004s
tests/cs/fractal$ ecsc Fractal.cs -platform clr -O2
tests/cs/fractal$ time mono bin/Fractal.exe
Mandelbrot:6839743 Julia:6449238

real    0m0.215s
user    0m0.212s
sys     0m0.004s
tests/cs/fractal$ ecsc Fractal.cs -platform clr -O3
tests/cs/fractal$ time mono bin/Fractal.exe
Mandelbrot:6839743 Julia:6449238

real    0m0.107s
user    0m0.104s
sys     0m0.000s

It's interesting to see that mcs's results are quite similar to ecsc's for the -Og and -O2 builds. But the -O3 build clearly blows all other executables out of the water in terms of performance.

Tool versions

The versions of the tools that were used to produce these measurements are listed below. I used a local build of ecsc, which explains why its version number looks funny. Almost all of ecsc's optimizations are implemented by Flame, though. So you can just look at Flame's version number instead.

$ mono --version
Mono JIT compiler version 4.6.2 (Stable 4.6.2.16/ac9e222 Tue Jan  3 11:48:26 UTC 2017)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           __thread
	SIGSEGV:       altstack
	Notifications: epoll
	Architecture:  amd64
	Disabled:      none
	Misc:          softdebug 
	LLVM:          supported, not enabled.
	GC:            sgen
$ mcs --version
Mono C# compiler version 4.6.2.0
$ ecsc --version
ecsc version 1.0.6219 (based on Flame 0.9.2)
EC# parser: Loyc 2.4.3
Platform: Unix 4.8.0.32
Console: xterm-256color
You can check for new releases at https://github.com/jonathanvdc/ecsc/releases
Thanks for using the EC# compiler! Have fun writing code.
ecsc: nothing to compile: no input files

Taking a look under the hood

If you want ecsc to explain which (-O3) optimizations it performed, then you can use the -Rinline and -Rscalarrepl, which turn on optimization remarks for the inlining and scalar replacement of aggregates pass, respectively.

tests/cs/fractal$ ecsc Fractal.cs -platform clr -O3 -Rinline -Rscalarrepl

Fractal.cs:94:21: pass remark: inlined direct call to 'complex'. [-Rinline]

    complex num = new complex(x, y);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Fractal.cs:99:33: pass remark: inlined direct call to 'square'. [-Rinline]

    accum = accum.square();
            ^~~~~~~~~~~~~~ 

Fractal.cs:100:25: pass remark: inlined direct call to '+'. [-Rinline]

    accum += num;
    ^~~~~~~~~~~~ 

Fractal.cs:101:29: pass remark: inlined direct call to 'sqabs'. [-Rinline]

    if (accum.sqabs() > limit)
        ^~~~~~~~~~~~~         

Fractal.cs:85:32: pass remark: replaced 7 aggregates by scalars. (recursion depth: 1) [-Rscalarrepl]

    public override double Render()
                           ^~~~~~  

Fractal.cs:127:13: pass remark: inlined direct call to 'complex'. [-Rinline]

    complex seed = new complex(Real, Imaginary);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Fractal.cs:136:21: pass remark: inlined direct call to 'complex'. [-Rinline]

    complex accum = new complex(m, n);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Fractal.cs:142:29: pass remark: inlined direct call to 'sqabs'. [-Rinline]

    if (accum.sqabs() > limit)
        ^~~~~~~~~~~~~         

Fractal.cs:145:33: pass remark: inlined direct call to '+'. [-Rinline]

    accum = accum.square() + seed;
            ^~~~~~~~~~~~~~~~~~~~~ 

Fractal.cs:121:32: pass remark: replaced 3 aggregates by scalars. [-Rscalarrepl]

    public override double Render()
                           ^~~~~~  

Fractal.cs:145:33: pass remark: recursively inlined direct call to 'square'. (recursion depth: 1) [-Rinline]

    accum = accum.square() + seed;
            ^~~~~~~~~~~~~~        

Fractal.cs:121:32: pass remark: replaced 3 aggregates by scalars. (recursion depth: 1) [-Rscalarrepl]

    public override double Render()
                           ^~~~~~  

Fractal.cs:121:32: pass remark: replaced 2 aggregates by scalars. (recursion depth: 2) [-Rscalarrepl]

    public override double Render()
                           ^~~~~~  

Clone this wiki locally