C# C# Programm sehr langsam

exobros

Ensign
Registriert
Apr. 2011
Beiträge
140
Hey Leute
Ich bin neu bei C#, und hab grad ein bischen mit XNA angefangen.
Ich hab mir selbst eine Klasse als tilemap geschrieben, in der es auch eine Render Methode gibt.
Diese Rendermethode ist komischerweise extrem langsam. Sie funktioniert zwar (alle wird korrekt gerendert)
allerdings seehr langsam. Pro durchlauf ca 400-500 millisekunden.

Hier ist mal der Code

Code:
        public void render(SpriteBatch sb, Rectangle srcRect, Vector2 destPos)
        {
            Stopwatch tm = new Stopwatch();        
// zum Testen wie lange der vorgang dauert
            tm.Restart();                                          
            for (int y = 0; y < srcRect.Height; y++)  
// Eine Reihe nach der anderen wird durchlaufen
            {
                for (int x = 0; x < srcRect.Width; x++)
// Ein Tile nach dem anderen in dieser Reihe wird durchlaufen
                {
                    String texID = textureAtlas[tiles[x+srcRect.X,y+srcRect.Y]]; 
// die ID der Textur des aktuellen Tiles wird abgefragt
                    try
                    {
                        sb.Draw(ResourceManager.getTexture(texID), new Vector2(destPos.X + x * tileSize, destPos.Y + y * tileSize), Color.White); 
//Die Textur wird gerendert
                    }
                    catch (ArgumentNullException) 
// Für den fall das das Tile die ID 0 hat, und somit nichts gerendert werden soll
                    {

                    }
                }
            }
            long abc = tm.ElapsedMilliseconds;  
//Zur Abfrage der Zeit
            long xy = abc;                                  
//Zur einfachen anzeige der Variable im Debugmodus
         }

Ich weiß die 2 for-schleifen in einander multiplizieren sich, allerdings laufen beide jeweils 4 mal durch, d.h. insgesamt wir der code innerhalb der inneren Schleife 16 mal ausgeführt, was eigentlich kein Problem sein sollte.

Habt ihr eine Idee warum das so ewig dauern könnte?
Leigt es vielleicht an dem try-catch block? die ArgumentNullException wird nämlich in diesem fall fast immer geworfen.
 
Zuletzt bearbeitet: (Übersicht)
Klar liegts an den Exceptions. Diese sollten nämlich (wie der Name schon sagt) nur in Ausnahmefällen geworfen werden und nicht die Regel darstellen:
MSDN - Exception-Klasse schrieb:
Das Auslösen und Behandeln einer Ausnahme beansprucht einen beträchtlichen Anteil an Systemressourcen und Ausführungszeit. Ausnahmen sollten nur zum Behandeln von wirklich außergewöhnlichen Bedingungen eingesetzt werden, nicht für die Behandlung von vorhersagbaren Ereignissen oder für die Ablaufsteuerung.

Prüf doch einfach vorher ob die Ojekte die du der Methode übergibst null sind.
 
Zuletzt bearbeitet:
Eine Exception dauert immer ewig zum werfen und ist and der Stelle auch deplaziert. Sie sollte nur verwendet werden, um (fatale) Fehler abzufangen.
 
Es könnte tatsächlich an der Exception liegen. Ich kenne mich mit C# nicht aus, aber in Java z. B. sind Exceptions tendenziell recht langsam. Wenn der ArgumentNull-Fall häufiger auftritt, dann solltest du darauf explizit prüfen und nicht mit try/catch arbeiten.
 
HI!

ja stimmt, exceptions sind langsam und sollten nur in Ausnahmefällen geworfen werden.

nachdem du eh weißt dass die Exception in bestimmten fällen kommt..... warum fragst du nicht darauf ab?
eine IF-Abfrage ist richtig schnell, Exceptionhandling dagegen langsamer als eine Schnecke...

sg
Alex
 
Danke für die antworten.
Bei Java hab ich das immer gemacht, da war das kein Problem ^^
Naja jetzt weiß ich ja was ich machen muss, dankeschön
 
Es ging ja dabei nur drum, das das programm einfach weiterlaufen soll, sollte es da nix zu rendern geben :D
 
hast doch bereits ne Stopwatch deklariert. Lass dir einfach an div. stellen ausgeben wieviel Zeit verloren gegangen ist dann solltest du die stelle schon finden können.

Ansonsten wie bereits gesagt: Exceptions für Ausnahmefälle nutzen.
 
Es kann auch sein, dass nur das Debugging langsam läuft und die Release version ohne Debugger deutlich schneller ist....
 
In Rendermethoden sollte man teure Instanzierungen vermeiden. Versuche irgendwie, die Stopwatch von außen zu übergeben, sodass nur ein Zugriff, aber kein ständiges new erfolgen muss.

Ich hab jetzt keine Ahnung, wie das bei der Stopwatch ist, aber es gehört sowieso nicht in die render-Methode, also raus damit.

Edit:

Ich habs ausprobiert. Es können weder die Exceptions sein, noch die Stopwatch. Beides ist extrem schnell. Mein PC schafft eine 100.000er for-Schleife mit jeweils neuer Stopwatch und 2000 behandelten Exceptions in 0,2 Sekunden.

Möglicherweise ist der ResourceManager.getTexture() Aufruf so teuer.

Code:
        Random r = new Random();

        for (int i = 0; i < 100000; i++)
        {
            try
            {
                Stopwatch stopwatch2 = new Stopwatch();
                stopwatch2.Reset();
                long x = stopwatch2.ElapsedMilliseconds;
                y += x;

                int z = r.Next(3);
                int o = ((int) y) / z;
                y += o;
            }
            catch(DivideByZeroException e) { 
                 excep ++;
            }
        }
Außenrum messe ich noch mit einer Stopwatch, die mir die 0,2 ausgibt. Außerdem rechne ich mit sinnlosen Variablen rum, um Compiler-Optimierungen zu verhindern, die das Ergebnis verfälschen würden. Die excep Variable zeigt mir, dass etwa 33% Exceptions fliegen, funzt also.

Edit2:

Allerdings frage ich mich auch, wie oft deine for-schleifen eigentlich laufen? Ist das eine volle Bildschirmauflösung? Also etwa 2 Millionen mal pro fertiges Frame? Möglicherweise doch die Exceptions...

Kein Plan :D

Mit innerer Stopwatch:
2 Million Durchläufe ohne Exceptions: 0,1 Sekunden
2 Million Durchläufe bei 1% = 20.000 Exceptions: 0,8 Sekunden
2 Million Durchläufe bei 10% = 200.000 Exceptions: 5,5 Sekunden

Ohne innerer Stopwatch:
2 Million Durchläufe ohne Exceptions: 0,02 Sekunden
2 Million Durchläufe bei 1% = 20.000 Exceptions: 0,6 Sekunden
2 Million Durchläufe bei 10% = 200.000 Exceptions: 5,1 Sekunden
 
Zuletzt bearbeitet:
Zurück
Oben