array.length in For-Schleife verwenden?

Status
Nicht offen für weitere Antworten.

Rock Lobster

Bekanntes Mitglied
Servus,

wenn ihr z.B. ein Array habt, und in einer For-Schleife die Array-Länge als Endwert benutzen wollt, benutzt ihr dann direkt array.length oder speichert ihr das vorher kurz in eine Variable?

Code:
for(int i=0; i<buffer.length; i++)

-- oder --

int bufferLength = buffer.length
for(int i=0; i<bufferLength; i++)

Anders gefragt, macht es einen Unterschied in der Geschwindigkeit? Da length ja eine Variable ist und keine Funktion, müßte ja das Auslesen dieser Variable keinen erheblichen Unterschied machen - aber wird da dann "direkt adressiert", also weiß die VM sofort, wo sie nachschauen muß, oder wird da erst ein Umweg über die Variable "buffer" gemacht, um auf "length" zuzugreifen? Weil dann wäre die zweite Lösung bei großen Schleifen sicherlich sinnvoller...
 

Rock Lobster

Bekanntes Mitglied
Naja foreach kann ich in meinen Fällen oft nicht gebrauchen, da ich den Index sehr häufig benötige.

Daß buffer.length mehr straight-forward ist finde ich natürlich auch, aber das beantwortet noch nicht meine Frage ;) ich programmiere Audio-Tools die so schnell wie möglich an den Daten rumfummeln müssen, daher wäre es für mich schon interessant zu wissen, ob buffer.length direkt oder indirekt auf .length zugreift :)
 

HeRaider

Aktives Mitglied
Also ich benutze immer.
Code:
for(int i=0; i<buffer.length; i++)
Ist meiner Meinung nach übersichtlicher. Ich glaube übrigens nicht, dass es da große Unterschiede gibt. Müsste alles eigentlich mehr oder weniger gleichschnell sein. Kannst ja mal wenn du Lust hast bei beiden Methoden die Zeit messen.
 

Rock Lobster

Bekanntes Mitglied
Hmm ja, Zeitmessung wäre vielleicht wirklich mal 'nen Versuch wert.

Was passiert eigentlich bei so etwas:
Code:
for(int i=0; i<buffer.length*2; i++)

Ist der Compiler dazu in der Lage, sowas als Konstante einzubauen? Die .length-Variablen sind ja eh final, von daher müßte er das ja evtl. so optimieren, daß er es vorher ausliest, *2 nimmt und hinterher nur diesen Temp-Wert in der Schleife testet.

Und falls es so ist, funktioniert das auch bei normalen Variablen? Also daß der Compiler z.B. merkt, daß sich die verwendete Variable in der Schleife eh niemals ändern kann... kann er dann auch temporär diese Variable *2 nehmen und nur damit dann die Schleife durchführen?

EDIT: Also bei sowas hier:
Code:
int size=70;
for(int i=0; i<size*3; i++)
{
    // size ändert sich hier drin nie
}
 

Marco13

Top Contributor
Nimm buffer.length. FALLS das Programm extrem zeitkritisch ist, dann lass zwischendurch einen Profiler drüberlaufen. FALLS die meiste Zeit in so einer Schleife flöten geht (die schon SEHR kurz sein muss, damit so eine lächerlicher Derefernzierung ins Gewicht fällt) dann ersetze das buffer.length durch ein 'int bufferLength', und lass' den Profiler nochmal laufen. FALLS es dann merklich schneller ist (was ich für praktisch ausgeschlossen halte) dann lass das mit dem bufferLength drin - ansonsten nicht.

(Meine Kristallkugel sagt mir, dass die meiste Zeit an GANZ anderen Stellen flöten gehen wird... :wink: )
 

outbreaker

Bekanntes Mitglied
habe mal schnell ein Programm geschrieben zum Zeit messen:

Code:
package testen;

public class T5 {

	String[] array = new String[100000];
	long timeD1 = 0;
	long timeD2 = 0;
	long timeD3 = 0;
	
	public T5() 
	{
		init();
		test();
	}
	
	private void init()
	{
		for (int a = 0; a < 100000; a++)
		{
			array[a] = "a";
		}
	}
	
