44

Code optimization

Embed Size (px)

Citation preview

code optimization techniques

● A substantial portion of a knowledge

worker's life may be spent waiting for a

computer program to produce output.

● Users and organizations control their wait time

by purchasing faster computers, adding memory, or using

faster network connections.

● Developers of application programs have a responsibility to

design their programs make the best use of these limited and

expensive resources.

What Is Code Optimization

● Optimization is the process of transforming a piece of code to make

it more efficient without changing its output

● Code optimization is a set of methods for code modification that

improves the code quality and efficiency.

● Optimization aims at -smaller size

-less memory consumption

-rapid executions (only few I/O operations)

Where To Optimize

● Check which portion or which module of the program is

running slow or using huge memory.

● If each part is separately being optimized then the total

programme will automatically get optimised.

● Optimization should be done on those part of program that

are run the most,especially on those methods which are called

repeatedly

Code Optimization Techniques

A program consist of :

• variables

• control statements

decision

loops

• functions

we need to optimize all these parts to run the program faster

Variable

The C compilers support the basic types

char,

short,

int,

long (signed and unsigned),

float and

double.

Using the most appropriate type for variables is very important, as it can reduce code

and data size and increase performance considerably.

Integers

Use unsigned int instead of int if we know the value will never be negative.

Some processors can handle unsigned integer arithmetic considerably faster than signed

So, the best declaration for an int variable in a tight loop would be:

unsigned int variable_name;

integer arithmetic is much faster than floating-point arithmetic, as it can usually be

done directly by the processor, rather than relying on external FPUs or floating point

math libraries.

Global variables

● Global variables are never allocated to registers.

● Global variables can be changed by assigning them indirectly using a pointer, or

by a function call.

● The compiler cannot cache the value of a global variable in a register, resulting in

extra loads and stores when globals are used.

int f(void);

int g(void);

int errs;

void test1(void)

{

errs += f();

errs += g();

}

Here a function uses global

variables heavily

Global variables

int f(void);

int g(void);

int errs;

void test1(void)

{

errs += f();

errs += g();

}it is beneficial to copy

those global variables into

local variables so that they

can be assigned to

registers.

If a function uses global

variables heavily

void test2(void)

{

unsigned int localerrs = errs;

localerrs += f();

localerrs += g();

errs = localerrs;

}

Try it out….

Write a c program to find sum of N integer

#include<stdio.h>

#include<conio.h>

main()

{

int n=10,sum=0,i;

for(i=0;i<n;i++)

sum=sum+i;

printf("Sum:%d",sum);

getch();

}

Try it out….

write a c program to find sum of N integer

#include<stdio.h>

#include<conio.h>

main()

{

int n=10,sum=0,i;

for(i=0;i<n;i++)

sum=sum+i;

printf("Sum:%d",sum);

getch();

}

#include<stdio.h>

#include<conio.h>

main()

{

unsigned int n=10,sum=0,i;

for(i=0;i<n;i++)

sum=sum+i;

printf("Sum:%d",sum);

getch();

}

#include <stdio.h>

int area=100;

int square(){

int x=10;

return x*x; }

int rectangle(){

int l=10,b=20;

int ar=2*(l+b);

return ar;

}

main()

{

area=area+square();

area=area+rectangle();

printf("area:%d",area);

}

Try it outWrite a program to find total area of a plot having a square shaped and rectangular shaped plot

global variable

#include <stdio.h>

int area=100;

int square(){

int x=10;

return x*x; }

int rectangle(){

int l=10,b=20;

int ar=2*(l+b);

return ar;

}

Try it outWrite a program to find total area of a plot having a square shaped and rectangular shaped plot

Making global variable local

main()

{

unsigned int localarea=area;

area=area+square();

area=area+rectangle();

printf("area:%d",area);

area=localarea;

}

Using array indices

switch ( queue ) {

case 0 : letter = 'W';

break;

case 1 : letter = 'S';

break;

case 2 : letter = 'U';

break;

}

