IrrLime: Draw2DImage Performance

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Catosaur
Posts: 2
Joined: Fri Dec 02, 2016 9:14 pm

IrrLime: Draw2DImage Performance

Post by Catosaur »

i found that x1000 Draw2DImage works slow, and it depends from delay time: more delay - faster, less delay - slower.

Code: Select all

 
using System;
using System.Collections.Generic;
using IrrlichtLime;
using IrrlichtLime.Core;
using IrrlichtLime.Video;
using IrrlichtLime.Scene;
using System.Diagnostics;
 
 
namespace MyIrr2D {
    class Program {
        static IrrlichtDevice d = IrrlichtDevice.CreateDevice(DriverType.Direct3D9,new Dimension2Di(1000,500));
        static VideoDriver v;
        static SceneNode s;
            
        static int i = 0;
        static Texture t;
 
 
        static void Main(string [] args) {
            v = d.VideoDriver;
            s = d.SceneManager.AddSceneNode("SceneNode");
            t = v.GetTexture("T.png");
            d.OnEvent += d_OnEvent;
            
            d.Run();
            while( true ) {
                Draw();
            }
        }
 
 
        static bool d_OnEvent(Event evnt) {
            switch( evnt.Type ) {
            }
            Console.WriteLine( evnt );
            return true;
        }
 
 
        static void Draw() {
            v.ClearBuffers( ClearBufferFlag.Color, Color.OpaqueBlue );
            PF( ()=>{
                v.BeginScene(ClearBufferFlag.Color);
                for( int q = 1; q <= 1000; q++ ) {
                    v.Draw2DImage( t,new Recti(10,20,200,500), new Recti(new Vector2Di(0),t.Size) );
                }
                v.EndScene();
            } );
        }
 
 
        static void PF( Action a ) {
            var w = new Stopwatch();
            w.Start();
                a();
            w.Stop();
            Console.WriteLine( a.Method.Name+": "+w.ElapsedMilliseconds );
            //Console.WriteLine( "GC={0}",GC.GetTotalMemory(false) );
            //GC.Collect();
        }
    }
}
 
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: IrrLime: Draw2DImage Performance

Post by CuteAlien »

Where do you delay anything?
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Catosaur
Posts: 2
Joined: Fri Dec 02, 2016 9:14 pm

Re: IrrLime: Draw2DImage Performance

Post by Catosaur »

here:

