Schnelles C++
-
dachschaden schrieb:
volkard schrieb:
Und das, wo ein FindNextFile Dir 1000 Takte wegkloppt? Irrsinn. Welchen Speicher zu allokieren sparst Du? Den Stackspeicher der lokalen Variablen? Naja, der ist nicht so irrsinnig teuer. Also eher kostenlos. Oder die ganzen strings für die root auf jeder Ebene? Kannst auch da einen unten anlegen und hochreichen. Bei Bedarf wächst er und schrumpft nicht.
Sowas tue ich nicht auf den Stack. Der Stack ist klein, der Heap ist groß. Wenn ich dann ein neues Verzeichnis öffne, lasse ich mir das auf dem Heap reservieren. Aber dann direkt zu Anfang und dann auch am Stück.
Soll ich etwas immer einstrlenmachen, damit ich weiß, wie wie Speicher ich jetzt haben muss?Vermutlich gehen wir von anderen Betriebsystem-Calls aus. Also ich denke schon dran nullterminirte Strings vom BS zu kriegen, und die beim Abstieg an meinen dranbauen zu müssen. strcat zum Beispiel oder string::+=. Beim Wiederaufstieg kann man in C++ auch wieder kürzen. Ich muss vorher nicht zählen (darf aber, oder darf sinnvoll schätzen), bei Bedarf wächst der string automatisch.
Ich gehe nicht von einer BS-Funktion aus, die mir ein ganzes Verzeichnis liefert, sondern daß ich FindFirst/FindNext zur Verfügung habe.dachschaden schrieb:
Aber die Leute, die dann später deinen Code lesen, denken sich in C "Cool, dass der daran gedacht hat", und in C++ "WTF hat er sich dabei gedacht?",
Jo, ist lästig. Immer, wenns wieder anfängt, daß ich hier als C++-Nube beschimpft werde, weil mein Code zu einfach(lesbar+schnell) ist, poste ich irgendwo ein wenig Template-Gefrickel und hab wieder ein Jahr Ruhe. Ist viel weniger Arbeit, als C++ zu meiden, finde ich.

-
Was ist von dem Tool zu halten, was Herb Sutter an dieser Stelle zeigt: https://www.youtube.com/watch?feature=player_detailpage&v=L7zSU9HI-6I#t=5898 Es nennt sich RightMark Memory Analyzer und kann hier http://cpu.rightmark.org/download/rmma38bin.rar runtergeladen werden. Ich habe gerade kein Windows zum Testen unter den Fingern. Gibt es so etwas auch für OSX oder Linux?
-
volkard schrieb:
Vermutlich gehen wir von anderen Betriebsystem-Calls aus. Also ich denke schon dran nullterminirte Strings vom BS zu kriegen, und die beim Abstieg an meinen dranbauen zu müssen. strcat zum Beispiel oder string::+=. Beim Wiederaufstieg kann man in C++ auch wieder kürzen. Ich muss vorher nicht zählen (darf aber, oder darf sinnvoll schätzen), bei Bedarf wächst der string automatisch.
Hast dann aber wieder einen
realloc. Mindestens.
Du nennst es "schätzen", ich würde es "wetten" nennen. Nee, ich gehe immer vom schlimmsten aus. Oder ich bin eher dazu bereit, Speicher zugunsten von Laufzeit zu opfern. Kommt dann aber auch wieder darauf an, für was für eine Plattform man da programmiert. Jenachdem ist dein Ansatz dann wesentlich intelligenter.volkard schrieb:
Jo, ist lästig. Immer, wenns wieder anfängt, daß ich hier als C++-Nube beschimpft werde, weil mein Code zu einfach(lesbar+schnell) ist, poste ich irgendwo ein wenig Template-Gefrickel und hab wieder ein Jahr Ruhe. Ist viel weniger Arbeit, als C++ zu meiden, finde ich.