	private void test()
	{
		for (int tests = 0; tests < 100000; tests++)
		{
		
			int z = 0;
			long time1 = System.nanoTime();
			for (int i = 1; i < array.length; i++)
			{
				z += 10;
			}
			long time2 = System.nanoTime();
			
			//Test 2
			
			long time3 = System.nanoTime();
			int bl = array.length;
			for (int i = 1; i < bl; i++)
			{
				z += 10;
			}
			long time4 = System.nanoTime();
			
			
			//Test 3
			
			int bl2 = array.length;
			long time5 = System.nanoTime();
			for (int i = 1; i < bl2; i++)
			{
				z += 10;
			}
			long time6 = System.nanoTime();
			
			timeD1 += (time2 - time1);
			timeD2 += (time4 - time3);
			timeD3 += (time6 - time5);
			
		}
		
		
		System.out.println("Zeit in nanoSekunden");
		System.out.println("time1: " + (timeD1/100000));
		System.out.println("time2: " + (timeD2/100000));
		System.out.println("time3: " + (timeD3/100000));
	}
	
	public static void main(String[] args) {
		new T5();
	}
}

Meine Ausgabe war diese:

Zeit in nanoSekunden
time1: 292545
time2: 146132
time3: 148758

Also grob würde ich sagen das die Variante mit dem vorher in eine Variable speichern doppelt so schnell ist

Das Programm berechnet das nicht für einen Versuch sondern führt 100000 mal die Schleifen mit je 100000 Durchgängen aus
 
S

SlaterB

Gast
Vertausche mal Test 1 mit Test 2, dann ist die andere Variante aufeinmal doppelt so langsam ;)

so richtig erklären kann ich es nicht, aber die Differenz der Nanosekunden ist auf jeden Fall Quark, so genau kann niemand messen,

lasse jede Operation für sich x Mio. mal laufen und miss dann die Zeit, die mindestens ein paar Sekunden betragen muss,
dann wirds zumindest nicht total unrealistisch
 

Rock Lobster

Bekanntes Mitglied
@ Marco13: Es ist mehr so 'ne prinzipielle Sache, da ich wirklich tonnenweise Schleifen in meinem Programm habe, die sich sehr oft nach der Größe eines Arrays richten. Wenn ich sowas nur 1-2x mache, dann bin ich da auch nicht so pingelig, aber da mein Programm wirklich sehr oft Daten hin- und herrechnen muß, wollte ich da halt nicht unnötig Zeit vergeuden :)
 
S

SlaterB

Gast
> aber da mein Programm wirklich sehr oft Daten hin- und herrechnen muß

Zeit ist relativ ;), egal ob eine oder 1000 Schleifen, du wirst immer nur 0.001% verlieren,

was macht es für einen Unterschied, ob deine Operation 1 sec dauert oder 0,99999 sec?
was macht es für einen Unterschied, ob dein Programm 1 Tag läuft oder 23:59:30?
 

Ariol

Top Contributor
Ich hab jetzt gerade ein int[100000] jeweils 100000-mal durch beide Möglichkeiten gejagt und Durchschnittsdauern errechnet:

Code:
public class SpeedTest
{
	public static void main(String[] args)
	{
		long[] run = new long[2];
		

		int[] array = new int[100000];
		int runs = 100000;
		
		for (int c = 1; c <= runs; c++)
		{
			long start1 = System.nanoTime();
			for (int i = 0; i < array.length; i++)
			{}
			long stop1 = System.nanoTime();

			long start2 = System.nanoTime();
			int length = array.length;
			for (int i = 0; i < length; i++)
			{}
			long stop2 = System.nanoTime();

			run[0] += stop1-start1;
			run[1] += stop2-start2;
		}
		
		System.out.println(run[0]/runs);
		System.out.println(run[1]/runs);
	}
}

Bei meinem armen schwachen Laptop ( ;-( ) ein ziemlicher Unterschied:

Code:
315429 // ohne "Auslagern"
158087 // mit
 

outbreaker

Bekanntes Mitglied
SlaterB hat gesagt.:
Vertausche mal Test 1 mit Test 2, dann ist die andere Variante aufeinmal doppelt so langsam ;)

