Kode optimering

Definition og egenskaber

Kodeoptimering er enhver metode til kodeændring for at forbedre Kodekvaliteten og effektiviteten. Et program kan optimeres, så det bliver en mindre størrelse, bruger mindre hukommelse, udfører hurtigere eller udfører færre input/output operationer.

de grundlæggende krav optimeringsmetoder skal overholde, er, at et optimeret program skal have samme output og bivirkninger som dets ikke-optimerede version. Dette krav kan dog ignoreres i tilfælde af, at fordelen ved optimering skønnes at være vigtigere end sandsynlige konsekvenser af en ændring i programadfærden.

typer og niveauer af optimering

optimering kan udføres af automatiske optimatorer eller programmører. En optimeringsværktøj er enten et specialværktøj eller en indbygget enhed i en kompilator (den såkaldte optimeringscompiler). Moderne processorer kan også optimere udførelsesrækkefølgen for kodeinstruktioner.

optimeringer klassificeres i optimeringer på højt niveau og lavt niveau. Optimeringer på højt niveau udføres normalt af programmøren, der håndterer abstrakte enheder (funktioner, procedurer, klasser osv.) og husker de generelle rammer for opgaven for at optimere designet af et system. Optimeringer udført på niveau med elementære strukturelle blokke af kildekode – sløjfer, grene osv. -kaldes normalt også optimeringer på højt niveau, mens nogle forfattere klassificerer dem i et separat (“mellem”) niveau (N. Virth?). Optimeringer på lavt niveau udføres på det tidspunkt, hvor kildekoden kompileres i et sæt maskininstruktioner, og det er på dette tidspunkt, at automatiseret optimering normalt anvendes. Assembler programmører mener dog, at ingen maskine, uanset hvor perfekt, kan gøre dette bedre end en dygtig programmør (alligevel er alle enige om, at en dårlig programmør vil gøre meget værre end en computer).

Hvad skal man optimere

med manuel kodeoptimering står man over for et andet problem: man behøver ikke bare at vide, hvordan nøjagtigt optimering skal udføres, men også hvilken bestemt del af programmet der skal optimeres. På grund af forskellige årsager (langsomme inputoperationer, forskellen i arbejdshastigheden for en menneskelig operatør og en computer osv.) bruges 90% af eksekveringstiden for et program til kun at udføre 10% af koden (denne erklæring er temmelig spekulativ med Pareto-princippet som en ganske tvivlsom grund, men A. Tanenbaum får det til at lyde overbevisende). Da optimering tager ekstra tid bortset fra den tid, du har brugt på at udvikle programmet, skal du hellere fokusere på at optimere denne tidskritiske 10% kode i stedet for at prøve at optimere hele programmet. Disse kodefragmenter er kendt som flaskehalse og kan detekteres af specialværktøjer – profiler – som kan måle den tid, som forskellige dele af programmet tager at udføre.

i praksis sker optimering dog normalt efter scenen med “kaotisk” programmering (herunder sådanne metoder som “Copy-Paste”, “vi vil se senere”, “det er OK på denne måde”), og er derfor en blanding af optimering som sådan, refactoring og fejlrettelser: forenkling af “skæve” konstruktioner som strlen(sti.c_str ()), logiske forhold som (a.H != 0 & & a.h != 0) osv . Profiler er til lidt hjælp med denne form for optimering. Ikke desto mindre kan du registrere disse problemer med statiske analyseværktøjer, dvs.værktøjer designet til at søge efter semantiske fejl, der er afhængige af dyb analyse af kildekoden. Som du kan se fra ovenstående eksempel med den mærkelige tilstand, kan ineffektiv kode vises som et resultat af fejl (som et forkert tryk i vores eksempel, hvor A.H != 0 && a.y != 0 skal være i stedet). En kraftig statisk analysator registrerer sådanne kodefragmenter og gør opmærksom på dem ved at producere advarselsmeddelelser.

gode og dårlige resultater af optimering

i programmering skal næsten alt behandles ud fra rationalitetssynspunktet – optimering er ingen undtagelse. Der er en tro på, at kode skrevet af en uerfaren Assembler programmør er 3-5 gange langsommere end kode genereret af kompilatoren. Bredt kendt er en sætning fra Knuth om tidlige optimeringer på lavt niveau (såsom forsøg på at spare på operatører eller variabler): “for tidlig optimering er roden til alt ondt”.

de fleste programmører klager ikke over optimeringer udført af optimeringsenheden, hvoraf nogle er konventionelle og obligatoriske. Som for eksempel optimering af haleopkald på funktionelle sprog (haleopkald er et specielt tilfælde af rekursion, som kan repræsenteres som en løkke).

man skal dog forstå, at flere komplekse optimeringer på niveau med maskinkode kan forårsage en stor afmatning af kompilering. Den fordel, de giver dig mulighed for at få, kan være alt for ubetydelig sammenlignet med generelle systemdesignoptimeringer. Man skal også huske på, at moderne sprog med alle deres syntaktiske og semantiske “dikkedarer” har mange nuancer og subtiliteter, så en programmør, der ikke er bekendt med dem, kan blive overrasket over et resultat af optimering.

tag for eksempel C++ og den såkaldte Returværdioptimering, når kompilatoren undgår at kopiere et midlertidigt objekt, der returneres af en funktion. Fordi kompilatoren udelader kopiering, kaldes denne metode også”Copy elision”. Så følgende kode:

#include <iostream> struct C { C() {} C(const C&) { std::cout << "A copy was made.\n"; }}; C f() { return C();} int main() { std::cout << "Hello World!\n"; C obj = f();}

kan have flere udgange:

Hello World!A copy was made.A copy was made.Hello World!A copy was made.Hello World!

mærkeligt, som det kan se ud, er alle de tre versioner gyldige, fordi sprogstandarden tillader udeladelse af opkald fra en kopieringskonstruktør i sådanne tilfælde, selvom konstruktøren har bivirkninger (price 12.8 Copying Class Objects, afsnit 15).

konklusion

således bør vi altid overveje at optimere programkoden ved hjælp af specialiserede værktøjer, hvor det er muligt, men gør det med stor omhu og være klar til sandsynligheden for uventede tricks fra kompilatoren til tider.

PVS-Studio

et sæt diagnostik implementeres i den statiske analysator PVS-Studio, der gør det muligt at finde nogle situationer, hvor kode kan optimeres. PVS-Studio som enhver anden statisk analysator kan dog ikke fungere som erstatning for profileringsværktøjerne. Kun dynamiske programanalysatorer er i stand til at identificere flaskehalse. Statiske analysatorer ved ikke, hvilke inputdataprogrammer der får, og hvor ofte et bestemt stykke kode udføres. Derfor siger vi, at analysatoren foreslår at implementere nogle “mikrooptimeringer” af kode, som ikke garanterer præstationsgevinsterne.

på trods af den betragtede ulempe fungerer PVS-Studioanalysator som et godt supplement til profileringsværktøjer. Desuden, når der beskæftiger sig med PVS-Studio advarsler, relateret til optimering, kode bliver ofte enklere og kortere. Denne effekt overvejes mere detaljeret i artiklen “undersøgelse af Mikrooptimeringer ved hjælp af Tisen-kode som et eksempel”.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.