if ( queue == 0 )

letter = 'W';

else if ( queue == 1

)

letter = 'S';

else

letter = 'U';

If you wished to set a variable to a particular character, depending upon the value of

something, you might do this:

Using array indices

A neater (and quicker) method is to simply use the value as an

index into a character array, e.g.:

static char *classes="WSU";

letter = classes[queue];

Control Statements

switch() instead of if...else...

For large decisions involving if...else...else..., like this:

if( val == 1)

dostuff1();

else if (val == 2)

dostuff2();

else if (val == 3)

dostuff3();

Control Statements

switch() instead of if...else...

It may be faster to use a switchswitch( val )

{

case 1: dostuff1(); break;

case 2: dostuff2(); break;

case 3: dostuff3(); break;

}

Try it out...

Write a c program to set index to english alphabet#include<stdio.h>

#include<string.h>

main()

{char letter; int ch;

printf("enter the pos");

scanf("%d",&ch);

switch(ch){

case 0:letter='a';break;

case 1:letter='b'; break;

- - -

}

printf("%c",letter); }

Try it out...

write a c program to set index to english alphabet

#include<stdio.h>

#include<string.h>

main()

{char letter; int ch;

printf("enter the pos");

scanf("%d",&ch);

switch(ch){

case 0:letter='a';break;

case 1:letter='b'; break;

- - -

}

printf("%c",letter); }

#include<stdio.h>

#include<conio.h>

main()

{

char *classes="abcdefghi";

int i,ch,letter[26],queue=0;;

for(i=1;i<=26;i++) {

letter[i]=classes[queue];

queue++;

}

printf("enter the position");

scanf("%d",&ch);

printf("%c",letter[ch]);

getch(); }

Loop jamming

Never use two loops where one will suffice

for(i=0; i<100; i++){

stuff();

}

for(i=0; i<100; i++){

morestuff();

}

Loop jamming

It will be better to do this way:

for(i=0; i<100; i++){

stuff();

}

for(i=0; i<100; i++){

morestuff();

}

for(i=0; i<100; ++)

{

stuff();

morestuff();

}

Try it out….

main()