Ich rede hier nicht mal vom Forum. Da mache ich mir überhaupt nicht die Mühe, den Leuten was beweisen zu wollen.
Ich meine, wenn der Code reviewt wird. Vielleicht habe ich da auch eine Opfermentalität, weil ich selbst so reviews mache, und ständig Code zu sehen bekomme, der stark entweder nach Jürgen "Ich kann alles" Wolf oder von C++ abgeleitet aussieht. In einer Bude lag der Wolf dann auch tatsächlich rum. m(
Jedenfalls versuche ich, mich immer der Mentalität der Sprache anzupassen. Und wenn ich die gleichen Hacks in C++ wie in C anwende und sonst kaum einen der Vorteile von C++, dann kann ich gleich C verwenden. Das kompiliert auch schneller.
-
dachschaden schrieb:
Hast dann aber wieder einen
realloc. Mindestens.
Du nennst es "schätzen", ich würde es "wetten" nennen. Nee, ich gehe immer vom schlimmsten aus. Oder ich bin eher dazu bereit, Speicher zugunsten von Laufzeit zu opfern. Kommt dann aber auch wieder darauf an, für was für eine Plattform man da programmiert. Jenachdem ist dein Ansatz dann wesentlich intelligenter.Wenn ich zufällige Längen zwischn 0 und 999 hätte und 100 "schätzen" würde und 100000 Files hätte, käme ich auf durchschnittlich 7 reallocs. Wobei ich vom dümmlichen
if(r>m){ m=r; realoc(m); }ausginge.
Bezahlbar, finde ich. Hab echt Angst, ich könnte statt der Mikrosekunde fürs reallocen vielleicht zwei Millionen Mikrosekunden ausgeben, um vorher durchzulaufen und die Maxgröße zu finden. Oder ich "wette" einfach, daß 2000 reichen werden und wenn nicht, kracht's eben. Wie stellst Du vorher die maximale Größe fest? Oder haste eine schlichte Garantie wie <=32786 und nimmst einfach die?
Mit m=r+r; bin auch auf 2.4 reallocs.
-
volkard schrieb:
Wie stellst Du vorher die maximale Größe fest? Oder haste eine schlichte Garantie wie <=32786 und nimmst einfach die?
Ich habe eine Funktion, die mir abhängig vom System die maximale Pfadgröße zurückgibt. Mit der arbeite ich. Wenn ich die nicht bekomme, schlägt der Call fehl. Also: Ja, ich suche mir so eine Garantie. Ja, dabei wird Speicher verwendet. Das ist mir klar.
-
dachschaden schrieb:
Ja, dabei wird Speicher verwendet. Das ist mir klar.
Speicher sparen, den kein anderer braucht, ist blöd. Embedded system nehme ich an und singlethreaded. Dann kannste die Garantie einfach benutzen und weiterreichen. Das Wachsen des Speichers, was ich auf PCs bevorzugen würde, könnte dümmstenfalls doppelt so viel Speicher fressen wie das feste Vorallokieren.
Seit ein paar Monaten darf man in C++ keine rohen Zeiger mehr nehmen. Würde ich aber da nehmen, ich Sau.
-
volkard schrieb:
Seit ein paar Monaten darf man in C++ keine rohen Zeiger mehr nehmen.
Sagt wer?
-
EOP schrieb:
volkard schrieb:
Seit ein paar Monaten darf man in C++ keine rohen Zeiger mehr nehmen.
Sagt wer?
Ein Global Moderator.

-
Ich hab kein C++11, also darf ich.
-
Warum hast du kein C++11?
-
Weil ich nur VisulStudio 2005 hab.
-
Warum lädst du dir keine neuere Version runter, oder nimmst MinGW oder Clang? Ich meine, C++11 ist der aktuelle Standard und der nächste steht schon vor der Tür. Ich kenne der alten Standard nicht so, da ich gleich mit C++11 angefangen habe, aber es hat sich ja schon wohl viel geändert.
-
Citizen42 schrieb:
Ich meine, C++11 ist der aktuelle Standard und der nächste steht schon vor der Tür..
Ich finde das toll, dass das so an alle vorbeigeht: C++14 ist schon seit 4 Monaten draußen!
-
Ups echt? Ich dachte irgend ein Draft wäre fertig und muss noch durchgewunken werden.
-
Jup, echt: http://en.wikipedia.org/wiki/C%2B%2B14
-
Jut, dann ab heute -std=c++14 denn das ist ja dann das neue Standard-C++. Sind ja zum Glück nicht so viele Änderungen wie bei C++11.
-
Nathan schrieb:
Jup, echt: http://en.wikipedia.org/wiki/C%2B%2B14
Ich denke der isocpp-Artikel passt hier besser.
Sind ja zum Glück nicht so viele Änderungen wie bei C++11.
Zum Glück?

-
Glück für das wenige Dazulernen von 11 auf 14. Die Änderungen vom alten 98 zu 11 waren ja wohl doch schon viel, aber auch gut, so wie ich das gelesen habe. Ich kenne ja C++98 gar nicht.
Nun haben wir bald 2015 und dann zwei Jahre Zeit bist es wieder was Neues gibt. Bis auf Mircosoft sind ja wohl auch die Features immer recht schnell in den Compilern verfügbar.
-
volkard schrieb:
Speicher sparen, den kein anderer braucht, ist blöd. Embedded system nehme ich an und singlethreaded. Dann kannste die Garantie einfach benutzen und weiterreichen. Das Wachsen des Speichers, was ich auf PCs bevorzugen würde, könnte dümmstenfalls doppelt so viel Speicher fressen wie das feste Vorallokieren.
Naja, ich hab mir schon was dabei überlegt.
Der Programmierer soll zum Beispiel bestimmen können, ob die Funktion jetzt einen Speicher, den er angegeben hat, verwenden soll - in einer Streamer-Struktur, die ich ursprünglich mal für einen IRC-Bot geschrieben habe, aber die hat sich als so vielseitig herausgestellt, dass ich die für das Verzeichnisse-durchlaufen einfach "missbraucht" habe - oder ob die Funktion sich darum kümmert. Der Vorteil ist: die Funktion reserviert den Speicher neu, behält aber originale Daten bei und schaut nur zu, dass am Ende die Daten der rekursiven Funktion geschrieben werden. Der Speicher wird dann nicht freigegeben, weil darum sich der Programmierer kümmern soll, und kann den erweiterten Speicher dann auch für andere Sachen nutzen.
Und wenn er keinen Bock hat, sich um die Speicherverwaltung zu kümmern, gibt er beim Initialcall einfach 0 an, und die Routine kümmert sich selbst darum. Dann gibt die aber den Speicher am Ende wieder frei - der Programmierer wollte ja nicht.Es ist erstaunlich, wie oft man einfach nur einen großen Speicherbereich braucht, und ein bisschen Intelligenz innerhalb seiner Routinen, um sich einen Haufen
malloc/realloc/free-Calls zu spraren. Den gleichen Speicherbereich, den du zum Buffern einer HTTP-Antwort verwendest, kannst du später dazu verwenden, zu ge-entzippen. Und dann später, um wieder in einem Verzeichnis suchen zu lassen und eine Anfrage zu generieren. Wenn man dann noch ein paar PP-Makros definiert, die quasi die Schnittstelle dafür bieten, muss du nur nur 5 weitere Zeilen in deine Funktion unterbringen, und kannst den Durchsatz um einiges erhöhen (waren damals von 50.xxx Cycles auf 10.xxx Cycles runter). Einen HTTP-Parser habe ich so (und ein paar zusätzlichen Tricks) auch von 60.xxx Cycles auf <2.000 Cycles bekommen.
-
Hört sich alles nicht praxisrelevant an. Ein HTTP Parser wird im HTTP Server nicht das Bottleneck sein. Schön, wenn es dir Spass macht, sowas zu optimieren, aber wirklich bringen tut es wohl nichts und führt sehr wahrscheinlich einfach nur zu schlechter wartbarem Code.