Stackoverflow bei instanzierung eine großen Objekts.
-
50 kloc+ in einer Funktion ist in modernen Hochsprachen einfach keine gute Idee. Quasi sämtliche Teile der Kette sind nicht darauf ausgelegt das zu verdauen, und speiben sich dementsprechend auch regelmässig an bei sowas. Der Umstand dass der Code super einfach ist, keine Schleifen enthält etc. ändert daran leider nichts.
-
Ein möglicher Workaround wäre den Code-Generator so umzustellen dass er z.B. für je 100~1000 Zeilen eine Funktion generiert, diese alle mit
[MethodImpl(MethodImplOptions.NoInlining)]
markiert und dann alle hintereinander im ctor aufruft.
Kann nicht garantieren dass es hilft, aber wäre mMn. Wert dass man es ausprobiert.
-
@Schlangenmensch sagte in Stackoverflow bei instanzierung eine großen Objekts.:
Ich habe keine Ahnung von C#, aber wenn es ein Problem ist, dass die Source Datei zu groß ist, weil alles in MyBigObject() passiert, würde ich das verlagern, also z.B. die Variable this.Root.B.A im Konstruktor von ObjectZ() erstellen.
Das ist ein guter Vorschlag, das habe ich mir auch schon überlegt. Leider erlaubt diese das aktuellen Software design nicht, und das zu ändern ist nicht gewollt, und zudem ein mega aufwand.
@Schlangenmensch sagte in Stackoverflow bei instanzierung eine großen Objekts.:
@SoIntMan sagte in Stackoverflow bei instanzierung eine großen Objekts.:
ja das passiert ab und an.. OutOfMemory oder VS stürzt ohne meldung ab
Vlt wäre es eine Möglichkeit schonmal VS 2022 auszuprobieren, dann mit 64 bit Unterstützung. Das könnte an der Stelle helfen.
ja das wäre ne Notlösung. ich sag's euch, Katastrophe die Leute da;=)
@hustbaer sagte in Stackoverflow bei instanzierung eine großen Objekts.:
50 kloc+ in einer Funktion ist in modernen Hochsprachen einfach keine gute Idee. Quasi sämtliche Teile der Kette sind nicht darauf ausgelegt das zu verdauen, und speiben sich dementsprechend auch regelmässig an bei sowas. Der Umstand dass der Code super einfach ist, keine Schleifen enthält etc. ändert daran leider nichts.
bin ganz deiner Meinung. Ich hätte das ganz anderes gemacht, aber die Urheber damals waren halt keine Architekten. Damals war das Objekt gar nich so umfangreich, aber es skaliert hat gerade gar nicht mehr. Ich würde es gern anpassen, aber das kostet zudem Geld;) und die leute kapieren es nicht das es ein großem problem is.
@hustbaer sagte in Stackoverflow bei instanzierung eine großen Objekts.:
Ein möglicher Workaround wäre den Code-Generator so umzustellen dass er z.B. für je 100~1000 Zeilen eine Funktion generiert, diese alle mit [MethodImpl(MethodImplOptions.NoInlining)] markiert und dann alle hintereinander im ctor aufruft.
Kann nicht garantieren dass es hilft, aber wäre mMn. Wert dass man es ausprobiert.du meinst ich soll die ca 50000 zeilen in 50 funktion splitten mit dem attribute?
-
@SoIntMan sagte in Stackoverflow bei instanzierung eine großen Objekts.:
du meinst ich soll die ca 50000 zeilen in 50 funktion splitten mit dem attribute?
Ja. Wenn du das ohne grossen Aufwand machen kannst, wäre das einen Versuch wert.
-
@hustbaer sagte in Stackoverflow bei instanzierung eine großen Objekts.:
Ja. Wenn du das ohne grossen Aufwand machen kannst, wäre das einen Versuch wert.
klar, ich kann auch jede zeile in ne funktion auslagern;) das Proble ich glatt aus;) es funktioniert momenta (gerade so am limit) aber das mache ich .. danke dir.
Aber eine rein technische frage dazu:
Würde ich bspw. die Zeile
this.x = new ObjectX();
n eine Function
void Create<T>(ref T target) : where T: class, new() { target = new T(); }
dann im ctor
Create<ObjectX>(ref this.x);
kapseln, würde der Compiler dann für jeden call ein sprungbefehlt zur Funktion setzen, oder die Funktion n-mal an der stelle , ich nehme an dass du genau das mit nem notInline meinst gell.
-
@SoIntMan
Also meine Idee war die, dass der JIT vielleicht einfach dadurch langsam wird und viel Speicher braucht, dass die Funktion so riesig ist. Wäre vorstellbar dass da Dinge passieren die nicht linear skalieren sondern schelchter. Also z.B. dass der JIT z.B. 4x länger braucht (und vielleicht auch 4x so viel Stack), wenn die Funktion 2x länger wird.In dem Fall kann es etwas bringen die Funktion in mehrere Stücke zu zerteilen. Nun gibt es aber - zumindest in C++ Compilern - eine Optimierung, die dann greift wenn die Funktion nur an einer einzigen Stelle aufgerufen wird. Diese werden viel eher inlined als Funktionen die an vielen Stellen aufgerufen werden. Grund ist einfach: wenn ich eine eher lange Funktion habe, und die an 100 Stellen inline, dann verschwende ich enorm Speicher. Wenn die Funktion dagegen nur an einer Stelle aufgerufen wird, dann ist es nicht wirklich wichtig wie lange die ist.
Daher hab ich sicherheitshalber empfohlen das "no inline" Attribut dranzuschreiben. Um zu verhindern dass der JIT sieht dass die Funktion nur an der einen Stelle aufgerufen wird, und beschliesst sie zu inlinen, trotz dem sie recht gross ist. Keine Ahnung ob das passieren würde, aber ich denke ein "no inline" Attribut an der Stelle kann nicht schaden.Um was es mir hauptsächlich ging ist aber eher einfach zu verhindern dass so grosse Funktionen geJITed werden müssen. Und da wäre dann jede einzelne Zeile in eine Funktion zu packen wieder kontraproduktiv. Weil du dann ja wieder eine grosse Funktion brauchst die alle kleinen aufruft.
Ob es überhaupt am JIT liegt kannst du aber relativ einfach ausprobieren. Wenn es am JIT liegt, dann sollte nur der 1. Aufruf der Funktion ein Problem sein. Weitere Aufrufe sollten dann auch ohne vergrösserten Stack gehen, und auch viel schneller laufen.
-
@hustbaer sagte in Stackoverflow bei instanzierung eine großen Objekts.:
Ob es überhaupt am JIT liegt kannst du aber relativ einfach ausprobieren. Wenn es am JIT liegt, dann sollte nur der 1. Aufruf der Funktion ein Problem sein. Weitere Aufrufe sollten dann auch ohne vergrösserten Stack gehen, und auch viel schneller laufen.
Also was mir eben aufgefallen ist, dass (im Debugger) wenn ich ein Breakpoint zur ersten Zeile (Funktion) setzt, und der Breakpoint erreicht wird. dann is alles in Butter und er ratterst die 50 Zeilen vollgas durch.
Aber von CreateInstance<MyBigObject>() bis zum Breakpoint der ersten Zeile in Ctor des MyBigObject. sehe ich im Diagnose tool VS dass der Speicher auf 1,3GB ansteigt, dann absinkt auf 200MB und dann zum Breakpoint hängt.
Das dauert 10-15sekunden , und da kann eben ein OutOfMemory kommen oder ein StackOverflow.. aber wenn er dann im ctor hängt passiert nichts mehr (außer ich würde evlt. in den 50k Zeilen zu viel Speicher allokieren dass es dann dock knallt=)Weißt wie ich mein?)
-
@SoIntMan sagte in Stackoverflow bei instanzierung eine großen Objekts.:
Aber von CreateInstance<MyBigObject>() bis zum Breakpoint der ersten Zeile in Ctor des MyBigObject. sehe ich im Diagnose tool VS dass der Speicher auf 1,3GB ansteigt, dann absinkt auf 200MB und dann zum Breakpoint hängt.
Das dauert 10-15sekunden , und da kann eben ein OutOfMemory kommen oder ein StackOverflow.. aber wenn er dann im ctor hängt passiert nichts mehr (außer ich würde evlt. in den 50k Zeilen zu viel Speicher allokieren dass es dann dock knallt=)Das klingt würde ich sagen sehr nach JIT. Aber...
Weißt wie ich mein?)
Nein, bin nicht sicher ob ich das richtig verstehe. Was macht denn
CreateInstance<MyBigObject>()
? Bisher hast du immer vonnew MyBigObject
geschrieben. (Bzw. 1xnew ObjectX
wo aber vermutlichnew MyBigObject
gemeint war.)Und: hast du denn ausprobiert was passiert wenn du den Code 2x hintereinander ausführst (natürlich ohne das Programm 2x zu starten)?
-
@hustbaer sagte in Stackoverflow bei instanzierung eine großen Objekts.:
Nein, bin nicht sicher ob ich das richtig verstehe. Was macht denn CreateInstance<MyBigObject>()? Bisher hast du immer von new MyBigObject geschrieben. (Bzw. 1x new ObjectX wo aber vermutlich new MyBigObject gemeint war.)
sorry für Verwirrung, ich meinte ich hatte die allokieren in ein funktion ausgelagert, weil ich vorhatte evtl. business logig zu kapseln, aber bisher siehtes einfach so aus.
T x = CreateInstance<T>() where T: class, new() => new T() ;
genau ich meinte im Prinzip immer n```csharp
ew MyBigObject().hmm ok 2 mal hintereiander also :
var a = new MyBigObject (); var b = new MyBigObject ();
du vermutest dass es dann nur bei de ersten Zeile so lang dauert, und bei de 2-ten dann nich mehr , hab ich recht!?
Muss ich heute abend mal ausprobieren
-
@SoIntMan sagte in Stackoverflow bei instanzierung eine großen Objekts.:
du vermutest dass es dann nur bei de ersten Zeile so lang dauert, und bei de 2-ten dann nich mehr , hab ich recht!?
Ja. Oder sagen wir so: wenn es am JIT liegt, dann müsste das so sein. Bzw. auch umgekehrt: wenn es so ist, dann liegt es ziemlich sicher am JIT.
-
@hustbaer sagte in Stackoverflow bei instanzierung eine großen Objekts.:
Ja. Oder sagen wir so: wenn es am JIT liegt, dann müsste das so sein. Bzw. auch umgekehrt: wenn es so ist, dann liegt es ziemlich sicher am JIT.
Alles klar Kommender ich kam bisher nicht dazu , heute probiere ich es
EDIT: @hustbaer Ja die zweite Instanziierung scheint schneller zu gehen;)