Code: Select all

 
            while( device.Run() ) {
                Thread.Sleep( 1000 );
                Draw();
 

Code: Select all

using System;
using System.Collections.Generic;
using IrrlichtLime;
using IrrlichtLime.Core;
using IrrlichtLime.Video;
using IrrlichtLime.Scene;
using System.Diagnostics;
using System.Threading;
 
 
 
namespace IrrUndepTests {
    class Program {
        static IrrlichtDevice device;
        static VideoDriver video;
        static SceneNode scene;
        
        static Texture texture;
 
 
        static void Main(string [] args) {
            device = IrrlichtDevice.CreateDevice(DriverType.Direct3D9,new Dimension2Di(1000,500));;
            video = device.VideoDriver;
            scene = device.SceneManager.AddSceneNode("SceneNode");
            texture = video.GetTexture("T.png");
            device.OnEvent += d_OnEvent;
            
            while( device.Run() ) {
                Thread.Sleep( 1000 );   // <<<<<<< THE DELAY FUNCTION. IF BIG - DRAWS FAST. IF SMALL - DRAWS SLOW
                Draw();
            }
        }
 
 
        static bool d_OnEvent(Event evnt) {
            switch( evnt.Type ) {
            }
            Console.WriteLine( evnt );
            return true;
        }
 
 
        static void Draw() {
            TestPerformance( PFDraw );
        }
 
        static void PFDraw() {
            video.BeginScene(ClearBufferFlag.All, new Color(200, 200, 200));
            for( int q = 1; q <= 1000; q++ ) { 
                video.Draw2DImage( texture,new Recti(10,20,200,500), new Recti(new Vector2Di(0),texture.Size) );
                //video.Draw2DRectangle( new Recti(10,10,300,200), Color.OpaqueRed );
            }
            video.EndScene();
        }
 
 
        static void TestPerformance( Action a ) {
            var w = new Stopwatch();
            w.Start();
                a();
            w.Stop();
            Console.WriteLine( a.Method.Name+": "+w.ElapsedMilliseconds );
            //Console.WriteLine( "GC={0}",GC.GetTotalMemory(false) );
            //GC.Collect();
        }
    }
}
 
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: IrrLime: Draw2DImage Performance

Post by CuteAlien »

Hm, don't really know why that makes a difference.
It sounds in theory like what you would get if the application would still send data to the card on next call. But to my knowledge the endScene() in Irrlicht is blocking, so that shouldn't be the case (it calls endScene and present, which is not optimal really as you could do stuff in between those calls, but anyway - after present the data should be send to the card as far as I know).
In other words - sorry, don't know.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: IrrLime: Draw2DImage Performance

Post by MartinVee »

I myself am coding using C++, and I've never encountered this problem.

Just a quick thought, though. You're creating a whole lot of Color, Recti and Vector2Di each time you're drawing. Basically, each time you call your Draw() function (that is each time you draw a single frame), you have :
  • 1 new StopWatch object
  • 1 new Color object
  • 1000 new Vector2Di objects
  • 2000 new Recti objects
You didn't post your performance numbers, but that means that if your program runs at 60 fps, you're collecting 180120 unused objects each second your program runs. So, I suspect you have a performance issue due to the garbage collector that needs to collect all those unused references all the time, and sleeping the thread helps the garbage collector to do its job. And the more you sleep, the less you're creating useless objects, so your program is faster.

As a quick test, can you modify your program this way (please note that I can't compile it, so you may need to correct my errors, typo and scope problems) :

Code: Select all

 
using System;
using System.Collections.Generic;
using IrrlichtLime;
using IrrlichtLime.Core;
using IrrlichtLime.Video;
using IrrlichtLime.Scene;
using System.Diagnostics;
using System.Threading;
 
namespace IrrUndepTests {
    class Program {
        static IrrlichtDevice device;
        static VideoDriver video;
        static SceneNode scene;
        static Texture texture;
 
        static Color BackColor;
        static Recti DestPos;
        static Recti SourcePos;
 
        static StopWatch swPerf;
 
        static void Main(string [] args) {
            device = IrrlichtDevice.CreateDevice(DriverType.Direct3D9,new Dimension2Di(1000,500));;
            video = device.VideoDriver;
            scene = device.SceneManager.AddSceneNode("SceneNode");
            texture = video.GetTexture("T.png");
            device.OnEvent += d_OnEvent;
            BackColor = new Color(200, 200, 200);
            DestPos = new Recti(10,20,200,500);
            SourcePos = new Recti(new Vector2Di(0),texture.Size);
            swPerf = new StopWatch();
            
            while( device.Run() ) {
                //Thread.Sleep( 1000 );   / / <<<<<<< THE DELAY FUNCTION. IF BIG - DRAWS FAST. IF SMALL - DRAWS SLOW
                Draw();
            }
        }
 
        static bool d_OnEvent(Event evnt) {
            switch( evnt.Type ) {
            }
            Console.WriteLine( evnt );
            return true;
        }
 
        static void Draw() {
            TestPerformance( PFDraw );
        }
 
        static void PFDraw() {
            video.BeginScene(ClearBufferFlag.All, BackColor);
            for( int q = 1; q <= 1000; q++ ) { 
                video.Draw2DImage( texture, DestPos, SourcePos );
            }
            video.EndScene();
        }
 
        static void TestPerformance( Action a ) {
            swPerf.Start();
            a();
            swPerf.Stop();
            Console.WriteLine( a.Method.Name+": "+swPerf.ElapsedMilliseconds );
        }
    }
}
 
Foaly
Posts: 142
Joined: Tue Apr 15, 2014 8:45 am
Location: Germany

Re: IrrLime: Draw2DImage Performance

Post by Foaly »

The garbage collector shouln't be an issue, unless you are using an IrrlichtLime <1.5.
We replaced most of these simple classes by structs, so they now live on the stack and aren't handled by the GC.
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: IrrLime: Draw2DImage Performance

Post by MartinVee »

This is much more complicated than "no, structs are never allocated on heap", as this question on Stack Overflow shows.

I don't pretend to know why the above code is slow. Like I said, I mostly use C++, and I used C# at a job during only two years, so I'm no expert. But as a C++ developper, seeing the "new" keyword called repeatedly to recreate exactly the same object strikkes me as inefficient. Maybe the changes I'm proposing won't impact the performance... but then again, what does the OP have to lose? I'd try it myself, as I'm curious about it, but I'm not setuped to do it.
Post Reply