Warum ist dieser Code mit mehreren "oder" Anweisungen etwas schneller als die Verwendung einer Nachschlagetabelle in Java?

8

Beim Betrachten einer Frage zur Mikrooptimierung, die ich gestern gefragt habe ( hier ), ich fand etwas Seltsames: Eine or -Anweisung in Java läuft etwas schneller, als einen booleschen Wert in einem Booleschen Array nachzuschlagen.

In meinen Tests läuft alg1 um 2% schneller als die folgenden Algorithmen auf long -Werten von 0 bis 1 Milliarde. (Ich habe die Reihenfolge geändert, in der die Algorithmen getestet werden, und ich bekomme die gleichen Ergebnisse). Meine Frage ist: Warum ist alg1 schneller? Ich hätte erwartet, dass alg2 etwas schneller ist, da es eine Nachschlagetabelle verwendet, während alg1 4 Vergleiche und 3 oder Operationen für 75% der Eingaben ausführen muss / p> %Vor%

Wenn Sie neugierig sind, testet dieser Code, ob eine Zahl ein perfektes Quadrat ist, und verwendet die Tatsache, dass perfekte Quadrate in hexadezimal 0, 1, 4 oder 9 enden müssen.

    
Kip 18.11.2008, 15:34
quelle

5 Antworten

6

Das Laden einiger zufälliger Daten ist im Allgemeinen langsamer als ein wenig nicht verzweigter Code.

Natürlich hängt alles von der Prozessorarchitektur ab. Ihre erste if-Anweisung könnte als vier Anweisungen implementiert werden. Die zweite kann potentiell Null-Zeigerüberprüfung, Grenzüberprüfung sowie das Laden und Vergleichen benötigen. Auch mehr Code bedeutet mehr Kompilierzeit und mehr Chance für die Optimierung in irgendeiner Weise beeinträchtigt werden.

    
Tom Hawtin - tackline 18.11.2008, 16:02
quelle
3

Ich würde raten , dass das Problem darin besteht, dass der Bereich nach dem Array sucht und ob das Array-Lookup als Methodenaufruf implementiert ist. Das würde sicherlich 4 direkte Vergleiche überschatten. Haben Sie sich den Byte-Code angesehen?

    
plinth 18.11.2008 15:41
quelle
1

Nach diesem Artikel Zugriff auf Array-Elemente sind "2- oder 3-mal so teuer wie der Zugriff auf Nicht-Array-Elemente". Ihr Test zeigt, dass der Unterschied möglicherweise noch größer ist.

    
asalamon74 18.11.2008 15:41
quelle
0

Es ist ein interessantes Stück Code, aber 2% ist ein wirklich kleiner Unterschied. Ich glaube nicht, dass Sie daraus sehr viel schließen können.

    
Mike Dunlavey 19.11.2008 00:11
quelle
0

Im aktuellen Beispiel stimme ich zu, dass die Überprüfung der Grenzen wahrscheinlich das ist, was Sie erreicht (warum die JVM dies nicht optimiert, übersteigt mich) - der Beispielcode könnte deterministisch nicht überlaufen ...

Eine andere Möglichkeit (besonders bei größeren Nachschlagetabellen) ist die Cache-Latenz ... Es hängt von der Größe der Register der Prozessoren ab und wie die JVM sie verwendet - wenn aber das Byte-Array nicht vollständig auf dem Prozessor bleibt, dann sehen Sie einen Leistungseinbruch im Vergleich zu einem einfachen OR, da das Array für jede Prüfung auf die CPU gezogen wird.

    
Kevin Day 20.11.2008 03:52
quelle

Tags und Links