so richtig erklären kann ich es nicht, aber die Differenz der Nanosekunden ist auf jeden Fall Quark, so genau kann niemand messen,

lasse jede Operation für sich x Mio. mal laufen und miss dann die Zeit, die mindestens ein paar Sekunden betragen muss,
dann wirds zumindest nicht total unrealistisch

Also das ist bei mir irgenwie nicht der Fall ???:L
Bei mir bleibt der Unterschied auch beim Tausch erhalten aber er ist nicht mehr ganz so groß

Zeit in nanoSekunden
time1: 229335
time2: 171863
time3: 175713

aber das kann schon an dem nanoTime Aufruf liegen
 
S

SlaterB

Gast
hier mal eine fairere Variante von Ariols Test

Code:
package test;

public class SpeedTest
{
    public static void main(String[] args)
    {
        a();
        b();
        a();
        b();
        a();
        b();

    }

    static void a()
    {
        long[] run = new long[2];


        int[] array = new int[10000];
        int runs = 100000;

        for (int c = 1; c <= runs; c++)
        {
            long start1 = System.nanoTime();
            for (int i = 0; i < array.length; i++)
            {
            }
            long stop1 = System.nanoTime();

            long start2 = System.nanoTime();
            int length = array.length;
            for (int i = 0; i < length; i++)
            {
            }
            long stop2 = System.nanoTime();

            run[0] += stop1 - start1;
            run[1] += stop2 - start2;
        }

        System.out.println(run[0] / runs);
        System.out.println(run[1] / runs);

    }

    static void b()
    {
        long[] run = new long[2];


        int[] array = new int[10000];
        int runs = 100000;

        for (int c = 1; c <= runs; c++)
        {
            long start1 = System.nanoTime();
            int length = array.length;
            for (int i = 0; i < length; i++)
            {
            }
            long stop1 = System.nanoTime();

            long start2 = System.nanoTime();
            for (int i = 0; i < array.length; i++)
            {
            }
            long stop2 = System.nanoTime();

            run[0] += stop1 - start1;
            run[1] += stop2 - start2;
        }

        System.out.println(run[0] / runs);
        System.out.println(run[1] / runs);
    }
}


19082
28950
16277
37274
17184
15889
15880
16358
17490
15868
15787
15801

der ist aber auch so einfach, dass man annehmen muss, dass der Compiler hier vereinfacht
 

Wildcard

Top Contributor
Und da sind wir wieder bei total falschen Mikro Benchmarks weil sich niemand Gedanken darüber macht was der JIT Compiler daraus bastelt :roll:
 

Marco13

Top Contributor
Man kann aber - so weit das möglich ist - versuchen, den JIT mit einzubeziehen. Also nicht nur TestA und TestB nacheinander laufen lassen, sondern TestA und TestB vielleicht 10 mal abwechselnd, evtl. noch mit größer werdenden Eingabedaten - von daher ist SlaterB's Test wohl noch am repräsentativsten - und wie man sieht, sieht man keinen praktisch relevanten Unterschied.
 

JavaFred

Aktives Mitglied
Rock Lobster hat gesagt.:
benutzt ihr dann direkt array.length oder speichert ihr das vorher kurz in eine Variable?
Du kannst das auch innerhalb des for-Konstrukts benutzen:

Code:
for(int i=0, len=buffer.length; i<len; ++i) { ... }

(So würde ich das machen.)
 

Rock Lobster

Bekanntes Mitglied
@ Wildcard: Vielleicht programmierst Du ja irgendwelche Business-Datenbank-Applikationen oder so, wo das vielleicht nicht so ins Gewicht fällt, aber bei Audio-Sachen will man schon höchstmögliche Performance haben. Und da finde ich es nicht verkehrt, zumindest mal drüber nachzudenken, zumal ich solche Schleifen wirklich ständig benötige, weil ich während des Abspielens zig Samples hin- und herkopieren will. Wenn sich hinterher rausstellt, daß es auf die Performance keinen großartigen Einfluß hat, weil der JIT da klüger ist als der Programmierer, dann ist das natürlich schön und für mich ja auch definitiv eine Antwort, die mir weiterhilft. Sich darüber aber überhaupt keine Gedanken zu machen, finde ich dagegen falsch. Und falls ich innerhalb einer Schleife z.B. 32768 mal unnötigerweise (!) einen Wert auslese, dann zählt das für mich nicht automatisch als "Trivialität" ;)

