Projektstruktur: Header Dateien im seperaten include folder?



  • @Finnegan sagte in Projektstruktur: Header Dateien im seperaten include folder?:

    @hustbaer sagte in Projektstruktur: Header Dateien im seperaten include folder?:

    Gibt aber Projekte wo überraschend wenig übrig bleibt wenn man konsequent alles wo es (bewiesenermassen, Profiler) wörscht ist aus den .h Files raus in die .cpp-s verschiebt.

    Ich würde auch sagen, dass sowas haupstächlich in Bibliotheken Anwendung finden sollte. Vor allem, weil diese nicht wissen können, in welchem Kontext sie letztendlich verwendet werden und es eben nicht "wörscht" sein könnte. In Anwendungscode habe ich selbst auch nur selten Bedarf für inline oder exzessive Nutzung von Templates.

    Nene, das Verschieben raus aus den Headers rein ins cpp macht auch bei Libraries extrem viel Sinn. Ist ja nicht jeder Algorithmus ein dürres Gerüst um irgendwelche Iteratoren/Funktoren/Traits die nach Inlining u.U. komplett verdampfen. Sowas wie nen Regex Matcher generisch auf Ranges/Iteratoren zu implementieren macht IMO exakt keinen Sinn. Das macht man 1x für ein Zeigerpaar, im .cpp File, und dann stoppelt man inline Wrapper für contiguous sequences drann.

    Ich würde nicht versuchen, dieses Verhalten über das inline-Schlüsselwort zu steuern. Wenn sich hier tatsächlich ein Problem zeigt, erachte ich es als sinnvoller, das mit compilerspezifischen noinline-Mechanismen zu erschlagen:
    ...

    Richtig, steuern sollte man es nicht darüber. Ich wollte lediglich darauf hinaus dass weniger Inlining sogar oft bessere Performance bedeutet.



  • Dieser Beitrag wurde gelöscht!


  • @hustbaer sagte in [Projektstruktur: Header Dateien im

    Ich würde auch sagen, dass sowas haupstächlich in Bibliotheken Anwendung finden sollte.

    Nene, das Verschieben raus aus den Headers rein ins cpp macht auch bei Libraries extrem viel Sinn. Ist ja nicht jeder Algorithmus ein dürres Gerüst um irgendwelche Iteratoren/Funktoren/Traits die nach Inlining u.U. komplett verdampfen.

    Ich habe nicht gesagt, dass es in die .cpp zu packen bei Bibliotheken keinen Sinn macht, sondern dass Templates und inline-Funktionen eher ein, Library-Ding sind.

    Sowas wie nen Regex Matcher generisch auf Ranges/Iteratoren zu implementieren macht IMO exakt keinen Sinn. Das macht man 1x für ein Zeigerpaar, im .cpp File, und dann stoppelt man inline Wrapper für contiguous sequences drann.

    Das ist ein schönes Beispiel. Es macht schon manchmal Sinn für generischen Code "Terminatoren" zu haben, die das "Generische" an dem Punkt unterbrechen, wo man das Problem auf ein spezielles heruntergebrochen hat - z.B. auf zusammenhängende chars im Speicher. Generisch muss der Code hier nur sein um diese chars aus beliebigen Datenstrukturen "auspacken" zu können.

    Ich mache das auch schonmal gerne so, dass ich einen lowlevel-Algorithmus schreibe, der beinahe C sein könnte und dann ein schönes generisches C++-Interface oben drauf setze. Für manche Probleme ist das eine gute Lösung.

    Richtig, steuern sollte man es nicht darüber. Ich wollte lediglich darauf hinaus dass weniger Inlining sogar oft bessere Performance bedeutet.

    Ja, ich verstehe, worauf du hinaus wolltest. Ich habe den Thread zu den Exceptions auf ARM im Nachbarforum gelsesen.

    Das ist schon etwas erschreckend, dass die Compiler sowas scheinbar nicht immer gut hinbekommen. Vielleicht liegt es aber auch daran, dass der Compiler nur die eine Übersetzungseinheit sieht und in dieser ist das dann isoliert betrachtet vertretbar (?).

    Schlimm wäre es, wenn das mit LTO oder PGO+LTO in grossen Programmen immer noch so aussähe. Werde das mal im Hinterkopf behalten und in Zukunft genauer beobachten. Bisher hatte ich das noch nicht so auf dem Schirm.



  • @Finnegan Dort ging's ja eher um das Einziehen von Hilfsfunktionen als darum ob man die manuell als "noinline" markieren muss. Und da finde ich nicht erschreckend dass Compiler das nicht können. Also das Erkennen von identischen Teilabschnitten von Funktionen + Deduplication dieser Teilabschnitte. Es wäre cool wenn sie es könnten, aber... is halt nich.

    Explizit als "noinline" markieren muss man nämlich anscheinend oft gar nicht. Zumindest GCC und Clang sind schlau genug z.B. "noreturn" Funktionen nicht zu inlinen . Also sowohl welche die explizit "noreturn" gemacht wurden als auch welche wo der Compiler sieht dass es einfach keinen normalen Exit-Pfad gibt.
    D.h. wenn man wo

    inline void throwBlahError(...) {
       ...
       throw BlahError(...);
    }
    

    stehen hat, dann reicht das. Explizites "noreturn" oder gar "noinline" bei der Definition von throwBlahError ist nicht nötig.

    Obwohl ich es (noinline) dann trotzdem auch dazuschreibe. Weil wenn ich mir schon die Arbeit mache throwBlahError als Funktion rauszuziehen, dann is das auch schon wurscht, bzw. sogar gut weil es dokumentiert wozu throwBlahError überhaupt in eine Funktion rausgezogen wurde.



  • @hustbaer sagte in Projektstruktur: Header Dateien im seperaten include folder?:

    Weil wenn ich mir schon die Arbeit mache throwBlahError als Funktion rauszuziehen, dann is das auch schon wurscht, bzw. sogar gut weil es dokumentiert wozu throwBlahError überhaupt in eine Funktion rausgezogen wurde.

    Mich wundert schon etwas, dass der Compiler das throw nicht erstmal intern wie eine Funktion behandelt - wie z.B. auch das new mit einer ähnlichen Syntax auch erstmal eine (Operator-)Funktion ist - und dann seine übliche Entscheidung trifft, ob er es inlined oder nicht. Das würde es zumindest nicht mehr nötig machen, dass du dir darüber den Kopf zerbrechen musst (gut, throw kann man nicht überladen, aber es sollte nicht zu kompliziert sein, da implizit eine Funktion draus zu machen).

    Bevor ich den Thread gelesen habe, hätte ich eigentlich gedacht, dass throw dass es so wäre - vielleicht mit ein paar Sonderbehandlungen, dass z.B. __internal_throw den Stack Frame wieder zurücksetzt, so dass es von aussen (z.B. für den Debugger) so aussieht, als sei dort geworfen worden wo auch das throwsteht, und nicht in __internal_throw.

    Naja, kann alles nur besser werden. Die Compiler sind dennoch schon beeindruckend gut geworden 😉



  • @Finnegan sagte in Projektstruktur: Header Dateien im seperaten include folder?:

    Mich wundert schon etwas, dass der Compiler das throw nicht erstmal intern wie eine Funktion behandelt - wie z.B. auch das new mit einer ähnlichen Syntax auch erstmal eine (Operator-)Funktion ist - und dann seine übliche Entscheidung trifft, ob er es inlined oder nicht.

    Macht er ja auch mehr oder weniger. Nur muss trotzdem noch das Objekt konstruiert werden das dann geworfen wird. Eine Funktion aufzurufen die eine Exception als Parameter nimmt ist auch nicht viel teurer als die selbe Exception zu werfen. Der Trick ist dass man der throwBlah Funktion möglichst billig zu konstruierende Parameter gibt. Also char const*, int etc.



  • @hustbaer sagte in Projektstruktur: Header Dateien im seperaten include folder?:

    @Finnegan sagte in Projektstruktur: Header Dateien im seperaten include folder?:

    Mich wundert schon etwas, dass der Compiler das throw nicht erstmal intern wie eine Funktion behandelt

    Macht er ja auch mehr oder weniger.

    Oh, dann habe ich wohl beim (nur) Überfliegen des Threads etwas falsch verstanden. Danke nochmal für die Aufklärung.

    Das mit den billig zu konstruierenden Objekten ist mir die Tage allerdings auch wieder aufgefallen, als ein T = std::string völlig verdeckt hat, wie wunderbar eine umgebende Template -Abstraktion tatsächlich wegoptimiert wurde 😉


Anmelden zum Antworten