LAG: Syncing problems in Neko+Cpp Targets

Hello Everybody!

I’m using Haxe for a sort while now and for the most part i’m enjoying it!. I wish to use it to make some 2D games. I am experiencing some problems though :frowning: On Neko and Cpp target - Cpp is my primary target, Neko is for testing. I’m experiencing a lot of lag. It seems that things are not buffered correctly on SDL backend targets. I’ve posted this example code to proof my point. Hopefully someone has a solution for this. This is otherwise a breakpoint for me.

I would ratter use Haxe then something else, but this kind of lag is unacceptable for me. (sorry, I really like haxe though)

Does anyone have a solution? Sometimes it takes a while for the lag to show, but if you keep restarting the program eventually you will have a version that lags.

This code should work out of the box on any new generated OpenFL project of any version. Only Flash does not like me and gives a blank window? :S Obviously I want to know what to do with this code to make it not lag!

package;
/*
 OpenFL program to show lag. It runs great in HTML5 but Neko And CPP targets are laggy.
        You can use any version of OpenFL + Lime, but Flash only shows a empty window :S ?

     	If you start the program either lag is already showing or it may take a while.
     	Keep restarting the program, eventually lag will show. Also dragging the window in
     	MS Windows can introduce lag. HTML5 does not show any of this behaviour.!, So i'm
        guessing that SDL - implementation or SDL itself - is the culprit!

		Please note that, resizing the stage is not implemented in this code, and
     	don't build with -debug! Debug targets can/may allocate new objects for debugging!
*/
import openfl.display.Sprite;
import openfl.geom.Rectangle;
import openfl.display.DisplayObjectContainer;
class Main extends Sprite {
	// you can play around with these, but 200, 300 is heavily tested
	// For windowed mode I use 1280x720
	public static inline var kSize:Int			= 200;
	public static inline var kSpeed:Int			= cast kSize*1.5;
	var amount:Int;
	var yoff:Float;
	var instances:Array<Sprite>;
	var colors:Array<UInt>	= [0xFF0000, 0x00FF00];
	var col:Int=0;
	var current:Int=-1;
	var world:DisplayObjectContainer;
	public function new () {		
		super ();
		world		= new DisplayObjectContainer();
		addChild(world);
		amount		= Std.int(stage.stageWidth / kSize)+2;
		instances	= new Array<Sprite>();
		yoff		= stage.stageHeight-kSize; // No subpixels, both are int.
		for (i in 0...amount) {
			newInstance(++current);
		}
		stage.addEventListener(openfl.events.Event.ENTER_FRAME, onUpdate);
	}
	function createSprite(color:UInt):Sprite {
		var s = new Sprite();
		s.graphics.beginFill(color);
		s.graphics.drawRect(0, 0, kSize, kSize);
		s.graphics.endFill();
		return s;
	}
	function newInstance(column:Int) {
		var s 	= createSprite(colors[col]);
		s.x		= column * kSize; // no subpixels, both are int.
		s.y		= yoff;
		if (++col==colors.length) col=0;
		instances[column]=s;
		world.addChild(s);
	}
	function onUpdate(e:openfl.events.Event) {
		moveWorldByDelta(1.0/60);
		validateBuild();
	}
	function validateBuild() {
		// Just math, no new Garbage() or "bad" + "string" + "concats"
		var c:Int 	= Std.int((-world.x+(stage.stageWidth))/kSize);
		var s:Sprite;
		if (c>current) {
			s = instances[0];
			for (i in 1...amount) { // no iterator!
				instances[i-1] = instances[i];
			}
			// No subpixels (both are int)
			s.x = ++current * kSize;
			instances[amount-1]=s;
		}
	}
	function moveWorldByDelta(delta:Float) {
        // Delta is open for discussion. But i've tried any sane value for it.
        // Dynamic delta's, smoothing deltas, but Fixed Deltas (like this one)
        // Give nice results. Also when in VSync (assuming 60hz), fixed delta's
        // 1/60 should give best results. (don't forget that the caller/drivers can/will also
        // adept their syncs when it fall behind, there no reason to do this yourself.)

       	// some much refered reading: https://gafferongames.com/post/fix_your_timestep/
       	// a suggested variable delta 0.01 or 0.02 makes the rendering really shakky.
        // After applying that he interpolates the alpha, technically he's is just doing a
        // complexed dynamic delta: (current_frame_time-_previous_frame_time), with
        // overhead of potentially calling the physics multiple times instead of once.
       	// also in vsync this kind of methods should not be necessary, just use 1/refreshrate.

		// Lets just say that even if 1/60 is inaccurate, then still the only real effect should
		// be speed, and this should not result in lag!. Lag is created by not being synced correctly
		// with the hardware. HTML5 syncs perfectly, CPP/Neko do not! Double Buffering is probably 
		// not well implemented!

		world.x -= Math.round(kSpeed * delta); // No subpixels!
	}
}