@ JavaFred: Über diese Möglichkeit hab ich noch gar nicht nachgedacht... sieht unter Umständen eleganter aus. Werd ich wohl mal im Hinterkopf behalten :)
 

Marco13

Top Contributor
array.length ist final. Wenn der Compiler das nicht wegoptimieren würde, sollte man sich schon Gedanken machen ....
 
S

SlaterB

Gast
der Compiler müsste erkennen, dass zwischendurch nicht das Array wechselt,
auch kein Hexenwerk, aber nicht trivial,

bei nicht lokalen Variablen wohl grundsätzlich ausgeschlossen?
 

schalentier

Gesperrter Benutzer
Also habs mir mal im Disassemble angesehen.

Wie man unschwer erkennen kann, spart man durch das vorherige Ablegen von array.length genau eine Operation, naemlich
//* 7 11:arraylength

In der VM Spezifikation kann man nachlesen was das macht:

Nimmt den ersten Wert vom Stack (was ein Array sein muss) und leg die Laenge zurueck. Wie das genau funktioniert steht da nicht. Vermutlich aber muss die Laenge von irgendwoher gelesen werden, um sie danach auf den Stack zu packen.

Im anderen Fall wuerde wohl der JIT den Speicherzugriff auf die lokale Variable (length im Beispiel) durch einen Registerzugriff wegoptimieren.

Demnach sollte die zweite Variante theoretisch schneller sein. Allerdings liegt das wahrscheinlich in einem Bereich, den man vernachlaessigen kann. Viel mehr kann durch das Optimieren des Schleifenbodies rausgeholt werden, denk ich mal. Sicherheit erhaeltst du nur, wenn du das mit einem Profiler ueberpruefst...

