#define vs. Methode mit Rückgabewert

  • #define vs. Methode mit Rückgabewert

    Ich frage mich gerade, wo die Unterschiede zwischen #define und einer Methode mit Rückgabewert liegen bzw. welche gerade auf iOS performanter wäre.

    Ein Beispiel:

    Quellcode

    1. #define IS_PRINTING_AVAILABLE NSClassFromString(@"UIPrintInteractionController") != nil
    2. - (BOOL)printingAvailable {
    3. return NSClassFromString(@"UIPrintInteractionController") != nil;
    4. }
  • performanter ist in dem moment das #define (der methodenaufruf fällt weg), es könnte aber eventuell schneller sein wenn du die methode tunest indem du nur einmal verscuhst due klasse zu erstellen und das ergebnis dann speicherst (in einem int zb).
    aber gemessen hab ichs nicht (kommt auch drauf an wieviele millionen mal du das pro sekunde aufrufst ;-))

    btw:

    Quellcode

    1. #define IS_PRINTING_AVAILABLE (NSClassFromString(@"UIPrintInteractionController") != nil)
  • Der define ist in so einem fall immer schneller, denn der "inhalt" vom define wird vor dem compilieren einfach überall dort wo das define benutzt wird eingesetzt.
    Somit sparst du dir logischerweise den funktionsaufruf.

    Aber z.B. bei diesem Beispiel:

    Quellcode

    1. #define CLAMP(x, vmin, vmax) (x > vmax ? vmax : (x < vmin ? vmin : x))
    2. float clamp(float x, float vmin, float vmax)
    3. {
    4. return (x > vmax ? vmax : (x < vmin ? vmin : x));
    5. }
    6. clampedX = CLAMP(sqrt(x * 26 / 13 - 5) * 123 / pow(45, 20)), 0, 100)
    7. clampedX = clamp(sqrt(x * 26 / 13 - 5) * 123 / pow(45, 20)), 0, 100)


    ist die funktion um längen schneller, denn die Rechnung "sqrt(x * 26 / 13 - 5) * 123 / pow(45, 20))" wird einmal berechnet und das ergebnis wird der funktion übergeben. Diese vergleicht nun einfach die floats und ist fertig.
    Bei dem define würde die Berechnung drei mal stattfinden, denn für jedes "x" würde "sqrt(x * 26 / 13 - 5) * 123 / pow(45, 20))" eingesetzt werden im code. Und diese drei berechnungen dauern mit sicherheit länger als ein kleiner funktionsaufruf ;)

    Kira
  • Der Unterschied ist, dass die eine Alternative eine echte Methode generiert und die andere einfach vor dem Kompilieren ein Find-Replace macht. Das Thema hatten wir hier schon oft und hitzig. Ich bin kein #define-Exorzist, aber man sollte die Dinger nur einsetzen, wenn es nötig ist (und wenn man ganz genau weiß, was man tut). Sie sind nicht typsicher, können ekelige Nebeneffekte haben und Compilerausgaben unleserlich machen (eben weil beim Compilieren dort nicht mehr das steht, was im Editor noch da war).

    In höheren Optimierungsebenen kann eine schnöde C-Funktion schneller als beide genannten Alternativen sein, weil der Compiler die Funktion entsprechend der Optimierungsanforderungen auto-inlinen kann, aber (im Gegensatz zum #define) nicht muss. Performancevorteile von kleinerem Code können u.U. den Overhead des Funktionsaufrufs kompensieren.

    Aber wie gritsch schon sagte: In diesem Fall dürfte es erheblich mehr bringen, das Ergebnis zu cachen.

    Und: POITROAE! Wenn Du ein Performance-Problem hast, kann ich mir nur schwer vorstellen, dass es an dieser Stelle liegt. Und selbst wenn, ist die Lösung mit Sicherheit anders als eine schnellere Implementierung der Abfrage.
    Multigrad - 360°-Produktfotografie für den Mac
  • Kira schrieb:

    ist die funktion um längen schneller, denn die Rechnung "sqrt(x * 26 / 13 - 5) * 123 / pow(45, 20))" wird einmal berechnet und das ergebnis wird der funktion übergeben. Diese vergleicht nun einfach die floats und ist fertig.

    Ich würde mal tippen, dass solange x nicht volatile ist, der compiler auch so clever ist, das bei dem #define herauszuoptimieren. Verlassen sollte man sich aber nicht darauf ;)

    Ich schliesse mich ansonsten natürlich der Allgemeinheit an:
    1. Diese "Optimierung" kostet Dich mehr, als sie bringen wird. Bei soetwas fällt der Funktionsaufruf doch nicht ins Gewicht, aber der Code wird komplizierter und Du holst Dir unter Umständen andere Probleme ins Haus.
    2. Diese "Optimierung" bringt wahrscheinlich nichts, wie Kira und mattik schon geschrieben haben, da eine C-Funktion wahrscheinlich inlined wird.
    3. Den Präprozessor sollte man, meiner Meinung nach, nur bemühen, wenn es keine einzige andere Möglichkeit gibt.
    C++