Schnellste Methode ein Array zu durchlaufen?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Schnellste Methode ein Array zu durchlaufen?

    Guten Abend,

    ich würde gern wissen welche dieser drei Versionen die Schnellste ist?

    Quellcode

    1. [activeBodies enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    2. [obj restoreState];
    3. }];


    Quellcode

    1. [activeBodies performSelector:@selector(restoreState)];


    Quellcode

    1. for(Body *activeBody in activeBodies) {
    2. [activeBody restoreState];
    3. }


    Gibts vielleicht ein schlanke Möglichkeit das zu Benchmarken?

    Vielen Dank,
    ToBSN
  • Zeitverschwendung. Die Unterschiede hier sind minimal. Solange du nicht gerade "objectAtIndex" benutzt, ist alles okay.

    Die dritte Methode ist vermutlich die Schnellste und die ersten beiden werden indirekt darüber implementiert.

    Außerdem meinst du wohl eher "makeObjectsPerformSelector" statt "performSelector".

    Benchmarken kannst du das außerdem ruhig selber, etwa mit mach_absolute_time() aus <mach/mach_time.h>-

    Wenn du es wirklich eilig hast, etwa in einer oft benutzten Funktion eines Spiels oder bei wissenschaftlichen Berechnungen, solltest du Objective-C-Kram eh einfach bleiben lassen und C-Arrays benutzen.
  • system schrieb:

    Wenn du es wirklich eilig hast, etwa in einer oft benutzten Funktion eines Spiels oder bei wissenschaftlichen Berechnungen, solltest du Objective-C-Kram eh einfach bleiben lassen und C-Arrays benutzen.

    Warum?
    Solange es Java-Portierungen von Quake2 gibt, würde ich mir um die Geschwindigkeit von Objective-C keine Sorgen machen.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Lucas de Vil schrieb:

    system schrieb:

    Wenn du es wirklich eilig hast, etwa in einer oft benutzten Funktion eines Spiels oder bei wissenschaftlichen Berechnungen, solltest du Objective-C-Kram eh einfach bleiben lassen und C-Arrays benutzen.

    Warum?
    Solange es Java-Portierungen von Quake2 gibt, würde ich mir um die Geschwindigkeit von Objective-C keine Sorgen machen.

    Was ist denn das für eine Aussage?! Quake 2 ist ewig alt. Heutzutage kratzt es lange nicht mehr am Rand des Möglichen. Die Graphik läuft über OpenGL Hardwarebeschleunigt. Das hat nicht mit der Sprache zu tun. Aber was hat die Geschwindigkeit von Java mit der von Obj-C zu tun?
    C++
  • zerm schrieb:

    Lucas de Vil schrieb:

    system schrieb:

    Wenn du es wirklich eilig hast, etwa in einer oft benutzten Funktion eines Spiels oder bei wissenschaftlichen Berechnungen, solltest du Objective-C-Kram eh einfach bleiben lassen und C-Arrays benutzen.

    Warum?
    Solange es Java-Portierungen von Quake2 gibt, würde ich mir um die Geschwindigkeit von Objective-C keine Sorgen machen.

    Was ist denn das für eine Aussage?! Quake 2 ist ewig alt. Heutzutage kratzt es lange nicht mehr am Rand des Möglichen. Die Graphik läuft über OpenGL Hardwarebeschleunigt. Das hat nicht mit der Sprache zu tun. Aber was hat die Geschwindigkeit von Java mit der von Obj-C zu tun?

    Was ist das für eine Aussage ??

    Würdest du einen 3D-Shooter in VB programmieren, nur weil es dort eine OpenGL-Schnittstelle gibt ?? Na also, Java ist nicht das Schnellste das ist kein Geheimnis. Es hat schon einen Grund warum die allermeisten Spiele in C/C++ oder eben Obj.C gemacht werden.Das alles hat zunächst mal nix mit der Grafikausgabe zu tun, sondern mit der "Performance" der verwendeten Sprache. Das man auch in C murks machen kann, steht da nicht zur Debatte.
  • system schrieb:

    Wenn du es wirklich eilig hast, etwa in einer oft benutzten Funktion eines Spiels oder bei wissenschaftlichen Berechnungen, solltest du Objective-C-Kram eh einfach bleiben lassen und C-Arrays benutzen.

    Naja, würd ich nicht generell sagen, in C musst du dich erst mal selbst um verkettete Listen (oder was auch immer) kümmern, wenn du die scheiße implementierst gewinnst du damit auch keinen Blumentopf.
  • wolf_10de schrieb:

    Würdest du einen 3D-Shooter in VB programmieren, nur weil es dort eine OpenGL-Schnittstelle gibt ?? Na also, Java ist nicht das Schnellste das ist kein Geheimnis. Es hat schon einen Grund warum die allermeisten Spiele in C/C++ oder eben Obj.C gemacht werden.Das alles hat zunächst mal nix mit der Grafikausgabe zu tun, sondern mit der "Performance" der verwendeten Sprache. Das man auch in C murks machen kann, steht da nicht zur Debatte.

    Es stimmt, das viele moderne Spiele auch CPU-bound sind. Das rührt aber i.d.R. hauptsächlich her von der komplexe Spiellogik, KI und evtl. Physik (sofern die auf der CPU läuft). Bei effizienter Verwendung von OpenGL hat man sehr wenig Last auf der CPU durch die Graphik, entsprechend ist die Sprache egal. Schliesslich ist es egal, in welcher Sprache ich meine Daten auf die Graphikkarte herunterlade, der Aufwand für den Call verschwindet gegenüber dem Transfer bzw. der Ausführung. Bei komplexeren Multi-pass Verfahren oder was-weiss-der-Teufel mag das ein wenig anders sein, aber das ist bei Quake 2 nicht der Fall. Von daher nehme ich stark an, dass es ähnlich performant unter VB oder meinetwegen Brainfuck läuft, sofern es ordentlich OpenGL-Schnittstellen gibt.

    wolf_10de schrieb:

    Naja, würd ich nicht generell sagen, in C musst du dich erst mal selbst um verkettete Listen (oder was auch immer) kümmern, wenn du die scheiße implementierst gewinnst du damit auch keinen Blumentopf.

    Darum nimmt man auch C++, da hat man schon alles dabei ;)
    C++
  • zerm schrieb:

    Es stimmt, das viele moderne Spiele auch CPU-bound sind. Das rührt aber i.d.R. hauptsächlich her von der komplexe Spiellogik, KI und evtl. Physik (sofern die auf der CPU läuft). Bei effizienter Verwendung von OpenGL hat man sehr wenig Last auf der CPU durch die Graphik, entsprechend ist die Sprache egal. Schliesslich ist es egal, in welcher Sprache ich meine Daten auf die Graphikkarte herunterlade, der Aufwand für den Call verschwindet gegenüber dem Transfer bzw. der Ausführung. Bei komplexeren Multi-pass Verfahren oder was-weiss-der-Teufel mag das ein wenig anders sein, aber das ist bei Quake 2 nicht der Fall. Von daher nehme ich stark an, dass es ähnlich performant unter VB oder meinetwegen Brainfuck läuft, sofern es ordentlich OpenGL-Schnittstellen gibt.


    Genau darum geht es, nicht um OpenGL / GPU sondern um die Dinge die du angesprochen hast (Logik, usw...) die laufen zumindest bei älteren Spielen noch auf der CPU, weshalb die verwendete Sprache in diesem Fall nicht egal ist. Da sind wir nämlich wieder beim Thema, ein Array in C ist garantiert schneller als eines in Java ;)
  • zerm schrieb:

    Es stimmt, das viele moderne Spiele auch CPU-bound sind. Das rührt aber i.d.R. hauptsächlich her von der komplexe Spiellogik, KI und evtl. Physik (sofern die auf der CPU läuft). Bei effizienter Verwendung von OpenGL hat man sehr wenig Last auf der CPU durch die Graphik, entsprechend ist die Sprache egal. Schliesslich ist es egal, in welcher Sprache ich meine Daten auf die Graphikkarte herunterlade, der Aufwand für den Call verschwindet gegenüber dem Transfer bzw. der Ausführung. Bei komplexeren Multi-pass Verfahren oder was-weiss-der-Teufel mag das ein wenig anders sein, aber das ist bei Quake 2 nicht der Fall. Von daher nehme ich stark an, dass es ähnlich performant unter VB oder meinetwegen Brainfuck läuft, sofern es ordentlich OpenGL-Schnittstellen gibt.


    Nicht ganz, in VB oder Java machst du ja bestimmten keine "nativen" C-Calls aller glBegin(...), da gibt es soweit ich weiß immer einen Wrapper, der dann die Funktion ausführt, somit bleibt die Geschwindigkeit bestimmt hinten an.

    Aber egal, dererlei Diskussionen hatten wir ja schon oft, schlussendlich muss man erstmal soweit kommen um über Performance-Probleme zu reden, in aller Regel klemmt es nämlich an anderen Stellen.
  • wolf_10de schrieb:

    zerm schrieb:

    Darum nimmt man auch C++, da hat man schon alles dabei

    Ohne STL sieht es da aber auch düster aus ;)

    Die "STL" gehört zum Sprachstandard. Ohne STL kein C++. (NB: "Die STL" ist eine Implementierung dessen, was später zum Sprachstandard wurde. In dem Sinne hat man alles unter C++ auch ohne "STL"; tatsächlich muss man kein einziges mal "STL" irgendwo erwähnen, um die std-lib zu verwenden.)
    Ich kann darauf vertrauen, dass wenn ich einen C++ Compiler habe, der auch std::list kann. Sonst ist es kein konformer C++ Compiler.
    C++
  • wolf_10de schrieb:

    zerm schrieb:

    Es stimmt, das viele moderne Spiele auch CPU-bound sind. Das rührt aber i.d.R. hauptsächlich her von der komplexe Spiellogik, KI und evtl. Physik (sofern die auf der CPU läuft). Bei effizienter Verwendung von OpenGL hat man sehr wenig Last auf der CPU durch die Graphik, entsprechend ist die Sprache egal. Schliesslich ist es egal, in welcher Sprache ich meine Daten auf die Graphikkarte herunterlade, der Aufwand für den Call verschwindet gegenüber dem Transfer bzw. der Ausführung. Bei komplexeren Multi-pass Verfahren oder was-weiss-der-Teufel mag das ein wenig anders sein, aber das ist bei Quake 2 nicht der Fall. Von daher nehme ich stark an, dass es ähnlich performant unter VB oder meinetwegen Brainfuck läuft, sofern es ordentlich OpenGL-Schnittstellen gibt.


    Nicht ganz, in VB oder Java machst du ja bestimmten keine "nativen" C-Calls aller glBegin(...), da gibt es soweit ich weiß immer einen Wrapper, der dann die Funktion ausführt, somit bleibt die Geschwindigkeit bestimmt hinten an.

    Aber egal, dererlei Diskussionen hatten wir ja schon oft, schlussendlich muss man erstmal soweit kommen um über Performance-Probleme zu reden, in aller Regel klemmt es nämlich an anderen Stellen.

    glBegin verwendet man ohnehin nicht, und generell (auch in C) gilt es, die Menge an OpenGL-Calls gering zu halten. Ob z.B. glDrawElements etwa direkt aufgerufen wird, oder über einen Wrapper ist, wenn man es richtig anstellt, idR unerheblich.
    Und mit OpenGL-Performance beschäftige ich mich oft genug, um zu wissen, wovon ich rede ;)
    C++
  • zerm schrieb:

    glBegin verwendet man ohnehin nicht,

    Das war ein Beispiel

    zerm schrieb:


    und generell (auch in C) gilt es, die Menge an OpenGL-Calls gering zu halten. Ob z.B. glDrawElements etwa direkt aufgerufen wird, oder über einen Wrapper ist, wenn man es richtig anstellt, idR unerheblich.

    Wenn man was richtig anstellt ???
    Ich bin mir sicher das

    Quellcode

    1. glDrawElements(....);

    und

    Quellcode

    1. gl.glDrawElements(....);

    sehr wohl einen Unterschied machen, letzteres ruft eine Java-Methode auf und keine C-Funktion..

    zerm schrieb:

    Und mit OpenGL-Performance beschäftige ich mich oft genug, um zu wissen, wovon ich rede

    Das will ich gar nicht in Frage stellen
  • wolf_10de schrieb:

    zerm schrieb:

    glBegin verwendet man ohnehin nicht,

    Das war ein Beispiel

    zerm schrieb:


    und generell (auch in C) gilt es, die Menge an OpenGL-Calls gering zu halten. Ob z.B. glDrawElements etwa direkt aufgerufen wird, oder über einen Wrapper ist, wenn man es richtig anstellt, idR unerheblich.

    Wenn man was richtig anstellt ???
    Ich bin mir sicher das

    Quellcode

    1. glDrawElements(....);

    und

    Quellcode

    1. gl.glDrawElements(....);

    sehr wohl einen Unterschied machen, letzteres ruft eine Java-Methode auf und keine C-Funktion..

    zerm schrieb:

    Und mit OpenGL-Performance beschäftige ich mich oft genug, um zu wissen, wovon ich rede

    Das will ich gar nicht in Frage stellen

    Natürlich macht es einen Unterschied. Aber nur einen geringen, du wirst schliesslich nicht soviele OpenGL-Calls feuern pro Frame, dass dies ins Gewicht fällt. Ich glaube auch nicht, dass der Overhead durch die Wrapper so bedeutsam ist. High-End Anwendungen, die hart am Limit laufen, können sich soetwas vielleicht nicht leisten, meinetwegen. Aber Quake 2? Das läuft doch sicherlich inzwischen sogar flüssig, wenn ich es komplett im Emulator laufen lasse :P
    C++
  • zerm schrieb:


    glBegin verwendet man ohnehin nicht, und generell (auch in C) gilt es, die Menge an OpenGL-Calls gering zu halten.

    Tut man nicht? Was nimmt man denn stattdessen?
    Oder lässt man einfach nur die Finger von den Methoden in gl.h und nutzt ausschließlich die aus glu.h?
    Ich zeige mich sichtlich verwirrt...

    zerm schrieb:

    Natürlich macht es einen Unterschied. Aber nur einen geringen, du wirst schliesslich nicht soviele OpenGL-Calls feuern pro Frame, dass dies ins Gewicht fällt. Ich glaube auch nicht, dass der Overhead durch die Wrapper so bedeutsam ist. High-End Anwendungen, die hart am Limit laufen, können sich soetwas vielleicht nicht leisten, meinetwegen. Aber Quake 2? Das läuft doch sicherlich inzwischen sogar flüssig, wenn ich es komplett im Emulator laufen lasse

    Genau das meinte ich.
    Bei den heutigen CPU- und GPU-Leistungen ist es total egal, wie viel Overhead da produziert wird.
    Da ich mir einfach nicht vorstellen kann, dass jemand hier privat versuchen wird Aion oder Ähnliches nachzuprogrammieren, halte ich meine obige Aussage für korrekt. ^^
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Lucas de Vil schrieb:

    zerm schrieb:


    glBegin verwendet man ohnehin nicht, und generell (auch in C) gilt es, die Menge an OpenGL-Calls gering zu halten.

    Tut man nicht? Was nimmt man denn stattdessen?
    Oder lässt man einfach nur die Finger von den Methoden in gl.h und nutzt ausschließlich die aus glu.h?
    Ich zeige mich sichtlich verwirrt...

    Nein, glBegin verwendet man nicht ernsthaft und ist in OpenGL 3.x auch deprecated. Es ist einfach nicht sinnvoll, Vertices/Attribute mit einzelnen Calls auf die Graphikkarte (bzw. den Server) zu laden. Hier gibt es Buffer Objekte (bzw. glVertexPointer etc.) und z.B. glDrawElements. Stell Dir vor, Du hast 4M Vertices, das würde zu 4M glVertex Calls (und ggf, zu 4M glNormal und 4M glTexCoord Calls) führen und ist niemals performant. Das ganze frühstückt man mit ein paar anderen Calls ab. Strenggenommen macht OpenGL intern auch nichts anderes, als alle Calls innerhalb glBegin abzuwarten, aufzusammeln und ein in einem Rutsch an der Server zu übermitteln.
    glBegin ("immediate mode") war von je her nur zu Debug/Test- und Lernzwecken. Da das Konsortium inzwischen wesentlich mehr Wert darauf legt, redundante und überflüssige API Calls zu entfernen, ist es daher auch deprecated. Wenn Du soetwas immer noch brauchen solltest, kannst Du es Dir auf andere Weise nachbauen. OpenGL will lowest-level sein.

    Lucas de Vil schrieb:


    zerm schrieb:

    Natürlich macht es einen Unterschied. Aber nur einen geringen, du wirst schliesslich nicht soviele OpenGL-Calls feuern pro Frame, dass dies ins Gewicht fällt. Ich glaube auch nicht, dass der Overhead durch die Wrapper so bedeutsam ist. High-End Anwendungen, die hart am Limit laufen, können sich soetwas vielleicht nicht leisten, meinetwegen. Aber Quake 2? Das läuft doch sicherlich inzwischen sogar flüssig, wenn ich es komplett im Emulator laufen lasse

    Genau das meinte ich.
    Bei den heutigen CPU- und GPU-Leistungen ist es total egal, wie viel Overhead da produziert wird.
    Da ich mir einfach nicht vorstellen kann, dass jemand hier privat versuchen wird Aion oder Ähnliches nachzuprogrammieren, halte ich meine obige Aussage für korrekt. ^^

    Jain. Tatsächlich wird für die meissten dieser Overhead vernachlässigbar sein, sofern man auf bspw. oben genanntes achtet. Ich habe ja schon Anfänger erlebt, die ein 800x600 Bild in OpenGL mit 800*600=480000 glVertex und glColor Calls dargestellt haben. Das hat dann grad noch geklappt, bei 2048x2048 ist dann die Framerate aber derbe eingebrochen....(Obwohl die GPU Däumchen dreht)
    C++
  • Quellcode

    1. #import
    2. @interface BaseObject : NSObject {
    3. int idx;
    4. }
    5. - (void)doSomeCrazyStuff;
    6. @property (readwrite) int idx;
    7. @end
    8. @implementation BaseObject
    9. @synthesize idx;
    10. - (void)doSomeCrazyStuff {
    11. //do some crazy stuff here!
    12. NSLog(@"doSomeCrazyStuff: %@ - %i", self, idx);
    13. }
    14. @end
    15. #define MAX_OBJECTS 10
    16. int main(int argc, char *argv[])
    17. {
    18. BaseObject *objects = (BaseObject*)calloc(MAX_OBJECTS, sizeof(BaseObject));
    19. int i;
    20. for (i = 0; i < MAX_OBJECTS; i++) {
    21. BaseObject *obj = [BaseObject new];
    22. obj.idx = i;
    23. objects[i] = *obj;
    24. }
    25. for (i = 0; i < MAX_OBJECTS; i++) {
    26. BaseObject *obj = &objects[i];
    27. [obj doSomeCrazyStuff];
    28. }
    29. //[objects release];
    30. NSLog(@"%@", objects);
    31. free(objects);
    32. objects = nil;
    33. NSLog(@"%@", objects);
    34. return 0;
    35. }
    Alles anzeigen


    Das wahrscheinlich schnellste Variante ist das über ein Stack zu lösen, richtig?
    Was muss ich machen um sicher zu sein das Speicher auch wieder freigeben wird?