Professional Documents
Culture Documents
Predavanje 7
Predavanje 7
Code tuning (podešavanje koda) je praksa modifikovanja korektnog koda na način da se poboljšaju
njegove performanse. „Tuning“ se odnosi na male promjene klase, metode, nekoliko linija koda.
Code tuning tehnike su u nekim slučajevima u kontraverzi sa refaktoring tehnikama jer se može desiti
da degradiraju internu strukturu koda da bi se postigle bolje performanse. Često je čitljivost koda
mnogo važnija od poboljšanja performansi. U mnogim slučajevima se poboljšaju performanse koda
primjenom code tuning tehnika ali ponekad ta poboljšanja mogu biti beznačajna. Također, poboljšanja
mogu varirati ovisno od kompajlera. Zbog toga je uvijek neophodno mjeriti performanse prije i poslije
primjene code tuning tehnika. Materijal je pripremljen na osnovu knjige – Code Complete, autora
Steve McConnela (poglavlje 26) i koristi se u edukativne svrhe.
Slijedi upoznavanje sa osnovnim code-tuning tehnikama koje se primjenjuje na: 1. Logičke iskaze 2.
Petlje 3. Podatke 4. Izraze 5. Rutine. Nakon toga se razmatra nekoliko specifičnih podešavanja koda u
.NET-u. Za sve code tuning tehnike postoje i chech liste.
Kada se procijeni da 5 nije veće od x nije potrebno da se ispituje drugi dio iskaza. Neki jezici
daju formu evaulacije poznatu kao „short-circuit“ evaulacija koja znači da kompajler
automatski zaustavi testiranje odmah čim je poznat rezultat. Dio je C++ i Java standarda.
Ako jezik ne podržava short-circuit evaulaciju tada se izbjegava korištenje logičkih operatora
(and, or,...) i dodaje se logički iskaz.
if (5<x) then
if (x<10) then
Kod se može zamijeniti sa lookup tabelom. Lookup tabela je teška za čitanje, pa je treba i
dodatno dokumentovati. Procijenjeno poboljšanje za C++ je 33%.
// definisanje tabele kategorija
static int categoryTable[2][2][2]={
// !b!c !bc b!c bc
0, 3, 2, 2, // !a
1, 2, 1, 1 // a
};
…
category=categoryTable[a][b][c];
2.Tuning petlji
Pošto se petlje izvršavaju više puta vruće tačke u programu su često unutar petlje. Tehnike
koje slijede čine petlju bržom.
Unswitching
Česte su petlje u kojima se ispitivanje odluke vrši unutar svake iteracije petlje, pri čemu ta
odluka ne utiče na tok izvršavanja.
//Kod sa if iskazom unutar petlje, pri čemu if iskaz ne utiče na indeks petlje
for (i=0; i<count;i++)
{
if (sumType==SUMTYPE_NET){
netSum=netSum+amount[i];
}
else
{
grossSum=grossSum+amount[i];
}
}
Ovaj fragment koda krši mnoga pravila dobrog programiranja. Čitljivost i održavanje koda su
često važniji od brzine izvršavanja ili veličine. Ovdje se petlje moraju održavati paraleno.
Jamming
Jamming (spajanje, fuzija) je kombinovanje 2 petlje koje imaju iste kontrolne uslove i koje
rade na istom setu elemenata.
//Kod sa dvije petlje koje rade na istom setu elemenata
for (i=0; i<n; i++)
sum[i] = 0.0;
for (i=0; i<n; i++)
rate[i] = 0.06;
//Jamming – spajanje dvije petlje koje rade nad istim setom elemenata
for (i=0; i<n; i++)
{ sum [i] = 0.0;
rate[i] = 0.06;
}
Unrolling
Unrollong (odmotavanje) propagira da se što je moguće više posla uradi u okviru jedne
iteracije petlje.
//Primjer petlje koja može biti unrooled
i=0;
while (i <count)
{
a[i]=i;
i=i+1;
Tehnika odmotavanja mijenja originalnu liniju a[i]=i sa dvije linije, brojač se povećava za
2 (umjesto za 1). Ekstra linija koda nakon terminiranje while petlje je potrebna kada je count
neparan.
// Unrolled kod
i=0;
while (i <count-1)
{
a[i]=i;
a[i+1]=i+1;
i=i+2;
}
if (i== count-1)
{
a[count-1] = count-1 ;
}
U ovom slučaju može se pointer izraziti kao dobro-imenovana varijabla i na taj način
poboljšati čitljivost i performanse.
Ukoliko se prije početka petlja postavi na kraju niza sentinel vrijednost koja odgovara
traženoj vrijednosti pretrage, uslov petlje je samo jedan test item[i]!=testValue.
if (i<count) {
….
Npr. za niz od 100 cjelobrojnih elemenata ubrzanje za Java kod je 44% a za C# 23%.
Broj izvršavanja za iteraciju vanjske petlje je 100, za unutrašnju petlju 100*5=500, što je
ukupno 600 iteracija. Promjenom petlji vanjska petlje bi se izvršavala 5 puta a unutrašnja
5*100=500, što je ukupno 505 iteracija.
Strenght Reduction (Jaka redukcija)
Jaka redukcija (strenght redukcija) znači zamijeniti skupe operatore kao što je npr.
množenje sa jeftinijim kao što je sabiranje u izrazima koji su ovisni od indeksa petlje.
-Koristiti integer tip podataka umjesto floating point (npr. indeks petlje), slično float
umjesto double,...
Korištenje hešinga
Heširanje znači spašavanje više traženih vrijednosti na takav način da se mogu lakše
koristiti. Naprimjer, ako program slučajnim uzorkom čita sa diska, metoda može koristiti heš
da spasi slogove koji se najčešće čitaju. Poslije kada rutina primi zahtjev za slogom,
provjerava se da li je taj slog u hešu i ako jeste rutina vrati slog iz memorije umjesto sa
diska.
Mogu se heširati i rezultati od zahtijevnog računanja. Npr. potrebno je izračunati dužinu
hipotenuze pravouganog trougla, dajući dužine druge dvije strane.
Druga verzija je mnogo komplikovanija nego prva ali zbog brzine (naročito u C++) je treba
razmotriti. Mnoge hešing šeme heširaju više od jednog elementa.
Kao i neke druge optimizacijske tehnike, heširanje dodaje kompleksnost i ima tendenciju
koda podložnog greškama.
4. Tuning izraza
Npr.
Umjesto sqrt(x) < sqrt(y) testirati x < y
//Log-base-two rutina
bazirana na sistemskoj rutini
unsigned int Log2(unsigned int x) {
return(unsigned int) (log(x)/log(2)) ;
}
Preračunati rezultate
Prilikom dizajniranja na niskom nivou uvijek je odluka da li računati rezultate u toku rada ili
ih izračunati jednom i koristiti ih po potrebi. Ako se rezultati koriste više puta često je
jeftinije da se preračunaju jednom što se može postići na više načina. Već je pominjano da se
može dio računanja izvršiti izvan petlje umjesto unutar petlje, koristiti lookup tabela,
smjestiti rezultate u fajl ili neku programsku strukturu.
Npr. u space-war video igrici program inicijalno računa graviti koeficijente za različite
distance od sunca. Prepoznato je relativno malo različitih distanci od sunca koje se
preračunavaju i smještaju u 10-dimenzionalni niz, što je brže nego da se preračunavaju u toku
izvršavanja programa.
Dodatno optimizacija programa preračunavanjem može se postići:
-preračunavanjem rezultata i dodijeljivanje istih u konstante za vrijeme kompilacije,
-preračunavanjem rezultata i dodjeljivanje istih u varijable koje se koriste za vrijeme
izvršavanja programa,
-preračunavanjem rezultata i smještanje istih u fajlove koji se pune za vrijeme izvršavanja
programa,
-preračunavanjem rezultata jednom kada se startuje program i onda referenciranje istih svaki
put kada je to potrebno,
-izračunavanjem što je moguće više prije nego što petlja počne i minimiziranjem posla koji se
obavlja unutar petlje,
-izračunavanjem rezultata prvi put kada zatrebaju i heširanjem istih tako da se mogu zatražiti
kada zatrebaju.
5.Tuning rutina
Dekompozicija programa je važna za code tuning. Objektno orijentisani dizajn doprinosi
dobroj organizacija koda nad kojim se može primijeniti i refaktoring i potrebne code tuning
tehnike.
Spajanje string literala se dešava za vrijeme kompilacije dok se za string varijable dešava za
vrijeme run time i koristiti se heap.
Koristiti StringBuilder –a za spajanje string varijabli:
StringBuilder sb1 = new StringBuilder();
string s1 = "test";
for (int i = 0; i < 100; i++)
sb1.Append(s1);
StringBuilder reducira overhead prilikom alokacije.