19. juni 2009 - 00:41Der er
7 kommentarer og 1 løsning
Er mit loop ok performance-wise eller kan det gøres bedre?
for (int x = 0; x < this.getWidth(); x++) { for (int y = 0; y < this.getHeight(); y++) { //Something goes here } }
Jeg har ikke megen JAVA erfaring eller anden programmeringsmæssig baggrund. Jeg skal snart til eksamen hvor jeg skal forklare et meget simpelt program der indeholder et par loops af denne type.
Spørgsmålet er om jeg kan opnå bedre performance (meget lidt eller blot teoretisk gælder også) ved at skrive loopet på en anden måde?
Uden at være kyndig udi hvorledes Java optimerer sin afvikling af bytekoden, slog det mig at det *kunne* koste lidt performance, hvis this.get....() skal evalueres for hvert loop. Kaldet af metoden get....() er ikke "gratis", så hvis ikke det er optimeret væk, vil du kunne spare lidt ved at lave følgende:
int Width = this.getWidth() int Height = this.getHeight()
for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { //Something goes here } }
Inde i løkken har du nogle kald til get....() - tilsvarende kunne du gemme dem i variable i starten af løkken: int red = pixel.GetRed() ..
Jeg har ikke kodet Java siden 2003, og dengang kostede det altså en del at kalde metoder hele tiden for at læse værdier ud. Men der er jo sikkert sket en del siden dengang, så jeg tager forbehold for "gammel viden".
jpvj du er et geni! Selvfølgeligt, det er klart. Men inden jeg sætter mig til at spille alt for smart ved eksamensbordet, skal jeg lige vide helt præcist hvorfor det er hurtigere.
Jeg forstår at hver eneste gang x++ og y++ køres (lad os sige at billedet er 500px * 375px, det er 187500 gange) skal computeren undersøge this (det aktuelle billede) og få bredde og højde. Da størrelsen altid er den samme er der ingen grund til at tjekke dette så forbandet mange gange og derfor spørger vi blot én enkelt gang for hvert billede ved at bruge den kode du foreslår.
Er jeg galt på den?
thesurfer, jeg kan godt se at du i eksempel 2 har gjort det samme som jpvj med at flytte this.getWidth(); og this.getHeight(); uden for loopet således at vi kun spørger om billedets bredde og højde en enkelt gang. Men hvad hjælper det at flytte int x = 0; og int y = 0; uden for loopet, hvordan kan det give noget performance-wise?
jeg forstår ikke hvad man opnår ved at angive x=0 og y=0 uden for loopet. Kan du gå lidt i detaljer her?
Det er meget svært at udtale sig generelt om hvordan JIT compileren optimerer.
Men et tilfældigt stykke test kode:
public class LoopFun { private final static int REP = 2000000000; public static void test1() { long t1 = System.currentTimeMillis(); SomeData sd = new SomeData(REP); for(int i = 0; i < sd.getN(); i++) { sd.add(); } if(sd.getSum() != sd.getN()) { throw new RuntimeException("Ooops"); } long t2 = System.currentTimeMillis(); System.out.println("Keep in: " + (t2 - t1)); } public static void test2() { long t1 = System.currentTimeMillis(); SomeData sd = new SomeData(REP); int n = sd.getN(); for(int i = 0; i < n; i++) { sd.add(); } if(sd.getSum() != sd.getN()) { throw new RuntimeException("Ooops"); } long t2 = System.currentTimeMillis(); System.out.println("Move out: " + (t2 - t1)); } public static void main(String[] args) { test1(); test2(); test1(); test2(); test1(); test2(); } }
class SomeData { private int n; private int sum; public SomeData(int n) { this.n = n; sum = 0; } public void add() { sum++; } public int getN() { return n; } public int getSum() { return sum; } } java version "1.3.1" Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24) Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode) Keep in: 20546 Move out: 9891 Keep in: 20234 Move out: 9891 Keep in: 20516 Move out: 9890 java version "1.3.1" Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24) Java HotSpot(TM) Server VM (build 1.3.1-b24, mixed mode) Keep in: 3813 Move out: 156 Keep in: 125 Move out: 234 Keep in: 3188 Move out: 156 java version "1.4.2_02" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_02-b03) Java HotSpot(TM) Client VM (build 1.4.2_02-b03, mixed mode) Keep in: 4625 Move out: 4453 Keep in: 3828 Move out: 3797 Keep in: 3797 Move out: 3813 java version "1.4.2_02" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_02-b03) Java HotSpot(TM) Server VM (build 1.4.2_02-b03, mixed mode) Keep in: 172 Move out: 188 Keep in: 156 Move out: 187 Keep in: 172 Move out: 157 java version "1.5.0" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64) Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing) Keep in: 5453 Move out: 5109 Keep in: 3797 Move out: 3812 Keep in: 3797 Move out: 3891 java version "1.5.0" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64) Java HotSpot(TM) Server VM (build 1.5.0-b64, mixed mode) Keep in: 360 Move out: 172 Keep in: 250 Move out: 172 Keep in: 172 Move out: 172 java version "1.6.0" Java(TM) SE Runtime Environment (build 1.6.0-b105) Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode) Keep in: 4360 Move out: 4422 Keep in: 4390 Move out: 4422 Keep in: 4375 Move out: 4406 java version "1.6.0" Java(TM) SE Runtime Environment (build 1.6.0-b105) Java HotSpot(TM) Server VM (build 1.6.0-b105, mixed mode) Keep in: 172 Move out: 171 Keep in: 188 Move out: 172 Keep in: 156 Move out: 172
antyder at fodelen ved at flytte metode kald ud af for loop forsvandt med Java 1.4 !
Endbidere er jeg meget skeptisk overfor hvorvidt det selv før 1.4 havde en praktisk betydning for ret mange programmer !!
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.