Ungewöhnlich hoher RAM-Verbrauch von TPF2 führt zum Absturz des Spiels / OS

Willkommen in der Transport Fever Community

Welcome to the fan community of Transport Fever and Train Fever, the economic simulators of Urban Games. The community is free for you to share and inform yourself about the game. We cultivate a friendly and objective interaction with each other and our team will be happy to answer any questions you may have.

 

Registration and use is of course free for you.

 

We wish you a lot of fun and hope for active participation.

The Team of the Transport-Fever Community

  • Hab es jetzt als Github-Repo veröffentlicht -> https://github.com/MarkMcWire/TPF2-Timetables

    Danke dir! So als unerfahrener Github-Noob sehe ich die grüne Dropdown-Fläche, wo "Code" draufsteht, wähle dort den ZIP-Download aus und kopiere/entpacke es anstelle der originalen Fahrplanmod in den üblichen Mod-Ordner. Das war's schon, oder muss man ingame noch etwas machen (ausser Fahrpläne anlegen natürlich)?

    aktuelles System: PC mit AMD Ryzen 9 5900X - 64GB RAM // AMD Radeon RX 6700XT 12 GB VRAM // 1TB SSD und 2+1 TB HD // 32-Zoll-Monitor mit 4K

    altes System: ASUS ROG GV752VW-T4004T: Intel Core i7-6700HQ - 16GB RAM // NVidia GTX960M 2 GB VRAM // 512GB SSD und 1024 GB HDD // 17-Zoll-FullHD

  • Wichtig :!::!::!: Vor Installation der neuen Fahrpläne-Version von MarkMarcWire aus github müsst ihr in der sav.lua den Eintrag ["timetable_gui.lua"] in ["timetable_engine.lua"] ändern, sonst sind eure Einträge weg.


    Das UI funktioniert übrigens nach wie vor holprig und unterdrückt manchmal Eingaben. Ich tippe mal blind, dass die Abfragegeschwindigkeit irgendwann reduziert wurde, ohne die Eingaben zu cachen. Diese, egal ob über Tastatur oder Maus, verschwinden dann im Nirvana. Wobei ich mich wundere, dass solch gravierende Bugs, die schon ewig drin sind, nicht mit Priorität angegangen werden. :(


    Edit: Mir scheint es so, als ob die Abstürze und Bugs bei GUI-Bedienung von Version zu Version zunehmen, ohne dass das Problem mit Priorität angegangen wird. Abfahrtszeiten gebe ich nur noch in der .sav.lua-Datei ein und lade dann neu; die Eingabe über den Dialog ist katastrophal und reines Glücksspiel mit etwa 50% Gewinnchance! ;( Neulich bekam ich sogar eine Absturzmeldung, ein UI-Element sei während eines Events zerstört worden. :(

    Auch, wenn ich in GUI-Programmierung noch ein wenig unerfahren bin, gebe ich mal zwei Theorien zum Besten:

    • GUI-Elemente werden mehrfach initialisiert. Das wäre eine Erklärung für den RAM-Verbrauch.
    • GUI-Elemente werden zu früh oder an falscher Stelle zerstört. Das wäre womöglich ein Synchronisierungsproblem.

    Wie dem auch sei: Den Fehler sehe ich mit hoher Wahrscheinlichkeit im GUI-Handling. Da ist mächtig der Wurm drin, und das von Anfang an. Ursprünglich äußerte es sich aber "nur" in fehlerhaften Updates des Linienfensters.

    RE heißt jetzt RRX, es fährt jetzt NX, fällt x-mal aus, sonst ändert sich nix. ;-)

    Edited 3 times, last by WernerK ().

  • Der Vollständigkeit halber:

    Die Änderungen von MarkMcWire wurden im November zunächst in Gregorys Fork ("1.3" auf Steam) gemergt, dann aber kurz darauf wieder rückgängig gemacht, aufgrund der Inkompatibilität mit bestehenden Fahrplänen, d.h. alle Einträge waren weg. Seitdem ist dort nichts mehr passiert. Im Discord wird gesagt man kann MarkMcWires Version (1.3.7) manuell installieren, wenn man vorher in der sav.lua eine Anpassung vornimmt, genauso wie auch von WernerK oben beschrieben.


    Hab nochmal kurz über die Changes geschaut: in der Theorie könnte MarkMcWires das Auftreten eines bestimmten (zufälligen) Crashs verhindern. Im Code sind allerdings auch viele Änderungen drinnen, die erfahrungsgemäß keinen Unterschied machen sollten.


    Weitere Infos zu Hintergründen und Testberichte der verschiedenen Versionen wären sicher hilfreich.

  • Irgendwo habe ich mal gelesen, die Version 1.2 + letztem Patch liefe recht gut. Zumindest das GUI könnte dort etwas stabiler laufen, aber das habe ich nicht getestet, und ich denke auch nicht, dass das Speicherproblem da raus ist. Ich benutze momentan - mit Kopfschmerzen - die Version 1.3 von MarkMcWire mit den (immer noch) angepassten Einträgen in der sav.lua und nehme auch sonst fast alle Einträge dort vor. Das klappt auch. Dennoch bin ich schon fast an dem Punkt angelangt, wo ich am liebsten etwas eigenes schreiben möchte. ?(

    RE heißt jetzt RRX, es fährt jetzt NX, fällt x-mal aus, sonst ändert sich nix. ;-)

    Edited once, last by WernerK ().

  • Moin zusammen,


    ich hatte auch die 1.3 aus dem Workshop probiert. Das Spiel ist mir beim entfernen eines Zeiteintags (X-Button) aus dem Fahrplan dann abgestürzt. Seitdem nutze ich wieder die Version 1.2, habe allerdings bei der unerklärliche in regelmäßigen Abständen Ruckler, in dem das Spiel kurz für ein paar Sekunden einfriert.


    Der Absturz kommt denke ich von der fehlerhaften UI oder?

    Und das sporadische Einfrieren wahrscheinlich von der Arbeitsweise der Mod und dem RAM?

  • Hallo, da ich gerade angesprochen wurde. Ich habe in TPF2 die letzten zwei Monate nix mehr gemacht. Ich wusste damals nicht, dass es Auslagern von Scripten in eine Datei mit anderen Namen Einfluss auf bestehende Spielstände hat. Ich hatte bei mir zum Testen einen relativ neuen Spielstand genutzt, wo ich die Fahrpläne von Grund auf neu gemacht hatte.

    Ich bin nach wie vor der Meinung, dass GUI und Engine in getrennte Skripte aufgerufen werden sollten, damit das Debuggen einfacher ist.

    Ich vermute, dass es ein Synchronitätsproblem gibt beim Aktualisieren der GUI und der anderen Spielelemente.

  • Das Auslagern von Skripten im /scripts Ordner ist erstmal egal. Nur das Umbenennen von Dateien im game_script Ordner ist kritisch, weil damit der Zustand assoziiert wird, welcher im savegame gespeichert ist.


    Deine Intention ist vollkommen richtig. Eine Datei names timetable_gui.lua in der der Zustand für den Engine Thread gehalten wird, ist verwirrend. Die Gui Funktionen hätten in separate Dateien ausgelagert werden sollen. Die Timetable Mod besteht im wesentlichen aus nur 3 Dateien, während zB Advanced Statistics in 93 Dateien aufgeteilt ist. Finde ich persönlich übersichtlicher als eine 2000 Zeilen Datei.


    Aber das ist leider der Fluch von Kompatibilitätserhaltung nach Release, weil man ja einen reibungslosen Update Übergang für Nutzer haben möchte, insb. bei Steam mit automatischen Updates. Da muss man theoretisch alle möglichen Kombinationen von existierenden Zuständen in Savegames berücksichtigen, um eine Kompatibilität zu gewährleisten. Sonst werden Nutzer update-scheu und das will man als Modder ja nicht. Daher ist Refactoring immer besser vor dem offiziellen Release. Und auch generell bei gemeinschaftlichen Open-Source Projekten sind große Refactorings schwierig.

  • Quote

    Ich vermute, dass es ein Synchronitätsproblem gibt beim Aktualisieren der GUI und der anderen Spielelemente.

    Zwischendurch hatte ich noch einen anderen Verdacht: Es könnte sein, dass nicht nur versucht wird, GUI-Elemente zu löschen, die noch benutzt werden, sondern auch der umgekehrte Fall, dass irgendwo GUI-Elemente nicht zerstört werden, obwohl es notwendig wäre, und das in so großem Stil, dass es den Speicher überschwemmt.

    RE heißt jetzt RRX, es fährt jetzt NX, fällt x-mal aus, sonst ändert sich nix. ;-)

  • Vorweg: Ich nutze Timetables nicht, aber vom durchlesen und mal kurz drüber schauen des Codes und des Fehlers:

    Code
    Warning: a UI element has destroyed itself during handling an event, this leads to undefined behaviour!


    Erklärung dazu:


    Ihr habt ein uiElement:onChange oder onIrgendEtwas event.

    In der eventFn() wird dann initIrgendwas() aufgerufen.


    initIrgendwas löscht dann die ganze UI einer Tabelle und baut den ganzen Kram neu auf. Wenn uiElement in der Tabelle steckt, ist das ganze nicht möglich. Wenn die gebundene Event Funktion eines UIElement fertig ist, wo ist dann das UIElemtent hin? Das ist die Fehlermeldung dort.


    Man kann UI Element ständig neu bauen, das macht alles in UI2 der CommonAPI2 auch so. Aber Events werden bei mir komplett anders verarbeitet. Eher Asyncron. Sprich ein Event wird gespeichert und dann später abgearbeitet. Das ist nicht sinnvoll, aber mein UI Layer funktioniert in weiten Teilen wie ImGUI. Also ich würde meinen Inspektor nicht nutzen können, wenn der ständig crashen würde...




    Für die Stabilisierung:

    Trennt Änderungen und Update


    onChange()

    -> ändert den Wert

    - anstatt nun die UI zu ändern:

    if (luaobj.needsUpdate ~= true) then

    uiwindow:invvokeLater(function()

    luoobj:refresh()

    end)

    luaobj.needsUpdate = true

    end


    function luaobj:refresh()

    self.needsUpdate = false

    -- umbau der Tabelle mit neuen Daten.

    end


    Die Idee dahinter, der Neuaufbau der UI wird ein Frame später ausgeführt. Die invokeLater Funktion ist am Fenster gebunden, also wird nicht zerstört egal was mit den Element passiert. Wenn ein Event für einen Refresh schon da ist, braucht es nicht nochmalig ein neues Refresh.



    Randnotiz: Durch UGs Konsolen UI Update werden beim Verlassen von Steuerelementen ein Change Ereignis ausgelöst.Egal ob man etwas ändert! Deswegen seht ihr bei meinen UIs meistens ein Apply oder Refresh Knopf, damit die UI nicht ständig neu aufgebaut werden muss. Ggf solltet Ihr den Wert überprüfen, ob sich etwas geändert hat.

  • invokeLater ist eine merkwürdige Sache. Ich wollte in meiner Tramblock-GUI darauf zurückgreifen, um das Selbstzerstören von Buttons innerhalb einer durch genau diese Buttons zu löschenden Tabelle zu verhindern. Hat aber nicht funktioniert. Ein Bug seitens UG? Dann habe ich gesehen, dass in der Fahrpläne-Mod als offensichtliches Workaround innerhalb des ersten invokeLater ein weiteres invokeLater ausgeführt wird. Ich habe mir dann, skeptisch, wie ich bin, für meine Zwecke selber eine Lösung geschrieben, die statt der verschachtelten invokeLater-Callbacks über guiUpdate läuft, und zwar über eine Zählfunktion nach dem zweiten Tick. Das funktioniert offensichtlich. Leider habe ich - abgesehen von Dauertests - aber bislang keine Lösung gefunden, um herauszufinden, ob im Speicher irgendwelche "Leichen" verbleiben.


    Da diese Diskussion doch sehr entwicklerspezifisch wird, sollten wir vielleicht zur weiteren Diskussion ein eigenes Thema im Skript-Modding-Bereich aufmachen.


    BTW: Was aber noch zum RAM-Thema gehört, ist ein anderes Problem, das ich mit der eingebauten Screenshot-Funktion habe. Nach mehreren Screenshots friert mir plötzlich das Spiel ein, und ich tippe ebenfalls auf einen RAM-Freigabe-Fehler. Hat das auch schon mal jemand gehabt?

    RE heißt jetzt RRX, es fährt jetzt NX, fällt x-mal aus, sonst ändert sich nix. ;-)

    Edited once, last by WernerK ().

  • Also ich nutze dafür einfach

    Code
    api.gui.util.destroyLater(elem)


    Der TE hat am Code gearbeitet, daher können wir hier ruhig entwicklerspezifisch sein denke ich. Alle Uninteressierten können das Thema ja ignorieren.


    Das Screenshottool erstellt die Bilder mit 10facher Loddistanz (standardmäßig) daher wird wohl sehr kurz viel (ausgelagerter GPU?) Speicher gebraucht. Insbesondere mit den höheren Auflösungen. Das ist normal. Und nur punktuell. Also ganz anders als das langsame Ansteigen.

  • Hier mal ein Beispiel, ich hab es auf die meiner Meinung nach problematischen Bereiche eingedampft.


    https://github.com/MarkMcWire/…pt/timetable_gui.lua#L682


    Nun sieht man hoffentlich was ich hier beanstande.


    ComboBox ist in einer Tabelle in einer Zeile von constraintHeaderTable

    In ComboBox:onIndexChanged gibt es ein call zu clearConstraintWindow -> das löscht alle Rows.


    Sobald die ComboBox geändert wird, sollte TPF2 abstürzen mit Fehlermeldung, das man Element nicht in einem Event löschen soll.


    Wenn das nicht passiert, hast du ein Speicherleck. Das durch UG Funktionen verursacht wird bzw. durch die Verschachtlung nicht direkt offensichtlich ist.


    PS: mehrere invokeLater calls hat man schon mal verschachtelt, um zu Warten bis die Höhe der Elemente errechnet werden, um dann ein UI Element an die Größe der Elemente anzupassen, das macht man halt 2 Frames später...

  • Quote

    Das Screenshottool erstellt die Bilder mit 10facher Loddistanz (standardmäßig) daher wird wohl sehr kurz viel (ausgelagerter GPU?) Speicher gebraucht.

    Was aber alleine nicht das Einfrieren erklärt.

    Quote

    Hier mal ein Beispiel, ich hab es auf die meiner Meinung nach problematischen Bereiche eingedampft.

    Yep, das leuchtet ein. Wäre schon mal eine Sache, die gefixt werden müsste. Aber wahrscheinlich nicht die einzige. Was mich (bin ich der Einzige? :/ ) aber auch von Anfang an genervt hat, dass beim Anklicken einer Linie häufig die Tabelle für eine völlig andere Linie erscheint, und dass zumindest in der 1.3er-Version Eingaben in Textfelder "verschluckt" werden. Keine Ahnung, ob das auf demselben Bug beruht.

    RE heißt jetzt RRX, es fährt jetzt NX, fällt x-mal aus, sonst ändert sich nix. ;-)

BlueBrixx