Performance During Fast-Forward

Started by namida, February 13, 2023, 01:08:14 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

namida

Edit Simon: I've split this off Fork: SuperLemmix.




QuoteI'd probably want to try and find a way to make it so it's the same speed regardless of what computer you run it on, and at this point I have no clue how this would even be approached. "if Superlemming=true, enable fast-forward" is relatively simple, whereas dealing with frame rates directly I can imagine will be much more difficult.

NeoLemmix sets a frame rate cap and runs as fast as it can subject to that cap. If the hardware can't manage the full fast forward speed, it'll just run as fast as it can. In extreme cases (slow hardware and/or large levels or with a lot of objects), it might not even manage the 17FPS of normal playback - again, in such a case it'll just run as fast as it can. Superlemming mode, back when it existed, just altered the frame rate caps.

Unless you can find a way to replicate the exact physics (or something you deem close enough and bug-free enough, if you're okay with breaking exact physics) with more efficient code, the only way you're getting around that is by frameskipping (ie: not actually rendering every frame if the hardware can't keep up).
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

WillLem

Apologies for the double-post, wanted to reply to this separately.

Quote from: namida on February 13, 2023, 01:08:14 AM
NeoLemmix sets a frame rate cap and runs as fast as it can subject to that cap ... Superlemming mode, back when it existed, just altered the frame rate caps.

I take it that, in the case of large levels and slow computers, the speed difference from increasing the cap would still be subject to performance capability? So, there wouldn't be much point in activating the mode on a large level, for instance.

I've noticed that SuperLemmini and Lix always have the same fast-forward speed (and, in fact, both offer multiple speeds) regardless of level size, and this doesn't seem to be visibly subject to computer performance as much as NeoLemmix's fast-forward. Is this to do with the code/program size/language being used (for instance, Java uses its own "environment" which I imagine means all resources are devoted to the Java app whilst it's active) or is it something else?

Dullstar

#2
I'd have to look at the code to be sure, but most likely Lix and SuperLemmini are coded to be able to handle the draw calls not keeping up with the speed of physics updates (of course, if the physics updates can't keep up then there's no choice but to slow down but I'm going to assume that NL's physics speed is probably at least reasonably comparable to Lix's -- you could check if the physics are the culprit just by seeing how long the mass replay checker takes, particularly on areas that suffer from slowdown, because it just runs the physics as quickly as it possibly can without drawing anything).




Older games often noticeably slow down, but most modern games will try to keep the gameplay moving at the same speed and just draws it less often, so for example the amount of distance something moves in one second will be the same whether the game is running at 144 FPS some really fancy setup, or struggling to maintain 30 FPS. It's not a property of the language, though some libraries/engines/etc. will make it easier than others.

Java's environment has a different purpose than what you're thinking: its purpose is so that if you want to port Java applications to a new platform, instead of everyone porting individual applications, someone just ports the runtime environment. It also definitely doesn't cause all resources to be devoted to the app while it's running: if it did, you wouldn't be able to run anything else alongside a Java app. That said, it doesn't seem to be particularly good at sharing, but not in a way that appears to confer any noticeable benefits to performance. If you haven't noticed, I actually really hate the Java runtime environment. A good runtime environment is an implementation detail that stays behind the scenes where you never have to think about it, ESPECIALLY if you're just the end user, but intensive Java applications (such as modded Minecraft) can fail that pretty easily, what with all the minimum/maximum memory allocation nonsense. Most programs just figure it out as long as you've got the bare minimum, but Java needs some hand-holding, apparently.

Simon

#3
Language/ecosystem shouldn't make a huge difference here. I'd wager that anything you see comes from choice of graphics library or from our algorithms.

Years ago, we blamed some of the performance problems on Graphics32. It's not designed for real-time games. But I don't know details. It's not necessarily lack of VRAM support; you should be able to get reasonable performance even with RAM bitmaps, e.g., what I had with Allegro 4 in 2006-2014.

I've tried to measure. NL runs smoothly in Wine with fast-forward even on bigger maps (Awesome level) with 50 lemmings. It makes no difference having lemmings on the screen or offscreen. I can't measure FPS easily in NL; I've merely eyeballed from the clock in the panel. It just looks like 60 fps during fast-forward.

There is a moderate performance dent during screen-edge scrolling in NL, strange, but let's ignore it. I'm not focusing on lemming details during scrolling, and I usually scroll during pause, anyway.

Lix in Wine also runs at full 60 fps, and you can make Lix show FPS in the panel with a user option in the graphics options section.

Lix (both in Wine and native on Linux) seems faster with the recomputation during framestepping backwards, but that again is a special use case that we can ignore for now. Rollback performance comes mainly from the caching algorithm, only secondly from the speed of the libraries. NL caches every 170 physics updates (10 seconds) and forgets more rarely, Lix caches every 10 physics updates and forgets more aggressively. The upshot is that Lix might even be less performant than NL to rollback when you've played for 20 in-game minutes and then want to roll back 2-3 minutes. But I haven't tested this. ("Better performance" here is hard to define anyway: Average performance? Fewer lag spikes? Smaller maximum lag spike? Lix will have considerable lag spikes here and then will rollback fast for a while.)

Anyway. I can't see clearly bad performance in Wine (neither in NL nor in Lix), even though I too remember dents. I'd have to test on your machine.

And I haven't tested extreme maps. It's possible that I'll see performance differences even on my machine with 1,000 lemmings on an even bigger map.

-- Simon

EricLang

I noticed, when refactoring my Lemmix, that during "hyperspeed" (no graphics should be done until the target frame) there was *still* some drawing done, which slowed down performance. This was noticable when rewinding one frame in pause mode (which basically replays the whole game until one frame before the current frame).

"Fast forward" should be able to do at least 50 FPS on modern computers. Graphics32 is quite fast, but faster is possible when handcrafting everything yourself :)
This is not Incredibly difficult: throw away Graphics32, use a home grown pixelbuffer and directly blit to screen using the windows StretchDiBits function. This function does not need a handle.
The only real drawback here is that you have no font-rendering available.

Then also I noticed that the update speed is probably not optimal in Lemmix, and maybe also in NeoLemmix. I presume the Application.OnIdle event is still used, which is not the fastest possible. Ideally you want to call Game.Update() as often as possible.

In my new project I use a faster method and also always render to screen, which gives framerates between 150 and 1000. And my computer is not the newest one.
Knowing that Delphi is a little bit faster than C# this should be possible in NeoLemmix too.
But also there could be some other bottleneck. I saw there was quite some stuff added to the mechanics.