![]() |
FastMM grotten langsam ?!
Jetzt hab ich gehört, dass FastMM doch sooo viel besser sein soll, als der Borland Speichermanager.
Habe D2005. Jetzt habe ich also probiert: ![]() und auch gleich mal getestet, und oh Schreck, mit FastMM braucht der Vorgang doppelt so lange. Mit Original Borland Speichermanager etwa 3000 ms und mit FastMM rund 6000 ms Liegt das an meinen fehlenden Kenntnissen über FastMM und dessen Optionen oder ist das einfach nur verarsche ? Wie sieht das bei Euch aus ?
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
const ende = 50000000; type tar = array of double; var i, a : longint; p: tar; c, start, stop, merke : tlargeinteger; begin application.processmessages; queryperformancefrequency(c); queryperformancecounter(start); // Speicherreservierung + Schreiben i:=0; while i<=ende do begin if i mod 10 =0 then setlength(p,i+10); //setlength(p,i+1); p[i] := 5000; inc(i); end;// von vor queryperformancecounter(stop); merke:=stop-start; // Durchlauf nur Schreiben queryperformancecounter(start); i:=1; while i<ende do begin p[i] :=6000.50; inc(i); end; queryperformancecounter(stop); Showmessage('Mit Speicherreservierung: ' + format('%.2f ms', [merke/c * 1000]) +#13#10 + 'Durchlauf Schreiben : ' + format('%.2f ms', [(stop-start)/c * 1000])); end; // dynamisches Array |
Re: FastMM grotten langsam ?!
Liste der Anhänge anzeigen (Anzahl: 1)
Also extrem viel schneller ist es auch nicht ... aber meißtens sollte es schneller sein, aber eben nicht immer ;)
Du könntest es ja mal unter den selben Bedingungen hiermit mit meinem MemoryManager versuchen. Der is 'ne Abart des FastMM und arbeitet ein klein wenig anders ^^ Ein-/Verstellen brauchst du auch nichts, mußt halt nur die FastXMM.pas als erstes in die Uses-Klausel deiner DPR einfügen. PS: als Extrem kannst du es ja mal in Einerschritten versuchen, also das SetLength bei jedem Durchgang aufrufen.
Delphi-Quellcode:
setlength(p,i);
Ach ja, das "Durchlauf nur Schreiben" kannst du dir sparen, denn die MemoryManager verwalten ja nur den Speicher, also das reservieren, Größe ändern und freigeben. Am Schreib-/Lesezugriff wird also nichts verändert. |
Re: FastMM grotten langsam ?!
Problem könnte ja sein, dass FastMM zwar schneller ist, dafür aber mehr Arbeitsspeicher zur Verwaltung braucht. Eventuell verursacht dieser Mehrverbrauch ein häufiges Auslagern des Speichers wodurch es natürlich langsamer wird.
|
Re: FastMM grotten langsam ?!
So, ich bins nochmal ^^
Also, da ich mir ja mal ein/zwei MemoryManager angesehn und mir sozusagen auch noch 'nen eigenen Angeschaft habe, kann ich dir schonmal eines sagen ... und zwar ist der FastMM was das Reservieren und Freigeben von Speicher angeht nicht schneller als der normale MemoryManager von Delphi. Und das Ändern der Speichergröße (Realloc) ist nur in einem begrenzten Bereich etwas schneller. Selbst Meiner ist da keine Ausnahme. Und zwar ist es so, das bei FastMM und FastXMM in Wirklichkeit nicht immer die Speicherzuweisung geändert wird - der normale MM führt ein Realloc immer durch. Es ist so, daß solange sich die Größenänderung innerhalb eines gewissen Bereichs (von der bereits reservierten Speichermenge abhängig) bewegt der Speicher nicht neu zugewiesen wird ... also wenn keine Änderung geschieht, dann wird natürlich Zeit eingespart ;) Zusätztlich hat mein MM eine etwas Einteilung der "kleineren" Speicherblöcke (bis 2 KB), was insgesammt einer etwas schneller Speicherbehandling resultieren sollte. Und wie gesagt, der FastMM und mein FastXMM sind hauptsächlich beim Realloc etwas besser. Es gibt zwar abundzu mal 'ne Geschwindigkeitssteigerung beim Alloc/Get und Free, aber dieser kann nicht wirklich in die Bewertung der MemoryManager einbezogen werden, da dieser eher unregelmäßig auftritt und aus der Struktur der internen Speicherwerwaltung resultiert. Oberhalb der 2 KB sind der FastMM und mein FastXMM etwa gleich ausgelegt und unterscheiden sich dirnt nicht all zu sehr, was das Tempo angeht. Einen weiter Vorteil gegenüber Delphi MM ist bei den Fast(X)MM, daß man halt einen besseren Einblick in die Arbeit des MMs hat - z.B. über die MemoryMap. Allerdings gibt es bei meinem FastXMM noch etwas zu beachten. (dieses Gild allerdings nicht für die hier hochgeladene "Single Unit"-Version) Und zwar kann man (zukünftig) meinen MM in einem speziellen Modus betreiben, welcher es erlaubt die Speicheroptimierung für jede Speicheranfrage(Get/Realloc/Free) einzeln einzustellen. Im Moment ist diese Optimierungsmöglichkeit allerdings nur bei der Stringbehandlung in meinem UCC enthalten, dieses wird aber demächst dort entfernt und direkt in den MM eingefügt. Und zwar kann man dem MM dann mitteilen, wie diser auf eine Größenänderung reagieren soll. Es ist dann also möglich die Speicherverwaltung speziell an die Bedürfnisse des Programms anzupassen, so daß man theoretisch (bei häufigen Änderungswünschen per Realloc) eine Geschwindigkeiststeigerung innerhalb des reallocs von bis zu 99% erreichen kann. |
Re: FastMM grotten langsam ?!
Zitat:
Und aktuell ist es so, daß der Speichermehrverbrauch beim bis zu 3-Fachen des tatsächlich benötigten liegen kann, allerdings liegt im großen Durchschnitt der reelle Mehrverbrauch bei etwa 5-10%, was bei normalen Anwendungen und ausreichend RAM kaum zu einer verstärkten Auslagerung des Speichers führen sollte. Wenn aber dennoch Speicherbereiche ausgelagert sind, dann wird sich die Geschwindigkeitssteigung durch Fast(X)MM eventuell sogar noch verstärken (habs noch nich getestet), da ja die Veränderungen im Speicher (welcher bei Windows reserviert wurde) stark minimieren. [add]Ach ja, wie breits gesagt wird sich eine Geschwindigkeitssteigerung nur vorwiegend bei kleinen Änderungen zeigen. Du änders den Speicher aber um jeweils um 10 Schritte, also 80 Byte (10 mal 8 Byte pro Double), was bedeutet, das sich in den ersten Durchläufen (wenn das Array noch kurz ist), sich kaum/keine Verbesserung einstellen wird und slbst später wird sich die Verbesserung eigentlich nicht so sehr zeigen, denn im Grunde genommen hast du ja selber schon eine "kleine" Speicheroptimierung eingebaut,
Delphi-Quellcode:
wodurch du aber wiederum einige Vorteile von FastMM ausgehebelt hast :stupid:
if i mod 10 =0 then setlength(p,i+10);
|
Re: FastMM grotten langsam ?!
Hallo Himitsu,
es ist natürlich so, dass ich nur die Hälfte von dem verstehe, was Du schreibst, da ich bei Speichermanagern nicht wirklich so der Fachmann bin. FastMM ist bei Verwendung von TList im obigen Beispiel etwa 10 Prozent schneller als Delphi. Der Vorteil verschwindet aber, wenn FastMM bei anderen Anwendungsfällen gleich um das Doppelte einen Ausreißer ins Negative hat. Zitat:
Eine Sache hab ich bei den Speichermanagern noch nicht verstanden, wenn ich ein Dynamisches Array habe, ist dieser Speicher auch wirklich dann zusammenhängend ? Was passiert in dem Fall, wenn das Array eine Größe von 1000 hat und dann irgendwo anders Speicher benötigt wird ,und wenn dann danach das Array auf 1001 vergrößert wird. Wird dann alles umkopiert ? Könnte es im Extremfall passieren, dass die ersten 1000 Elemente an eine neue Stelle kopiert werden ? Ich arbeite im Moment noch mit Listen, würde aber gern auf Arrays umsteigen, meine tests haben aber ergeben, dass bei einer großen Anzahl von Elementen das irgendwie langsamer ist. Leider stören mich der Platz der vielen Zeiger ... naaja .. |
Re: FastMM grotten langsam ?!
Zitat:
Obwohl es natürlich möglich wäre, daß eine Verlangsamung auf Grund der anderen Art der Speicherverwaltung auftritt. (es wird halt etwas mehr gerechnet, um so optimaler zu arbeiten) Obwohl ich nicht hoffe, daß es auch bei meinem MM so ist ._. (hast du es auch mal damit versucht) Und wenn, würde ich mir dieses Verhalten, bei Zeiten, nochmals genauer ansehn und prüfen was sich da machen ließe ^^ Zitat:
Dazu gibt es dann folgende Konstanten:
Delphi-Quellcode:
Mit slReal (ist natürlich der Standard, wenn man nichts angibt) bleibt alles so wie es bisher ist.
Type SLType = Type LongInt; // The OLE-WideString supported only slReal and slUnique is always set.
Const slReal = ...; slUpDown_1 = ...; slOnlyUp_1 = ...; // 0,1 KB / 128 B slUpDown = ...; slOnlyUp = ...; // 1 KB / 1024 B slUpDown10 = ...; slOnlyUp10 = ...; // 10 KB / 16384 B slUpDown100 = ...; slOnlyUp100 = ...; // 100 KB / 131072 B slUpDown1M = ...; slOnlyUp1M = ...; // 1 MB / 1048576 B slSetNew = ...; slZeroNew = slSetNew or Ord(#0); slSpaceNew = slSetNew or Ord(' '); slUnique = SLType($00200000); //slThreadSave = SLType($00800000); Über slUpDown... wird der Speicher immer nur in Schritten eines bestimmten Wertes reserviert und mit den slOnlyUp... kann zusätzlich noch verhindert werden, daß Speicher freigegeben/verkleinert wird. Wenn man z.B. einen String hat, dessen Größe sich sehr oft (vorzugsweise in kurzer Zeit) über einen weiten Bereich verändert, dann kann man z.B. über die Angabe von slOnlyUp1M dafür sorgen, daß tatsächlich ständig Speicher freigegeben und reserviert wird. (einzig bei S := ''; oder einem SetLength auf 0 wird immer der Speicher, unabhängig vom Parameter, freigegeben, dieses hängt aber mit der Definition der Strings zusammen) Es ist ja so, daß die Fast(X)MM vorwiegend ihre Vorteile nur bei kleiner Veränderungen können und bei "extrem" Großen nicht verbessern ausspielen. Es haben alle alle Funktionen/Prozeduren zur Stringbehandlung (wenn es erforderlich ist) einen weiteren Parameter. (was ich ja auf weitere Bereich ausweiten möchte) z.B.
Delphi-Quellcode:
Abgesehn davon hab ich mir auch noch weitere Optimierungen einfallen lassen, was das Tempo steigern kann :mrgreen:
Procedure _SetLength(Var S: AnsiString; Len: LongInt; Typ: SLType = slReal);
z.B.
Delphi-Quellcode:
Zweiteres wird also schneller sein, da dort nach der Funktion nich erst der als String freigegeben und durch den Neuen ersetzt werden muß, da ja der String direkt verändert wird.
Function _StringReplace(Const S, OldPattern, NewPattern: AnsiString; Flags: TReplaceFlagsEx; Typ: SLType = slReal): AnsiString;
Procedure StringReplaceV(Var S: AnsiString; Const OldPattern, NewPattern: AnsiString; Flags: TReplaceFlagsEx; Typ: SLType = slReal);
Delphi-Quellcode:
S := _StringReplace(S, 'alt', 'neu', [rfeReplaceAll]);
StringReplaceV(S, 'alt', 'neu', [rfeReplaceAll]); Zitat:
Es muß also Aufgrund der zsammenhängenden Datenstruktur immer ein zusammenhängender Speicherbereich reserviert werden. Und zumindestens Fast(X)MM versuchen zuerst den nachfolgenden Speicher zu reservieren und wenn dieser schon belegt ist, dann muß halt der gesamte Speicher (z.B. die Arraydaten) verschoben/kopiert werden. PS: die Listen verbrauchen ja nicht nur durch die vielen Zeiger mehr Platz. Es muß ja auch (unter Umständen, weiß ja nicht wie alle Listen arbeiten) für die einzelnen Elemente ein eigener Speicherbereich reserviert werden und pro Speicherbereich werden ja auch noch bestimmte Verwaltungsdaten (im MemoryManager) benötigt. :) |
Re: FastMM grotten langsam ?!
Huhu...
FastMM scheint in den meisten Fällen tatsächlich schneller zu sein als der Borland MM, jedoch habe ich bessere Erfahrungen mit RecyclerMM, welcher vor allem für Multi-Threaded Anwendungen optimiert ist, machen können... Kann es jedem nur empfehlen: ![]() |
Re: FastMM grotten langsam ?!
Hab mal 'nen kurzen Blick in den RecyclerMM geworfen.
Zitat:
Außerdem scheint der wohl nicht ganz platzsparend zu sein ... mir sind da schon auf den ersten Blick einige Dinge aufgefallen, welche wohl bei normalem Betrieb (vorallem ohne Nutzung des UsageSnapShots/UsageTrackers) einiges an Speicher und Rechenzeit verschwenden. Die Speicherverwaltung der kleineren SpeicherBlöcke halte ich beim FastMM für optimaler - von der Speicherausnutzung her. Und wenn der läuft will ich lieber nichts all zu Schlechtes über den RecyclerMM sagen - irgendwo hat sicher jeder MM seine Vor- und Nachteile. Aufgrund von Hagens Aussage revidiert. :mrgreen: Aber die Einbeziehung der Rechenzeit in den UsageBenchmark find ich nicht schlecht ... werd' mal sehn, ob ich das bei mir auch mit mache - die Aufrufe werden ja bei mir eh schon mitgezählt, wenn auch in einer etwas ausführlicheren Form (nicht in der SingleUnit-Version) |
Re: FastMM grotten langsam ?!
Kurz: RecyclerMM ist Schrott ! lass die Finger davon.
Gerade das angepriesene Multithreading ist tödlich. Denn RecyclerMM kann niemals korrekt erkennen wann ein Thread terminiert wird und dies führt dazu das die zu diesem Thread allozierten Speicherbereich nicht mehr fregegeben werden können. Besonders in ActiveX, COM etc. pp. Anwendung sind solche extern allozierten Threads vorhanden. Bedenke ja das der eigene Prozess ja nur ein COM Service ist der die COM Anforderungen externer Prozesse erfüllen muß. Wird nun in diesem COM Objekt zb. mit LongStrings gearbeitet so alloziert RecyclerMM Speicherresourcen die er nicht mehr freigeben kann. Denn RecyclerMM kann keine Kontrolle darüber haben wann nun der externe Thread tatsächlich beendet wird. Gruß Hagen |
Re: FastMM grotten langsam ?!
Hm, kaum zu glauben...
@Hagen: da musst du mir mal erklären warum RecyclerMM sowas nicht können sollte, die anderen jedoch schon ^^... Naja und wie gesagt, bisher hat sich RecyclerMM bewährt, performance-technisch der schnellere zu sein! |
Re: FastMM grotten langsam ?!
Moin zusammen,
Habe die Probeweise gestern mal in ein größeres Projekt eingebunden. Im Projekt werden komplexe Formulare dynamisch erzeugt. Mit RecycleMM lief der Formularwechsel (dynamischer Abbau und Aufbau des nächsten Forms) sichtbar (!) schneller. Leider gab es auch Fehlermeldungen bei Programmende, sodass ich davon ausgehe, dass es da doch noch Pointerprobleme gibt. Grüße // Martin |
Re: FastMM grotten langsam ?!
Zitat:
Nö, die Anderen können es genauso wenig wie RecyclerMM, und ohne tiefe OS Tricks wirds auch keinen MM geben können der es kann, so einfach ist die Sache. Ich versuch das Problam nochmal zu verdeutlichen: Du schreibst eine DLL die RecyclerMM benutzt. Diese DLL exportiert Funktion XYZ und in dieser führst du umfangreiche Berchnungen druch die sehr viele Speicherblöcke alloziert und dealloziert. Die DLL bindest du in einer neuen Anwendung ein und rufst nun die Funktion XYZ innerhalb eines Threads auf. Was passiert nun in RecyclerMM == R und in einem normalen MM = N ? 1.) Thread wird erzeugt 2.) Funktion XYZ wird aufgerufen 3.) Speicher wird alloziert - R alloziert viel mehr Speicher als nötig und erzeugt beim ersten Aufruf für diesen Thread einen komplett eigenständigen Memory Manager - N hat schon einen MM für alle Threads und alloziert Speicher geschützt per RTL Critical Sections für alle Threda vom selben Pool 4.) Speicher wird freigeben und wieder neu alloziert - R gibt niemals den freien Speicher zurück ans das OS, im WorstCase belegt also R immer mehr virtuellen aber real ungenutzen Speicher - N ging gegebenfalls beim überschreiten gewisser Größen den Speicher mit VirtualFree() wieder an das OS zurück 5.) alle Speicherbereich in Funktion XYZ werden freigegeben da XYZ terminieren möchte - R legt diese freien Speicherbereich in seinem Threadeigenen Pool ab, gibt sie aber nicht an das OS zurück - N legt diese Speicherbereich in seinen gemeinsammen Pool ab, andere Threads könnensie wiederbenutzen oder beim überschreiten eines Thresholds gibt N sie mit VirtualFree() sofort an das OS zurück 6.) Funktion XYZ kehrt zurück, Prozess terminiert Thread - R hat nun einen rießigen Block von Speicherleiche übrig gelassen da R nicht auf die Terminierung des Thread reagieren kann - N hat ebenfalls ungenutzen virtuellen Speicherliegen, der aber durch andere Thread erneut benutzt werden kann und beim Beenden des Prozesses == entladen der DLL auch sauber per Vitual Free freigegeben werden kann. Wiederholt man nun sehr schnell den Prozess des Threads erzeugen, Funktion XYZ ausführen und Thread zerstören so entstehen immer neuere Speicherleichen in R. Man könnte nun argumentieren das die DLL in der R, N enthalten ist per Code Hooks auf die Beendigung eines Thread reagieren könnte. Ja das wäre möglich aber ist nur scheinbar eine Lösung. Denn bei eigenen Programmen geht dies noch zu machen aber nicht mehr bei zb. COM, ActiveX Servern. Dies können nicht ermitteln ob und wann ein Thread terminiert wird, dies geht einfach nicht da es auf API Ebene des OS keinen Signaling Mechanismus dafür gibt. Ich möchte hier auch nicht weiter darüber diskutieren. Meine Emofehlung lautet RecyclerMM nicht zu benutzen. Der Author ist sich dieses Problemes sehr wohl bewusst da ich mit ihm darüber korrespondiert habe. Desweiteren wurde deises Problem ebenfalls in den Borland NewsGroup diskutiert. Zweitens ist dies schon wieder ein par Jahre her ! und es erfolgte keine Reaktion darauf indem man zumindestens im RecyclerMM darauf hinwies. Ich bin aber nicht für die korekte Funktion andere Sourcen verantwortlich. Ergo: er ihn nutzen möhcte soll es tuen, sich aber dann nicht wundern wenn er Fehler bekommt die er nicht im mindestens einzuodrnen weis. Denn Fehler in einem Speichermanager führen zu fehlern die man so nicht debuggen geschweige denn einzuordnen weis. Man sucht dann wochenlang in seinen eigenen Sourcen ohne Erfolg. Gruß Hagen [edit] PS: Ich habe keinen eigenen MM programmiert und verkaufe auch kein irgendwie geartetes Produkt in dieser Richtung. Soll heissen ich habe nicht das geringste Interesse RecyclerMM zu diskretitieren noch die Arbeit des Authors schlecht zu machen. Das einzisgte was ich mache ist euch zu warnen das mit RecyclerMM designtechnisch begründete Fehler auftreten müssen ! [/edit] |
Re: FastMM grotten langsam ?!
In der damaligen Diskussion in den NewsGroups stellten sich zwei mögliche Lösungen:
1.) RecyclerMM exportiert eine Funktion zb. DoneMM() die der Programmierung am Ende eines Threads aufzurufen hat. 2.) RecyclerMM exportiert eine Funjtion zb. CleanupMM() die der Programmierer periodisch aufzurufen hat oder aber innerhalb vom RecyclerMM() periodsich per Timer aufgerufen wird. Nun analysieren wir das mal: 1.) falls wir einen COM/ActiveX Service oder eine DLL programmieren dann kann diese durch externe Prozesse aufgerufen werden die NICHT durch uns selber programiert wurden, sondern zb. in VB, C oder sonstwas. Ergo: DoneMM() kann und wird garnicht aufgerufen. Diese Lösung fehlt also ins Wasser. 2.) falls wir einen COM/ActiveX Service oder eine DLL programmieren dann kann diese durch externe Prozesse aufgerufen werden die NICHT durch uns selber programmiert wurden, sondern zb. in VB, C oder sonstwas ;) Ergo: CleanupMM() wird nicht aufgerufen. Selbst aber ein Timer basiertes Aufrufen von CleanupMM() muß scheitern da RecyclerMM innerhlab dieser Funktion garnicht unterscheiden kann ob ein Thread noch läuft, nur gestoppt wurde oder aber tatsächlich terminiert wurde. Man kann zwar per Trial&Error versuchen herauszubekommen ob ein Thread-Handle oder Thread-ID ungültig ist aber dies würde nur funktionieren wenn das OS dokumentiert sicherstellen würde das ein einmal benutzte Thread ID oder Thread Handle nicht mehr wiederbenutzt wird. Nun, Windows garantiert eine solche Vorgehensweise aber nicht !! Ergo: es entstehen viel zu viele Unwägbarkeiten, bis hin zu "fehlerhaften" Benutzung des MMs durch uns selber. Ein guter MM muß aber in solchen Sachen wirklich Bullet Proof konstruiert sein. D.h. das Konzept muß so konstruiert werden das es keine Möglichkeit für eine "Fehlbenutzung" durch andere Programmierer kommen kann. Übrigens, ich rede hier nicht von theoretischen Dingen, sondern aus selber gemachten Erfahrungen. Eine TCP/IP Service der per COM Schnittstelle aufgerufen werden konnte wurde mit RecyclerMM ausgestattet. Eben weil sehr viele, große und häugfige Speicheranforderungen stattfanden und ich mir vom RecyclerMM einen Performanceboost erhoffte. Dies war auch in den Tests wunderbar der Fall, mit einem Schönheitsfehler: Die Tests wurden auf Grund der äußeren Umstände immer nur so durchgeführt das nur eine TCP/IP Clientverbindung stattfinden konnte. Dieser Test simulierte also NUR die technische Funktionaliät aber NICHT die praxisnahe reale Auslastung mit 1000'enden Clients innerhlab von Sekunden. Als es dann soweit war, Abnahme war gemacht, Kunde hattte bezahlt und ging in den Echtbetrieb kackte der Server ständig schon teilweise nach Minuten komplett ab. So, die Suche konzentierte sich naturgemäß erstmal nur auf den Server, dessen TCP/IP Konfigurationen, auf die Router, neueste Patches etc. pp. Dies verschlang Wochen da es sehr schwer nachvollziehbar war und die Clientlast sich sehr unregelmäßig verteilte. Erst nachdem ich eine zusätzliche Anwendung programmierte die 1000'ende Clients simulierte konnten wir das Problem eingrenzen. Natürlich kam ich nicht sofort auf die Idee den fucking RecyclerMM zu deaktievieren sondern ging stur von einem Fehler in meinen Sourcen und später in Indy's Sourcen aus. Naja, nach 6 Wochen schmiß ich RecyclerMM auf Grund eines systematischen Vorgehens, also Routine, verdchatsweise raus. Danach ging alles wie gehabt. Also nochmal 1 Woche programmiert um alle Sourcen wieder auf ihren Auslieferungszustand zu versetzenund schlußendlich habe ich länger daran gesessen diesen Fehler zu entfernen als das eigentlichen Projekt zu seiner Fertigstellung an Zeit erfodert hatte !! Die Entwicklungszeit verlängerte sich also von 5 Wochen auf +7 Wochen. Meine finanzielle Kalkulation war fürn Popo. Gruß Hagen |
Re: FastMM grotten langsam ?!
So nun konzepionell:
Es gibt mehrere Wege einen MM zu "optimieren". 1.) man alloziert ständig mehr Speicher auf Verdacht um im eventuell späteren Falle einer Reallokation sofort diese Anforderung erfüllen zu können. 2.) man ändert die Strategie der Verwaltung der freien Speicherblöcke um später dann gezileter und schneller eine Speicheranforderung erfüllen zu können. 3.) man optimiert den Sourcecode indem man schneller Assemblerfunktionen benutzt. Nur Punkt 2.) ist eine echte Altrnative und in FastMM4 auch das primäre Optimierungsziel gewesen. Nur 2.) optimiert den Algorithmus ansich und bietet somit das meiste Potential. Punkt 3.) kann nur ein Fein-Tuning darstellen. Punkt 1.) ist eher gefährlich als nützlich. Aber gerade Punkt 1.) wird bei den meisten sogannenten "besseren" MM's benutzt. Was ist daran aber so gefährlich ? Ok, RecyclerMM: dieser übertreibst mit Punkt 1.) und im WorstCase betrachtet bedeutet dies: Allozieren für jede Speicheranforderung immer wieder komplett neuen Speicher. Bei der Deallokation dieser Speicher spare die komplette Zeit ein indem du diesen Speicher garnicht mehr freigibst !!! Man kann sich nun leicht ausrechnen was passieren muß. Aber exakt so geht RecyclerMM vor. Ok, er optimiert indem er übergroße Speicherblöcke alloziert, quasi die Speicheranforderung höher auslegt als benötigt. Die Wahrscheinlichkeit diese preallozierten Überhangs im vergleich zu dann tatsächlichen Auslastung wird immer schlechter je größer dieser Überhang ist. Jetzt stellen wir uns mal vor ALLE Programme würden solche MMs benutzen !? Dann würden nur 3 Prozesse immer mehr an Speicher verbrauchen diesen aber eben nicht effektiv nutzen. Ergo: ein guter Speichermanager wird nicht nur schnell Speicher allozieren können, nein, viel wichtiger ist es das er auch diesen Speicher immer wieder auch an das OS freigibt wenn er nicht mehr benötigt wird. Denn nur so eine Strategie kann dazu führen das nicht die eigenen Anwendung nur deshalb schneller wird weil sie den anderen Anwendungen den Speicher wegnimmt/blockiert. Schaut man sich FastMM4 genauer an so erkennt man wodurch er ca. 2 mal schneller als der Borland MM wird. 1.) viele Sourcen nutzen Assembler bzw. sind besser durch den Compiler optimierbar. Ein Umschreiben des Borland MMs nach dieser Taktik wird den Borland MM auch ca. 50-60% beschleunigen können. 2.) der Rest des Performancegewinnes liegt darin begründet das die Granulatät des FastMM4 höher ist als die ses Borland MMs. D.h. FastMM4 kann viel exakter entscheiden und geordeneter auf spezifische Speicheranforderungen reagieren als der BorlandMM. FastMM4 benutzt quasi ein leicht optimaleren Algorithmus. Gruß Hagen |
Re: FastMM grotten langsam ?!
Was ist die effizientest Alternative aus unserer Sicht ?
1.) Optimierung an der Stelle wo der meiste Gewinn zu erwarten ist, in den eigenen Algorithmen. 2.) Vermeidung quasi Vorbeugung. D.h. man versucht die Aufrufe an den MM von Anfang an zu reduzieren. Gerade im LongString-Bereich kann man da einiges verbesseren. Statt also LongString weiderholt additiv zusammenzubauen -> R := R + S; wird ein langer möglichst in seiner LÄnge exakt vorausberechneter String prealloziert und dann durch einfach Kopierungen zusammengebaut. In den meisten Fälle optimiert man damit nicht nur EIN Problem sondern gleich MEHERE auf einmal. Dementsprechen sieht der Performancgewinn im Nachinein auch aus. Nicht nur 50% schneller sondern bis zu 500-1000% schneller kann so eine Funktion werden. Diese Ratio ist einfach nicht mit einem besseren MM erraichbar, das geht einfach nicht. Eine weitere Optimierung ist das informelle Wissen. D.h. man weis das spezielle gleichgroße Datenstrukturen im Programm benutzt werden und optimiert indem man deren dynamische Speicheranforderungen in statisch und preallozierte und postdeallozierte Speicheraufrufe umwandelt. Man baut quasi einen Cache nur für diese speziellen Datenstrukturen. Auch dies kann die Performance weit mehr als nur 30-50% erhöhen, öfters wird man weit mehr als 500%-1000% Steigerungen erreichen können ! Woran liegt das ? Einerseits darin das man wesentlich schneller solche preallozioerten gelichgroßen Blöcke allozieren und freigeben kann. Aber auch andererseits weil man so definitiv 0% Fragmentierungen der Speicherblöcke erreichen kann. Und diese Fragmentierung des Speichers ist das as jeden MM zu schaffen machen wird. Gruß Hagen |
Re: FastMM grotten langsam ?!
Zu Hagen's Beitrag #13:
Bei RecyclerMM kann ich bestätigen, daß dieser mit verschiedenen Modulen (DLLs und Co.) nicht klar kommt. Für FastMM trift dieser aber auch nur bedingt zu, denn dort muß die entsprechende Funktionalität erst aktiviert werden und selbt dann steht dieses nicht volltändig zur Verfügung, denn die Memory-Funktionen sind nicht vollständig für SharedMemory ausgelegt. GetMem, FreeMem und ReallocMem können zwar vollständig für alle Threads/Module freigegeben werden, aber bei den Zusatzfunktionen wie z.B. für den UsageTracker sieht es anders aus, denn diese greifen nur auf den in ihrem Bereich liegenden MM zu, selbst wenn es nicht der global initialisierte MM ist, was zu netten Problemen führen kann/wird. ;) Mein MM ist da schon konsequenter und gibt alle nötigen Funktionen global frei. Also jeder FastXMM schaut immer erstmal nach, ob es im Programm schon irgendwo einen weiteren FastXMM gibt und übergibt dann die kontrolle an diesen. Ich muß allerdings zugeben, daß ich aber auch noch nicht zu 100% konsequent bin, denn es gibt "noch" ein kleines Problem, was aber extrem selten auftritt. Also wenn z.B. in mehreren dynamisch geladenen Moduelen (DLLs...) der FastXMM enthalten ist und zusätzlich aber keiner in einem statisch geladenen Modul, oder im Hauptmodul (EXE), dann wird es zu Problemen kommen, sobald nicht das zuerst geladene Modul auch als letztes freigegeben wird. (bei den anderen ist die Reihenfolge egal) Allerdings haben dieses Problem auch alle anderen Memory Manager, welche ich bisher gesehn hab und dazu kommt noch, daß dieses Problemchen in der nächsten Generation meinen FastXMM behoben wird. :mrgreen: Solche CleanUp-Funktionen (Beitrag #14) wären aber auch nicht nötig, wenn die Programmierer, so wie es auch eigentlich der Fall sein sollte, beim Beenden der verschiedenen Teile darauf achten würden, daß auch wirklich alles Nötige freigegeben wird, daher ist in Fast(X)MM derartiges erst garnicht implementiert. ^^ Es wird "nur" beim Programmende (sobald FastXMM freigegeben wird) geprüft, ob noch irgendwas allociert ist, welches ja eigentlich nicht de Fall sein dürfte, wenn alles ordnungsgemäß freigegeben wurde. Und was nochmal den Speichermehrverbrauch bei Fast(X)MM angeht, so ist dieser beim Aufruf von GetMem/FreeMem nicht wesentlich anders, als bei BorlandMM. Nur beim ReallocMem wird entweder nicht sofort, oder im vollständigen Maße verkleinert, ebenso wird beim Vergrößern halt etwas mehr gemacht, da hierbei für einen zukünftigen Aufruf von ReallocMem vorgesorgt wird. Und wenn man sich dazu noch den Benchmark (Anzahl der Aufrufe der einzelnen Memory-Funktionen) ansieht, dann wird deutlich, daß der größte Teil an Aufrufen nicht beim ReallocMem liegt, wodurch also viel öfters passend Allociert wird, und somit meißtens "kein" Mehrverbrauch zu erwarten ist. Und wie Hagen schon sagte kann man nicht für alles den MM verantwortlich machen, denn man hat auf vieles selber Einfluß und kann selber an vielen Stellen verbesserungen innerhalb der eigenen Codes hervorrufen. Und was die Fragmentierung anmgeht, so scheint BorlandMM wohl ganz schöne Probleme zu haben, welche bei anderen nicht so stark auftreten. PS: @Hagen In deinem letzten Beitrag (#16) sagtest du was von 'ner Art Cache ... was meinst du, wenn man etwas derartiges direkt in den MM mit einbauen könnte ... also z.B. spezielle GetMem/FreeMem, welche auf einen Cache mit vorher festgelegen Blockgrößen zugreift? [add] Manchmal ist man auch sowas von Blind :wall: eine entsprechende Funktionalität für einen benutzerdefinierten Cachebereich existiert ja schon und wird fleißig für alle Speicherblöcke bis 2 KB - 4 Byte verwendet. Im grunde genommen brauchte ich ja nur dieses erweitern und lediglich eine Procedur zum Initialisieren der einzelnen Cacheguppen erstellen. Und könnte dann alles über die Standardfunktionen (GetMem/FreeMem) laufen lassen ... wobei ich dann dort wohl lieber noch Konstanten für den schnelleren Zugriff auf eine bestimme Cachegruppe einführen, welche dann statt der gewünschten Blockgröße (Size) angegeben wird ... wäre ja nicht gerade effektiv immer erst nachzusehen ob eine gewünschte Größe (Size) zufällig in einem der Cacheblöcke vorhanden ist :stupid: Also, wenn jemand sowas gebrauchen könnte/würde, dann bitte melden ... man muß sich ja nicht mehr Arbeit machen, also unbedingt nötig -.-'' |
Re: FastMM grotten langsam ?!
Hm, die Idee solche "Caches" in den MM auszulagern halt ich für Zeitverschwendung.
1.) Die Art & Weise, also welchen Typus "Cache" man benutzen wird hängt sehr stark von der Aufgabe und sogar von späteren Tests ab. So gibt es zb. alleine bei der Art&Weise wie der Cache befüllt wird Unterschiede. Zb. LIFO oder FIFO Caches, random Access Caches etc. pp. 2.) Die Größe und Anforderungen an den Cache hängen von den Datenmengen ab. Ein Cache der mit minimalem Aufwand zb. 1024 Datenelemente verwalten kann wird bei 1024*1024 anderen Datenelementen eventuell viel inperformanter sein als eine andere "Cache" Struktur. Ich meine also das der Programmierer eines MM's nicht hellsehen und schon garnicht es allen möglichen zukünftigen Anforderungen recht machen kann. In meinen IIntegers wird dieser sogenannte Pool = Cache als FIFO mit konfigurierbarer Tiefe ausgelegt. Zuerst hatte ich einen LIFO=Stack benutzt und musste dann aber feststellen das kontrahär zum eigenen Gefühl der FIFO wesentlich effizienter war. Interessant an der Sache war der Punkt der dynamisch einstellbaren FIFO Speichertiefe. Diese ermöglichte nämlich später in den Performancetests mit sehr sehr unterschiedlichen mathematischen Formeln, aber immer der gleichen underlaying Math Library, einige statistische Gegenüberstellungen durchzuführen. Obwohl nun die math. Library identisch ist, und in vielen Bereichen sogar vergleichbar und in der Anzahl ähnliche math. Funktinen benutzt wurden, gab es bei all dieses Algorithmen sehr unterschiedliche FIFO Speichertiefen die zur maximalen Performance führten. Es war sogar meisten so das gleich mehrer unterschiedliche Speichertiefe maximale Performance lieferten. D.h. die Performancekurve relativ zur gewählten Speichertiefe war niemals linear noch stetig. Der Glaube "viel hilft viel" wurde eindeutig wiederlegt. Soll heissen: Obwohl die Aufgaben für diesen "Speichermanager" sehr sehr ähnlich waren gab es keine FIFO Speichertiefe die bei allen Aufgaben immer ein optimales Ergebnis lieferte. Genau der gleichen Situation sehen sich Programierer eines allgemeingültigen MMs gegenübergestellt. Da aber die Menge aller möglichen Algorithmen unendlich groß ist wird es niemals DEN Speichermamanger geben können. Gruß Hagen |
Re: FastMM grotten langsam ?!
Das einzigste was mich an der Entwicklung eines eigenen MMs reizen würde ist folgender Gedanke:
Oben beschrieb ich ja schon das es niemals einen MM-Algorithmus geben kann der durchschnittlich allen möglichen Anforderungen gerecht werden kann. Diese Aussage stimmt nur bedingt wenn man sich vom Konzept eines "statischen" MMs verabschiedet. Das Konzept eines "dynamischen" MMs wäre es nun die Anforderungen an den MM selber statistisch zu analysieren und darauf hin seine Taktiken dynamsich anzupassen. Sogesehen würde ich einen solchen MM als strategisch intelligent bezeichnen. Die Challange dabei wäre es einerseits einen celveren Algo. zu entwicklen und andererseits die zusätzlich nötige statistische Auswertung und Speicherverbrauch optimiert hinzubekommen. Gruß Hagen |
Re: FastMM grotten langsam ?!
Moin, Spätmoin,
also Hagen, bei Deinem Monolog habe ich doch andächtig gelauscht und kann dem doch widerstehen einen Speichermanager selbst zu programmieren, auch wenn ich vor Optimierungsalgorrihtmen nicht wirklich zurückschrecke. Zudem ist mir beim Test doch aufgefallen, dass mehr Speicher Geschwindigkeit bringt, auch mit einem Teil der Folgen, die Du beschrieben hast. 1.) Wäre es überhaupt denkbar einen Speichermanager so anzupassen, dass er bei Com und OLE Objekten keinen größeren Speicherbereich anfordert, also nur auf normale Objekte mit seiner Optimierung reagiert. 2.) Endet das letztlich in einer Art zeitgesteuerten Garbage-Collection. Dein Speichermanager müßte ja in den Idle-Zeiten genauer Untersuchen welche Speicherlücken er noch freigeben kann. 3.) Ist das nicht eher die Aufgabe eines Programm unabhängigen Dienstes? Viele Grüße // Martin |
Re: FastMM grotten langsam ?!
Zu 1:
Denkbar ist vieles, sogar sowas, nur wird es halt schwierig festzulegen wann es sich um ein COM/OLE-Objekt handelt. Zu 2 und 3: Ich habe ja mit Absich nicht etwas derartiges eingebaut, obwohl ich es Anfangs vor hatte und FastMM besitzt auch nichts vergleichbares. Denn wie Hagen schon sagte, es ist unmöglich für den MM festzustellen ob ein Speicherblock noch benötigt wird, selbst wenn der Thread, welcher diesen hat allocieren lassen längst beendet ist, denn es kann ja durchaus sein, daß der Speicherblock an einen anderen Thread übergeben wurde, was der MM ja nicht wissen kann. |
Re: FastMM grotten langsam ?!
Moin, Himitsu
bei Deinem Speichermanager mußte ich leider feststellen, dass er nich unter D6 zu compilieren ist, sodass ich jetzt auch keine Vergleich liefern kann. Aber letzlich ist doch das Resultat, dass diese Speichermanager nur da interessant sind, wo im wesentlichen mit einer Anwendung auf dem Rechner gearbeitet wird. Oder ist das jetzt überinterpretiert? Grüße //Martin |
Re: FastMM grotten langsam ?!
Tut mir Leid .. das ist ja nur 'ne Auskopplung aus meinem UCC und dort hatte ich noch keine Zeit es abwärtskompatibel zu machen ... aber bis auf D4 runter sollt es mal irgendwann laufen ._.
Aber kannst du mir mal sagen was da nicht laufen will? (hab derzeit mein D4 nicht installiert) |
Re: FastMM grotten langsam ?!
Zitat:
RecyclerMM alloziert quasi für jeden Thread einen eigenen unabhängigen Speichermanager. Nun stellen wir uns mal vor dieser Thread übergibt tatsächlich einen für ihn allozierten Speicherbereich einem anderen Thread. Was soll passieren wenn der allozierende Thread nun terminiert wird ? Reagiert RecyclerMM darauf und zerstört den threadeigenen Speichermanager so zerstört er für den anderen Thread diesen übergebenen Speicherblock. Reagiert RecyclerMM aber nicht auf die Termination des Threads so bleiben Speicherleichen übrig. Dieses Verhalten kann mit einem threadübergreifenden MM, wie dem BorlandMM oder FastMM4 nicht auftreten. Man kann aber durch eine ausführliche Dokumentation und eventuell vorhanden spezielle Kopierfunktionen dieses Problem umgehen. Wichtiger ist einfach die Frage ob es einen allgemeingültigen und immer funktionierenden Weg gibt das RecyclerMM auf die Terminierung eines beliebigen Threads reagieren kann. Und diese Frage muß man auf API Ebene ganz klar mit "nicht möglich" beantworten. Der einzisgte Ausweg wäre ein virtueller Treiber der sich in das Kernel einklinkt und auf die Termierung eines beliebigen Threads reagiert. Gruß Hagen |
Re: FastMM grotten langsam ?!
Zitat:
Man könnte mit Sicherheit einen MM programmieren der mehrere GetMem() Funktionen besäße. Je nach gewünschtem Verhalten würden diese GetMem() Versionen unterschiedliche Speuicheranforderungen durchführen. Zb. eben ein GetMem() für die LongStrings die mit hoher Wahrscheinlichkeit ReallocMem() aufrufen. Und ein anderes GetMem() für Speicherbereiche die immer fixierte Länge besäßen. Zitat:
Die Idle Methode bezog sich darauf die Threadeigenen MMs innerhalb vom recyclerMM wieder freizugeben. Dabei wird periodisch überprüft ob zu einem Threadeigenem MM der Thread noch gültig ist. Nur gibt es eben auf API Ebene keinen Weg zu erkennen ob ein Thread Handle oder ThreadID noch gültig ist. Dies ist im Grunde exakt das gleiche Problem mit Objektreferenzen. Also Zeiger auf Objekte bei denen aber das Objekt schon längst wieder freigegeben wurde. Der Objektzeiger zeigt also in einen Speicherbereich in dem schon längst nicht mehr das originale Objekt gespeichert ist sondern entweder garkeines oder noch viel schlimmer ein neues der gleichen Klasse, aber eben NICHT mehr das originale ! Da Windows ebenfalls die Handles in der internen Handletabelle zum Prozess wiederverwendetet und unter Win95 zb. die ThreadID direkt korrespondiert zum Speicherbereich des Threadhandles (ThreadID ist quasi ein umgerechneter Wert des Speicherbereiches auf den das Handle zeigt), entsteht somit exakt das gleiche Problem wie bei den Objekten. Man kann definitiv nicht erkennen ob ein Thread Handle/ID noch der original gemeinte Thread ist. Zitat:
Man kann zb. einen TCP/IP Server als DLL, Dienst oder eigene Anwendung programmieren, dadurch ändert sich aber nichts am Verhalten des Servers ansich. Zitat:
Konzeptionell würde ich ein solches System aber anders angehen. Zb. einen MM der einen "Lern-modus" enthält. Wie oben angedeutet gäbe es verschiedene GetMem() Funktionen. Eine für definitiv sich reallokierende Funktionen und einen für fixed Size Allokationen. Man bindet einen solchen MM ganz normal in seine Anwendung ein, per Compilerswisches im "Lern"-Modus. Der MM protokolliert nun jede Speicherallokation und auch die Reallokationen schon bestehender Speicherbereiche. Ausgehend davon ermittelt er also mit welcher GetMem() Funktion,sprich welchen Typus von Speicher die Anwendung zu jedem zeitpunkt benötigt. Daraus ermittelt er zb. das Funktion XYZ immer nur Speicher alloziert mit fester Größe a 32 Bytes. Diese Information führt dazu das im Patch-Modus der MM eine spezielle GetMem() Funktion an die originale Stelle des Funktionsaufrufes hinein "patcht". Die Funktion XYZ ruft ab jetzt immer eine GetMem() Funktion auf die nur Blöcke von 32 Bytes in einem speziellen Speicherbereich alloziert. Oder Funktion ABC führt eine LongString Berechnung durch. Dabei wird er String additiv vergrößert, von zb. 4 Zeichen auf durchscnittlich 1024 Zeichen +-128 Zeichen. Diese statistischen Infos werden im MM im Lernmodus ermittelt und führen nun im gepatchten Modus dazu das der erste Aufruf von GetMem() in Funktion ABC sofort einen String mit Länge 1024 alloziert. So bei diesem MM gäbe es noch einen Lernmodus und eine finale gepatchte Anwendung. Schafft man es dies statistischen Informionen aber kompakt und permanent aktuell zu halten so könnte man auch auf diese 2 Phase verzichten und der MM würde quasi permanent lernen und entscheiden. Gruß Hagen |
Re: FastMM grotten langsam ?!
Im Lernmodus könnte man die zusätzlichen statitischen Infos selber im Speicherblock speichern, sprich Addresse des GetMem() aufrufes in der übergeordneten Funktion, erstmalige Speichergöße, Anzahl der Reallokationen, durschnittliche Reallokations-Größe in Bytes und finale maximal Speichergröße. Diese Daten werden dann extern gespeichert für die spätere Auswertung. Man lässt also die Anwednung erstmal unteer verschiedenen Umweltbedinugen laufen. Später in der Auswertung kann man nun anhand dieser Daten erstmal überprüfen wo und wann Speicherlecks auftreten. Dann kann man noch unterscheiden zwischen Speicherallokationen mit immer fester Größe und somit all diese Aufrufe auf eine spezielle GetMem() Funktion umleiten. Oder man erkennt das ein Speicherbereich oft vergrößert wird und ermittelt die durschnittlich beste Speichergröße. Wiederum diregiert man die GetMem() Aufrufe zu einer speziellen Version um die nun schon beim ersten Aufruf einen Speicherbereich auf die durchschnittliche Größe alloziert.
Aus all diesen Infos entsteht quasi ein Patch-Protokoll das die finale Version des Programmes mit dem nicht-lernfähigen MM entsprechend abändert. Gruß Hagen |
Re: FastMM grotten langsam ?!
Nur so mal, als kleine Anekdote: Der SQL-Server von Microsoft verzichtet aus Performancegründen komplett auf einen Speichermanager im herkömmlichen Sinn. Alle internen Datenstrukturen sind statisch angelegt. Der "Speichermanager" verwaltet die Pages (also die Seiten in denen die Daten stehen) als verkettete Liste: Seiten, die am Ende der Liste gelandet sind, werden ggf. recycled oder an Windows zurück gegeben (selten).
Im Endeffekt bedeutet das, das das 'komfortable' Arbeiten mit einer dynamischen Speicherverwaltung eben Zeit kostet. Wenn man wirklich schnelle Programme benötigt, muss man sich eben davon verabschieden. Wie so oft gilt auch hier: Das Design entscheidet über Performance. Ich halte auch Nichts von langwierigen Analysen der konkreten Speicheranforderungen einer Applikation. Denn hier wird man höchstens marginal etwas verbessern können: Eine Anwendung, die schnell laufen muss, aber Millionen von Speicherblöcken alloziiert und freigibt, hat einen Designfehler und 'verdient' es nicht, das man an ihr rumdoktort, denn es ist anzunehmen, das die Applikation auch sonst schlecht geschrieben ist. |
Re: FastMM grotten langsam ?!
Zitat:
Denoch meine ich das ein komplett neuer MM der die Aussicht auf wesentlich bessere Performance als die bisherigen haben soll, nur mit einem komplett neuem Konzept Erfolg haben kann. Und gerade ein "strategisch intelligenter" MM entlastet ja den Programmierer von der Verantwortung und dem Aufwand sich über bessere Datenstrukturen und Optimierungen in den eigenen Algorithmen Gedanken machen zu müssen. Und diese Sichtweise ist nicht zwangsläufig eine schlechte Sichtweise. Eines weis ich aber mit Gewissheit: die jetzigen MMs wie FastMM4 haben die bisherigen Konzepte im Grunde bis an ihre Grenze ausgenutzt. Um sie nun noch performanter zu machen müssen sie weitreichendere Information sammeln und dann entsprechend auch nutzen. Ich meine also das man sehr wohl noch nicht die Performancegrenze ansich erreicht hat, sondern nur das die bisherigen Algorithmen ausgereizt sind. Gruß Hagen |
Re: FastMM grotten langsam ?!
Das mit dem Informationen sammeln hab ich ja im Moment etwas anders gelöst ... bei meinen String-Funktionen kann man ja (wenn nötig) selber entsprechende Informationen mitgeben. Es ist also möglich selber zu beeinflussen, wie das Speichermanagement arbeiten soll und es so etwas an seine Bedürfnisse anzupassen.
|
Re: FastMM grotten langsam ?!
Es gibt durchaus eine begrenzte Moeglichkeit mehrere spezifische Memorymanager parallel zu fahren.
Es gibt naemlich drei verschiedene Typen von Alloziierungen/Dealloziierungen in die man sich einklinken kann. 1. explizit per GetMem/FreeMem 2. implizit fuer Strings 3. indirekt fuer Objekte Damit koennte man drei verschiedene Pools mit spezifisch optimierten Strategien implementieren, denn die alloziierten Elemente koennen nicht von einem Pool in den anderen geraten. Zumindest nicht durch Code der nicht komplett falsch ist. Niemand wuerde auf die Idee kommen das ein FreeMem auf ein Objekt eine ungefaehrliche Operation ist. |
Re: FastMM grotten langsam ?!
Zitat:
3. würde einen festen Speicherbereich benötigen, da Objekte nicht mehr realloziert werden. 2. hat die höchste Wahrscheinlichkeit für Reallokationen und ein entsprechend großer Überhang bei der Allokation wäre hier am sinnvollsten um Fragmentierungen zu vermeiden 1. kann beides sein und wird eine Mixtur ergeben, die Fragmentierungen dürften hier am größten sein, dafür werden direkte Aufrufe von GetMem()/FreeMem() immer weniger in heutigen Libraries benutzt. Es macht also durchaus Sinn darüber nachzudenken verschiedene Funktionen dafür zu coden. Gruß Hagen |
Re: FastMM grotten langsam ?!
Alles schön und gut. Aber wie stelle ich nun FastMM4 ein, dass er bei einer Multithreading Anwendung am effizientesten arbeitet ??. Weiters habe ich festgestellt, dass bei Verwendung von TVirtualTreeView beim Beenden angebliche Speicherlecks auftreten (MemProof hat da keine gefunden). Die .inc Datei des FastMM4 ist ja elends lange. Welche Schalter sollte man setzen ???
|
Re: FastMM grotten langsam ?!
Wenn FastMM4 Speicherlecks findet, sind da auch Welche. Die .inc-Dateien sind zwar lang, aber lesen sollte man das schon. Das nennt sich 'user manual'. Dort findest Du dann auch die optimale Einstellung für multithreaded Anwendungen. Die habe ich nämlich nicht im Kopf und müsste auch erst lesen.
|
Re: FastMM grotten langsam ?!
SpeicherLeak's ... es ist schon so, daß FastMM nur Meckert, wenn beim Beenden noch irgendwelche Speicherbereiche reserviert sind, also nicht Freigegeben wurden, daß heißt, wenn da gemeckert wird, dann ist da auch ein Leak ... vielleicht sollte sollten die von MemProf mal bei sich suchen, wenn es da nichts findet.
PS: wozu ein User-Manual, die Kommentare in der .inc sind doch eigentlich soweit selbsterlärend. Na ja, gerade deswegen ist bei meiner Version fast nichts mehr einzustellen :roll: |
Re: FastMM grotten langsam ?!
Ist zwar richtig, das die Kommentare selbsterklärend sind. Trotzdem gibt es immer noich fragen. Ist es besser die Speicherleckerkennung aus/abzuschalten ?? Wie wirkt sich das auf die Laufzeit aus ?? Gibt es Schalterkombinationen, die die Effizienz des Speichermanagers erhöhen (in Bezug auf Multithreading) ?? Ich setze derzeit den FastMM bei einer Anwendung mit mehr als 1 Million Codezeilen ein. Da kommts auf jede 1/10 Sekunde an.
|
Re: FastMM grotten langsam ?!
Zitat:
|
Re: FastMM grotten langsam ?!
Gut, meine Anwendung ist etwas kleiner, aber dafür werden die die Zeilen auch mehrfach ausgeführt (Stichwort: "Wiederverwendung von Zeilen" = Recycling = Gut für die Umwelt!)
Ich dachte mir zuerst, "nimmste FastMM4, dann geht die Luzie ab"... Nach umfangreichen Tests habe ich keinen signifikanten Unterschied festgestellt. Ich habe nur reihenweise Speicherlecks gefunden, denn da ist FastMM4 wirklich gnadenlos. Zu deinen Fragen: Speicherleckerkennung kostet Zeit. Welche Schalter man bei Performanceoptimierung erst gar nicht anfässt, ist doch auch klar. Bleiben noch einige Optimierungsschalter, von denen gibt es vielleicht 3-5 Stück, macht 8-32 Kombinationen. Von denen widerum sind Einige nicht möglich, bleiben also doch nur eine Handvoll Kombinationen übrig. Teste doch einfach mal, ich kann mir vorstellen, das es wirklich auf die Einzelanwendung ankommt. Und wenn Du Zig-Millionen Mal Speicher anforderst, kann es sein, das dein Programm von der Performanceseite her suboptimal gestaltet ist. Ich habe z.B. eine Anwendung, die benötigt Instanzen einer Klasse, die ca 8kb gross ist, und ständig. Anstatt die Klassen brav zu instantiieren, verwende ich eine eigene Garbagecollection und habe damit schon sehr viel rausgeholt. Vor einiger Zeit gab es mal eine Diskussion (hier oder DF) um einen optimalen Speichermanager, denn es gibt ihn noch nicht. |
Re: FastMM grotten langsam ?!
Zitat:
|
Re: FastMM grotten langsam ?!
Die Speicherleckerkennung verlangsammt den MM etwas und verbraucht auch noch etwas mehr Speicher, da ja irgendwie zusätzlich zum "normalen" Betrieb noch die Informationen für die Leckerkennung verarbeitet und gespeichert werden nüssen.
Was mit dem OutOfMemory hatte ich schonmal gesagt, ich bin mittler Weile soweit den MM von Delphi mit 'nem winzigen mehrdimensionalem Array (in meinem Fall war's ein String-Array) zu überlasten - virtueller Speicher war'n knapp 800 MB vorhanden und mit nichmal 50 MB tatsächlischem Speicherverbrauch meldete der Delphi-MM OutOfMemory und belegte selber fast den gesammten zur Verfügung stehenen virtuellen RAM. Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz