Optimizing OSS Linux Applications for your Computer
One of the huge benefits of running Open Source software under GNU/Linux is the ability to fine tune applications for the machine or set of machines that they will run on. This article tells you how to accomplish this by compiling your apps with special cpu & architecture tuning parameters.
While this tuning is possible using pretty much any build system, this article only covers open source applications that are distributed using the automake/autoconfigure build system.
Step 1: Identifying the tunings for your architecture
To find out the best settings for your processor & machine type, download this handy shell script from the Internet (thanks to the folks @ pixelbeat.org): http://www.pixelbeat.org/scripts/gcccpuopt
Then run it on the machine you are building for to get the results:
kain@slickbox:~> wget http://www.pixelbeat.org/scripts/gcccpuopt --17:41:10-- http://www.pixelbeat.org/scripts/gcccpuopt => `gcccpuopt' Resolving www.pixelbeat.org... 220.127.116.11 Connecting to www.pixelbeat.org|18.104.22.168|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 11,425 (11K) [text/plain] 100%[====================================>] 11,425 50.74K/s 17:41:10 (50.57 KB/s) - `gcccpuopt' saved [11425/11425] kain@slickbox:~> sh gcccpuopt -march=prescott -mfpmath=sse
As you can see, the current GCC (GNU compiler) tunings for my centrino duo laptop are printed by the script. We’ll take note of these settings for the future.
Step 2: Obtain the source code to the desired application.
Visit the web site of the program you wish to compile, download its source archive, and extract it into your desired build directory. In this example, I’ll be compiling the core component of the compiz 3D window manager. As a processor-intensive application, this is a good example of the kind of program one should optimize for their system.
Step 3: Configure the build for optimization, build, & install
I now configure the build using the settings from above
kain@slickbox:~/software/compiz/new> cd compiz-0.6.2/ kain@slickbox:~/software/compiz/new/compiz-0.6.2> \ CFLAGS='-march=prescott -mfpmath=sse -O2' configure –prefix=/usr/local checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for a thread-safe mkdir -p... /bin/mkdir -p checking for gawk... gawk .... kain@slickbox:~/software/compiz/new/compiz-0.6.2>
This step uses the CFLAGS environment variable as a hint to the configure script that I’d like to pass the supplied arguments to gcc. I use -march=prescott for my cpu type and -mfpmath=sse as mandated by the ggcccpuopt scipt. I also decided to throw in -O2 to enforce additional optimizations on the generated code which some applications may or may not already do by default. Lastly, I tell configure to install the program in /usr/local which is merely a preference.
Next, I build the program. And install it
kain@slickbox:~/software/compiz/new/compiz-0.6.2> make make all-recursive make: Entering directory `/home/kain/software/compiz/new/compiz-0.6.2' Making all in include make: Entering directory `/home/kain/software/compiz/new/compiz-0.6.2/include' make: Nothing to be done for `all'. make: Leaving directory `/home/kain/software/compiz/new/compiz-0.6.2/include' Making all in src make: Entering directory `/home/kain/software/compiz/new/compiz-0.6.2/src' gcc -DHAVE_CONFIG_H -I. -I.. -I/usr/include/libxml2 -I/usr/include/startup-notification-1.0 -I../include -DPLUGINDIR=\"/usr/local/lib/compiz\" -DIMAGEDIR=\"/usr/local/share/compiz\" -DMETADATADIR=\"/usr/local/share/compiz\" -march=prescott -mfpmath=sse -O2 -Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -D_FORTIFY_SOURCE=2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c mv -f .deps/main.Tpo .deps/main.Po .... kain@slickbox:~/software/compiz/new/compiz-0.6.2> sudo make install ....
Note the use of my arguments in the compiler calls. Thus, it is building the application for our specific machine architecture!
So what’s happening under the hood?
As you may or may not know, the job of a compiler is to translate high level C code to machine-dependent assembly code consisting of many tedious lines of code called cpu instructions. Because by default, the compiler does not know what class of cpu it is compiling for, it uses the safest (and most restrictive) set of instructions and assumptions about the cpu hardware when generating its code. By specifically telling the compiler what cpu it is building for, we can take advantage of all of the features of our cpu and use a more enhanced set of instructions, resulting in highly optimized and faster code. That’s all there is to it!
Its important to note that some software developers make assumptions about the way their code will be generated, causing these optimizations to actually break the applications! While this is not likely, be sure to understand the program you are building before attempting to do this.