{ int a[100],sum=0,product=1,i;

printf("enter elements into array");

for(i=0;i<5;i++)

scanf("%d",&a[i]);

for(i=0;i<5;i++)

sum=sum+a[i];

for(i=0;i<5;i++)

product=product*a[i];

printf("\nsum:%d \n

product:%d",sum,product); }

Write program to find sum and product of elements in a array

Try it out….

main()

{ int a[100],sum=0,product=1,i;

printf("enter elements into array");

for(i=0;i<5;i++)

scanf("%d",&a[i]);

for(i=0;i<5;i++)

sum=sum+a[i];

for(i=0;i<5;i++)

product=product*a[i];

printf("\nsum:%d \n

product:%d",sum,product); }

Write program to find sum and product of elements in a array

for(i=0;i<5;i++)

{

scanf("%d",&a[i]);

sum=sum+a[i];

product=product*a[i];

}

Function Looping

If a function is often called from within a loop ,it may be possible to put that loop

inside the function to cut down the overhead of calling the function repeatedly

for(i=0 ; i<100 ; i++)

{

func(t,i);

}

-

-

-

void func(int w,d)

{

lots of stuff.

}

func(t);

-

-

void func(w)

{

for(i=0 ; i<100 ; i++)

{

//lots of stuff.

}

}

Try it outWrite a program to find sum of n numbers

#include<stdio.h>

#include<conio.h>

main()

{

int n=10,i,total=0;

for(i=0;i<10;i++)

total+=sum(i);

printf("\n sum is:%d",total);

getch();

}

sum(int i)

{ int sum=0;

sum=sum+i;

}

Try it outWrite a program to find sum of n numbers

#include<stdio.h>

#include<conio.h>

main()

{

int n=10,i,total=0;

for(i=0;i<10;i++)

total += sum(i);

printf("\n sum is:%d",total);

getch();

}

sum(int i)

{ int sum=0;

sum=sum+i;

}

main()

{ int total=0;

total=sum();

printf("\n sum is:%d",total);

getch();

}

int sum()

{ int sum=0,i;

for(i=0;i<10;i++)

sum=sum+i;

return sum;

}

Faster for() loops

Ordinarily, we used to code a simple for() loop like this:

for( i=0; i<10; i++){ ... } [ i loops through the values 0,1,2,3,4,5,6,7,8,9 ]

If we needn't care about the order of the loop counter, we can do this instead:

for( i=10; ; i-- ) { ... }

Using this code, i loops through the values 9,8,7,6,5,4,3,2,1,0, and the loop should be

faster.

This works because it is quicker to process i--

Try it out….Write a program to find factorial of a number

main()

{

int factorial=0,n=3;

factorial=fact(n);

clrscr();

printf("%d",factorial);

getch();

}

fact(int n)

{

int i,fact=1;

for(i=0;i<n;i++)

fact*=i;

return fact;

}

Try it out….Write a program to find factorial of a number

main()

{

int factorial=0,n=3;

factorial=fact(n);

clrscr();

printf("%d",factorial);

getch();

}

fact(int n)

{

int i,fact=1;

for(i=0;i<n;i++)

fact*=i;

return fact;

}

main()

{ int

factorial=0,n=3;

factorial=fact(n);

clrscr();

printf("%d",factorial);

getch();

}

fact(int n)

{ int i,fact=1;

for(i=n;i!=0;i--)

fact*=i;

return fact*;

}

loop unrolling

● Small loops can be unrolled for higher performance.

● If the loop iterates only a few times, it can be fully unrolled, so that the loop

overhead completely disappears.

This can make a big difference. It is well known that unrolling loops can produce

considerable savings, e.g.:

for(i=0; i<3; i++){

something(i);

}

something(0);

something(1);

something(2);

Early loop breaking

It is often not necessary to process the entirety of a loop.

Example, if we are searching an array for a particular item, break out of the loop as

soon as we have got what we need.

Example: this loop searches a list of 10000 numbers to see if there is a -99 in it.

found = FALSE;

for(i=0;i<10000;i++)

{

if( list[i] == -99 )

{

found = TRUE;

}

}

if( found ) printf("Yes,

there is a -99. Hooray!\n");

found = FALSE;

for(i=0; i<10000; i++)

{

if( list[i] == -99 )

{

found = TRUE;

break;

}

}

if( found )

printf("Yes, there is a -

99. Hooray!\n");

Try it outwrite a program to find position of an element in array

main( )

{ int arr[10],i,element,f=0;

printf("enter the elements");

for(i=0;i<10;i++)

scanf("%d",&arr[i]);

printf("enter the elements to search");

scanf("%d",&element);

for(i=0;i<10;i++)

{ if(arr[i]==element)

f=1;

}

if(f = =1) printf("element found");

}

Try it outwrite a program to find position of an element in array

main( )

{ int arr[10],i,element,f=0;

printf("enter the elements");

for(i=0;i<10;i++)

scanf("%d",&arr[i]);

printf("enter the elements to search");

scanf("%d",&element);

for(i=0;i<10;i++)

{ if(arr[i]==element)

f=1;

}

if(f = =1) printf("element found");

}

early loop

breaking

main( ) {

int arr[10],i,element,f=0;

printf("enter the elements");

for(i=0;i<10;i++)

scanf("%d",&arr[i]);

printf("enter the elements to search");

scanf("%d",&element);

for(i=0;i<10;i++)

{ if(arr[i]==element)

{ f=1; break;}

}

if(f = =1) printf("element found");

}

Code Motion

Code motion involves identifying bits of code that occur within loops, but need only

be executed once during that particular loop.

For example,

void shift_char(char *str){

int i;

for(i=0;i<strlen(str);i++){

str[i]++;

}

}

void shift_char(char *str){

int i;

int len=strlen(str)

for(i=0;i<len;i++){

str[i]++;

}

}

Try it outWrite a program to search a character in a string

main()

{ char arr[10];

int i,ch,f=0,len;

printf("enter the string");

scanf("%s",&arr);

printf("enter the character to

search");

scanf("%s",&ch);

len=strlen(arr);

for(i=0;i<len;i++)

{ if(arr[i]==ch)

{ f=1; break;}

}

if(f==1) printf("element found");

}

function strlen is called once and set

to variable len

Function Design

● keep functions small and simple.

● This enables the compiler to perform optimizations

such as register allocation more efficiently.

function call overhead

● There is some limitation upto which words of argument

can be passed to a function in register.

● If the argument limitation is 4 then the 5th and

subsequent words are passed on the stack.

int f2(int a, int b, int c, int d, int e, int f)

{

return a + b + c + d + e + f;

}

int g2(void) {

return f2(1, 2, 3, 4, 5, 6);

}

The fifth and sixth parameters are stored on the stack in g2, and reloaded

in f2, costing two memory accesses per parameter.

int f1(int a, int b, int c, int d)

{

return a + b + c + d;

}

int g1(void) {

return f1(1, 2, 3, 4);

}

This code works fine.

Minimizing parameter passing overheadTo minimize the overhead of passing parameters to functions:

● Try to ensure that small functions take four or fewer arguments.This will reduce

the number of parameters and increase readability.

● Pass pointers to structures instead of passing the structure itself.

void print_data_of_a_structure ( const Thestruct *data_pointer)

{

...printf contents of the structure...

}

● Avoid functions with a variable number of parameters. Those functions effectively

pass all their arguments on the stack.

Try it outwrite a c program to print content of a structure

struct student

{ int id;

char name[20];

float percentage };

void func(struct student *record);

int main()

{ struct student record;

record.id=1;

strcpy(record.name, "Raju");

record.percentage = 86.5;

func(&record);

return 0; }

void func(struct student *record)

{

printf(" Id is: %d \n", record->id);

printf(" Name is: %s \n", record->name);

printf(" Percentage is: %f \n", record->percentage);

}

struct student

{ int id;

char name[20];

float percentage; };

void func(struct student record);

int main()

{ struct student record;

record.id=1;

strcpy(record.name, "Raju");

record.percentage = 86.5;

func(record);

return 0; }

void func(struct student record)

{ printf(" Id is: %d \n", record.id);

printf(" Name is: %s \n", record.name);

printf(" Percentage is: %f \n",

record.percentage);

}

Pass pointers of a

structure

Inline function● Inlining is the process by which the contents of a function are copied and pasted

instead of a traditional call to that function.

● This form of optimization avoids the overhead of function calls, by eliminating the

need to jump, create a new stack frame, and reverse this process at the end of the

function.

Inline int square(int x)

{

return x*x

}

#include<math.h>

double length(int x,int y)

{

return sqrt(square(x)*square(y))

}

Try it outwrite a program to implement square root of x2+y2

#include<stdio.h>

#include<conio.h>

#include<math.h>

main()

{

int x=4,y=3,a;

a= sqrt(square(x)+square(y));

clrscr();

printf("\n %d",a);

getch();

}

int square(int x)

{ return x*x;

}

#include <stdio.h>

#include<math.h>

int main() {

int tmp,x=4,y=3;

tmp = sqrt(square(x)+square(y));

printf("square val=%d\n", tmp);

return 0;

}

int inline square(int x) {

return x*x;

}

Inline function

Advantage of using inline function

● No function call overhead

As the code is substituted directly ,there is no overhead like saving and storing

register

● Lower argument evaluation overhead

The overhead of parameter passing is generally lower,since it is not

necessary to copy variables

THE END