Many thanks in advanced for any help on this matter!

Best regards!

The Neko target is known to be a slow target (unfortunately!)

I would like to look into support for the new “HL” Haxe target, or an HTML5 windowed solution (like Node Webkit?) as a good testing target, but that’s another subject :slight_smile:

I am concerned about that delta time code, I wonder if it handles dropped frames properly. Perhaps try setting your project to <window fps="10" /> and see if it still behaves properly (albeit, a bit jerky due to the low frame rate). If it does not, then there’s a logic issue with handling dropped frames

Using vsync (such as when we target HTML5 using requestAnimationFrame) you can end up getting extra frames. I have a system that will run at 120 FPS on HTML5, so if there are logic issues with getting a different number of frames, extra frames on a system like that will also cause a different kind of trouble

Hi there!
Thanks a lot for your reply.!

Define performance… This code is 100% garbage free and clean. On the render loop it does not introduce any new objects!. It does some really simple arthritics which can be done by any environment with ease. Even the slowest of computer environments/languages will execute this well before 16ms. After execution opengl needs to be updated. If you are writing to a buffer that the display is reading from then you will have lag. And that is exactly what is happening

On moments that the render loop kind of syncs with the hardware then its barely noticeable, but if you startup this code and its way of of sync, then you will have lag.

The performance of Neko should not even be relevant unless you have a very large batch of physic that needs to be done. So unless OpenFL+Lime are very brutal to/on Neko - which i don’t think they are, then Neko itself should not be the problem.

Java is pretty slow as well,but I can post some code based upon LibGDX which does the exact same thing as this code which runs really smooth on my desktop. The language or environment are usally not to blame. Mostly its uneducated programmers that are the real issue on performance.

// Depending on how this is compiled.
trace("this" + "can" + "be" + "very" + "expensive" + "on" + "a" + "render" + "loop");

Its not handeling anything. If a frame drops, then the update is not trigger, so then I will not move for one frame. The lag that is showing up is very constant throughout all frames. (or at least half of them). External frame drops will not occur on this rate.

Also there are very easy ways to detect if you make a list overtime how much frames you are getting suppose to how may your should be getting… I can assure you that this code is getting 60fps. Even if over a period of say 2 seconds one frame is dropped, that this will surly not explain what I’m seeing. A framedrop will give a very small hickup, not a persisnt problem.

Also you can never truly compensate for that. It will be visible no matter how you decide to compensate for it.

This code will run as smooth as butter on HTML5. And for what use will you render 120fps. Normal displays get updated every 60hertz, so half of your frames are just eating CPU/Mem resources.

To be quite honest I’m not that familiar with WebGL’s internals. Perhaps its delegated in a way - by the browser - that It all ways renders in sync. I can assure you that for desktops this is a whole different story. You need to double buffer correctly or get in to syncing problems which will give laggy graphics.

Anyways, what every you do with the delta for FPS will not make up for what i’m seeing.

Anyways,
Thanks for your reply!