Code:
public static void main(String args[])
    {
        String array[] = new String[20000];
    //    0    0:sipush          20000
    //    1    3:anewarray       String[]
    //    2    6:astore_1        
        for(int i = 0; i < array.length; i++)
    //*   3    7:iconst_0        
    //*   4    8:istore_2        
    //*   5    9:iload_2         
    //*   6   10:aload_1         
    //*   7   11:arraylength     
    //*   8   12:icmpge          30
            System.out.println(array[i]);
    //    9   15:getstatic       #3   <Field PrintStream System.out>
    //   10   18:aload_1         
    //   11   19:iload_2         
    //   12   20:aaload          
    //   13   21:invokevirtual   #4   <Method void PrintStream.println(String)>

    //   14   24:iinc            2  1
    //*  15   27:goto            9
        int length = array.length;
    //   16   30:aload_1         
    //   17   31:arraylength     
    //   18   32:istore_2        
        for(int i = 0; i < length; i++)
    //*  19   33:iconst_0        
    //*  20   34:istore_3        
    //*  21   35:iload_3         
    //*  22   36:iload_2         
    //*  23   37:icmpge          55
            System.out.println(array[i]);
    //   24   40:getstatic       #3   <Field PrintStream System.out>
    //   25   43:aload_1         
    //   26   44:iload_3         
    //   27   45:aaload          
    //   28   46:invokevirtual   #4   <Method void PrintStream.println(String)>

    //   29   49:iinc            3  1
    //*  30   52:goto            35
    //   31   55:return          
    }
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Caesar-Verschiebung: IndexOutOfBoundsException bei Verschiebung > array.length Allgemeine Java-Themen 2
L array.length-Problem Allgemeine Java-Themen 60
LucasGlockner Effizienter byte-Zugriff auf ein long[]-Array Allgemeine Java-Themen 8
8u3631984 Frage Performance bei Linked List und Array List Allgemeine Java-Themen 5
M Queue mit einem Array implemetieren Allgemeine Java-Themen 16
M Array Rang eines Elements Allgemeine Java-Themen 4
TheSepp Java bestimmtes Array auf den Wert 0 setzen Allgemeine Java-Themen 32
TheSepp Wie kann man Leerzeichen aus einer Array liste entfernen? Allgemeine Java-Themen 10
B HeapSort für Array of Strings funktioniert nur teilweise Allgemeine Java-Themen 3
noah1407 Array Allgemeine Java-Themen 3
D Methoden Teil-Array mit Maximalwert bestimmen Allgemeine Java-Themen 23
N einem Array Objekte hinzufügen die ihr Array position gespeichert haben Allgemeine Java-Themen 34
N zweidimensionalen Array in dreidimensionalen Array speichern Allgemeine Java-Themen 4
N Schnellste Methode, ein Array durchzugehen? Allgemeine Java-Themen 9
T Objekt Array Aufgabe mit Busdatenbank Allgemeine Java-Themen 2
L Array und Index Allgemeine Java-Themen 26
L die 3 größten Zahlen im Array Allgemeine Java-Themen 1
G jToggleButton in Array/ArrayList Allgemeine Java-Themen 12
S Übergabe eines Sortierkriteriums für ein Artikel Array mittels BiPredicate<Artikel, Artikel> Allgemeine Java-Themen 13
Willi.We Array sortieren Allgemeine Java-Themen 5
gotzi242 Array Summe bestimmen tipps? Allgemeine Java-Themen 14
H Matrix ohne Array erstellen Allgemeine Java-Themen 9
Aboya Char Array rekursiv vergleichen Allgemeine Java-Themen 15
V4ll3.Wff Array in Java Allgemeine Java-Themen 4
Noahscript Aus einem byte Array Steuerungszeichen und Code bekommen und ersetzen Allgemeine Java-Themen 3
H Array Sportschütze Allgemeine Java-Themen 6
Sumo_ow "ArrayIndexOutofBoundsException: 2" Array Problem Allgemeine Java-Themen 6
xGh0st2014 Problem mit Java Array Allgemeine Java-Themen 1
M Array verändern Allgemeine Java-Themen 1
A JavaFX 2 dimensionales array Allgemeine Java-Themen 1
LimDul Direktes return eines Array geht nicht Allgemeine Java-Themen 20
S Array dynamisieren oder ArrayList verwenden? Allgemeine Java-Themen 17
M Java 2D Array für ein Grid erstellen ? Allgemeine Java-Themen 2
H Array mit dem Datentype String[] initializieren Allgemeine Java-Themen 7
L ArrayList mit String Arrays in ein Array umwandeln Allgemeine Java-Themen 1
H Elemente aus ArrayList in Array speichern Allgemeine Java-Themen 8
E Datentypen Wie kann ich die Längen der unterschiedlichen Ebenen aus einem Objekt lesen von dem ich weiß, dass es ein mehrdimensionaler Array ist? Allgemeine Java-Themen 3
N Byte Array in Java "dekomprimieren" Allgemeine Java-Themen 3
parrot Array Aufgabe Allgemeine Java-Themen 3
N String Array Eingabe Allgemeine Java-Themen 6
R Warum wird mir in der Konsole das "Standard Array" ausgegeben? Allgemeine Java-Themen 2
N Variablen Array Länge ändern. Allgemeine Java-Themen 8
D Kgv aller Paare aus einem Array mit n integer berechnen Allgemeine Java-Themen 5
W Enumeration ein Array/List als Eigenschaft mitgeben - warum geht das nicht? Allgemeine Java-Themen 0
kodela Problem mit strukturiertem Array Allgemeine Java-Themen 18
A Array Problem Allgemeine Java-Themen 8
Drachenbauer Wie stelle ich fest, ob ein Objekt in meinem Array vorkommt? Allgemeine Java-Themen 5
F Datei in String-Array einlesen Allgemeine Java-Themen 8
L Objekt aus Objekt-array "löschen" Allgemeine Java-Themen 2
I Array Parameter mit 2 Klassen - NullPointerException Allgemeine Java-Themen 3
X Größten Werte in meinem Array löschen? Allgemeine Java-Themen 16
E Angabe wie groß Array sein soll und in for-schleifen diesen Array füllen Allgemeine Java-Themen 3
F 3 Dimensionales Array mit Allgemeine Java-Themen 9
M Steueralgorithmus verwandelt Array in Anfangszustand Allgemeine Java-Themen 9
W Array vs. ArrayList vs. HashMap Allgemeine Java-Themen 20
D Datentypen 2-3 Baum erstellen mit geordnetem int-array Allgemeine Java-Themen 0
T Objekt in Array packen Allgemeine Java-Themen 6
M Zahlen in Array anordnen Allgemeine Java-Themen 8
M Eclipse Unvollständigen Array ansteuern Allgemeine Java-Themen 2
D Erste Schritte Im Array Werte tauschen Allgemeine Java-Themen 5
Xge For/Array Error: IndexOutOfBounds Allgemeine Java-Themen 4
M Wie kann ich ein int[] Array in einer Methode benutzen? Allgemeine Java-Themen 6
FRI3ND Datentypen Date-Array sortieren - Text mitnehmen? Allgemeine Java-Themen 7
D Integer-Array variabler Größe mit Zahlen befüllen (Schleifen) Allgemeine Java-Themen 0
J Variablen Array ertellen bei model.put Allgemeine Java-Themen 13
S Eindimensionales Array in zweidimensionales Array speichern Allgemeine Java-Themen 5
R convert 2d array list to 2d array Allgemeine Java-Themen 1
J json Array würfel Spalten durcheinander Allgemeine Java-Themen 9
MiMa Array umbau oder Alternative? Allgemeine Java-Themen 5
L Datentypen 3D Array Allgemeine Java-Themen 3
M 2D Array mit unterschiedlichen Längen erstellen und befüllen Allgemeine Java-Themen 11
Mario1409 Methoden JSON Array von URL Allgemeine Java-Themen 8
E Swing Array mit Bildern in GUI darstellen Allgemeine Java-Themen 2
P Array einer abstrakten Klasse Allgemeine Java-Themen 4
H Zweidimensionales Array - Zellen der Tabelle verbinden Allgemeine Java-Themen 2
M Zweidimensionales Array mit Binärzahlen füllen Allgemeine Java-Themen 8
M Array aus Thread Objekten erstellen Allgemeine Java-Themen 2
kodela Dynamisches Array in einer Klasse Allgemeine Java-Themen 5
G Array ohne Aufzählungszeichen ausgeben Allgemeine Java-Themen 6
J Wie kann ich ein Java Array als Säulendiagramm ausgeben? Allgemeine Java-Themen 2
Z 2D Array Pixels reparieren Allgemeine Java-Themen 2
S Algorithmus welcher True-Werte in einem Array findet und auswertet. Allgemeine Java-Themen 5
B Polibios Array erweitern Allgemeine Java-Themen 1
R Index in einem Array löschen Allgemeine Java-Themen 10
R Index in einem Array löschen Allgemeine Java-Themen 2
U Methoden Algorithmus MergeSort String [ ] array sortieren programmieren Allgemeine Java-Themen 17
J Array-List Bubble-Sort Allgemeine Java-Themen 12
4 Variablen Int-Array Int Zuweisen Allgemeine Java-Themen 7
J Array Allgemeine Java-Themen 8
Z Array mit unterschiedlichen Werten Allgemeine Java-Themen 1
L sortiertes Array im main aufrufen klappt nicht. Allgemeine Java-Themen 3
O Mein JButton Array funktioniert nicht Allgemeine Java-Themen 3
A Mit dem letzten bis zum ersten Wert aus Array rechnen Allgemeine Java-Themen 15
A Vector Strings in Array splitten Allgemeine Java-Themen 6
I Muster in Array suchen Allgemeine Java-Themen 10
RalleYTN Datentypen Herausfinden ob Object ein Array ist ohne den Typen des Arrays zu kennen? Allgemeine Java-Themen 12
S Variablen String[] Array per schleife in int[] einlesen Allgemeine Java-Themen 8
B Zahlen manuell eingeben und in Array Speichern Allgemeine Java-Themen 2
R Wärmeleitung, 3d-Array Allgemeine Java-Themen 2
T Java Array in Methoden Allgemeine Java-Themen 1

Ähnliche Java Themen

Neue Themen


Oben