45…50 is really good!
Yeah, it’s 45-50 rendered and I’m updating Corona/physics 60 times a second. Seems to be the best compromise. Especially if your physics system is framerate based, which it is by default. It just kind of irks me that I can’t get this phone I’m testing with to render faster. Especially since I’m easily updating/rendering everything within 16 milliseconds.
Can you send me your binary somehow so I can test it and measure FPS on my Lumia 625?
I don’t know if it’s possible.
>> The main issue in my game is that the physics frame-rate slow downs are getting bigger after time.
Olaf, that definitely sounds like a memory leak. I don’t think the framerate improvements that I’m making will help with that.
I’m not seeing any leaks with the apps I’m running at the moment… or Visual Studio isn’t detecting the ones you are seeing. Would you be willing to send your project to us so that we can try it for ourselves?
Also, I do know that tomorrow’s daily build will contain some memory leak fixes for all platforms. There were some minor memory leaks involving rendering geometry via display.newLine(), newCircle(), newRect(), newRoundedRect(), and newPolygon(). It was a minor leak, but they would accumulate over time if you create/destroy these often. I’ll get a hold of those fixes and include them in our next WP8 build for you guys next week.
Lerg, would you mind waiting until next week?
I don’t a nice means of packaging everything up right now.
Plus, I’ll see about finishing implementing what since it *is* an improvement.
Sure, no hurry.
Joshua,
OK, you were right - I had one particle update enterFrame listener that I didn’t remove before exiting scene. Oops…
Now everything runs fast after several level updates. My bad. There still are frame-rate slow downs, but they don’t increase in time.
Anyway, thanks for your help.
Olaf,
We’ll be sending everyone a new WP8 update today which provides the framerate and timer improvements that you need. It’s a pretty huge improvement and I’d be interested to know how well it works for you. Just note that if you have native XAML UI on top (like a TextBox), then that can cause a huge framerate issue if you’re rendering at 60 FPS. I can’t do much about that because Corona and Microsoft’s UI are heavily competing for the rendering thread’s time. If you frequently display native UI on top (I don’t think you do), then you’ll have to switch to 30 FPS… which by the way is much smoother and improved as well. Kind of a bummer that I can’t make 60 FPS play nice with XAML, but this is the best compromise that I could come up with.
I also had the Win32 functions removed that caused your app to be rejected from the Windows Store. Just note that I haven’t tested uploading it to the Windows Store myself. Not set up for this yet and haven’t had time. So, if you can confirm if this resolves the app rejection issue then that would be great. Thanks!
I’ve also whipped together the following Lua code which you can use to measure the framerate…
local lastEnterFrameTime = nil local durationCollectionSize = 60 local durationCollectionIndex = 1 local durationCollection = {} for index = 1, durationCollectionSize do durationCollection[index] = 0 end local function onEnterFrame(event) local currentTime = system.getTimer() -- If this is the first frame, then fetch the current time and exit out. if (lastEnterFrameTime == nil) then lastEnterFrameTime = currentTime return end -- Store the duration since the last frame. durationCollection[durationCollectionIndex] = currentTime - lastEnterFrameTime lastEnterFrameTime = currentTime -- Do not continue if we have more durations to collection before averaging below. if (durationCollectionIndex \< durationCollectionSize) then durationCollectionIndex = durationCollectionIndex + 1 return end -- Average the collected durations and print it to the log. local averageDuration = 0 for index = 1, durationCollectionSize do averageDuration = averageDuration + durationCollection[index] end averageDuration = averageDuration / durationCollectionSize local averageFps = 1000 / averageDuration print("Average FPS = " .. tostring(averageFps) .. ", Average Duration = " .. tostring(averageDuration)) -- Reset data collection. durationCollectionIndex = 1 end Runtime:addEventListener("enterFrame", onEnterFrame)
The above will print the average framerate once every 60 frames to Visual Studio’s Output panel. Just remember that you don’t want to print() on every frame since that function has a huge performance penalty on WP8. I measures about 3-4 milliseconds per print! But once every 60 times isn’t so bad.
Joshua,
I’ve just tested the new CoronaCard build. It’s sooo much smoother! I could even increase the particles number because I didn’t observe lags when the particles were removed. Once I increased their number - the tiny lags appeared again but I noticed them only because I knew they occured before. Now the lags don’t affect the gameplay at all! Thanks a lot, it’s a great improvement!
Below this post I paste a framerate output I get on my Lumia 625 - nearly 60fps
I have only rate&review native UI popup appearing at the beginning after every 5th game launch, so it doesn’t affect my fps during the gameplay.
Regarding submitting the package to the Windows Store - it has passed the validation now, thanks.
So once you have the native/lua communication done, I’d be able to submit my release candidate to the Q&A Microsoft team with no fear :-) When do you think it might be ready?
Here’s the fps log:
Average FPS = 40.187541862023, Average Duration = 24.883333333333 Average FPS = 50.718512256974, Average Duration = 19.716666666667 Average FPS = 59.820538384845, Average Duration = 16.716666666667 Average FPS = 60.606060606061, Average Duration = 16.5 Average FPS = 59.464816650149, Average Duration = 16.816666666667 Average FPS = 56.232427366448, Average Duration = 17.783333333333 Average FPS = 60.06006006006, Average Duration = 16.65 Average FPS = 60.240963855422, Average Duration = 16.6 Average FPS = 59.94005994006, Average Duration = 16.683333333333 Average FPS = 59.94005994006, Average Duration = 16.683333333333 Average FPS = 57.08848715509, Average Duration = 17.516666666667 Average FPS = 58.42259006816, Average Duration = 17.116666666667 Average FPS = 58.42259006816, Average Duration = 17.116666666667 Average FPS = 60.606060606061, Average Duration = 16.5 Average FPS = 59.52380952381, Average Duration = 16.8 Average FPS = 57.19733079123, Average Duration = 17.483333333333 Average FPS = 60.240963855422, Average Duration = 16.6 Average FPS = 60.180541624875, Average Duration = 16.616666666667 Average FPS = 56.127221702526, Average Duration = 17.816666666667 Average FPS = 54.347826086957, Average Duration = 18.4 Average FPS = 57.526366251198, Average Duration = 17.383333333333 Average FPS = 59.52380952381, Average Duration = 16.8 Average FPS = 60.362173038229, Average Duration = 16.566666666667 Average FPS = 59.701492537313, Average Duration = 16.75 Average FPS = 57.692307692308, Average Duration = 17.333333333333 Average FPS = 59.464816650149, Average Duration = 16.816666666667 Average FPS = 60.362173038229, Average Duration = 16.566666666667 Average FPS = 58.881256133464, Average Duration = 16.983333333333 Average FPS = 59.701492537313, Average Duration = 16.75 Average FPS = 57.034220532319, Average Duration = 17.533333333333 Average FPS = 60.728744939271, Average Duration = 16.466666666667 Average FPS = 59.171597633136, Average Duration = 16.9 Average FPS = 37.974683544304, Average Duration = 26.333333333333 Average FPS = 60.483870967742, Average Duration = 16.533333333333 Average FPS = 57.636887608069, Average Duration = 17.35 Average FPS = 57.859209257473, Average Duration = 17.283333333333 Average FPS = 58.939096267191, Average Duration = 16.966666666667 Average FPS = 59.582919563059, Average Duration = 16.783333333333 Average FPS = 60.301507537688, Average Duration = 16.583333333333 Average FPS = 57.859209257473, Average Duration = 17.283333333333 Average FPS = 59.820538384845, Average Duration = 16.716666666667 Average FPS = 60.120240480962, Average Duration = 16.633333333333 Average FPS = 58.881256133464, Average Duration = 16.983333333333
That’s great! Thank you so much for your patience and for taking the time to post your test results.
I didn’t mean for it to take this long (achieving 60 FPS was quite challenging), but I think the performance improvements were worth it in the end.
Regarding native UI framerate issues, I’ve only noticed serious framerate issues when giving a TextBox the keyboard focus or when pinch zooming a WebBrowser control. Interestingly enough, giving a text field within a WebBrowser control keyboard focus does not cause a framerate issue. It’s really hit-or-miss. But I suppose it’s not that big of deal since you probably wouldn’t display native UI during gameplay and only in static screens within Corona.
I’m currently working on the native/Lua bridge API now. I expect to have it done by the end of this week (worst case). Hopefully sooner. Also, I still plan on looking into the “applicationSuspend” issue that you’ve mentioned with the Start/Home key.
Yes, the extra time and your effort were definitely worth it! Thanks
Olaf,
I just tested for the “applicationSuspend” issue you mentioned before where pressing the Start/Home button and then pressing Back doesn’t always cause a suspend event to get raised. It’s always working for me. I also tried pressing the Power button and Search button too.
Are you still able to reproduce this issue?
I’m kind of baffled as to what might be causing this. The only thing that I can think of is that something crashed during the suspend, which Visual Studio’s debugger should be able to catch.
Edit:
I’m testing this with our “Hardware\SystemEvent” sample project that is included with the Corona Simulator.
OK, I’ve tested it again and it seems to be working fine now. I’m getting an applicationSuspend event every time I hit Start button.
Maybe the issue was caused by some bug from the previous build? Anyway, it’s working now. Thanks.
The text updating in this beta generally very laggy - when I have a static score screen where a timer that counts up the score points earned in a round, the text updating works VERY slow, even though the timer iteration timespan is set to 25 ms:
local gameRoundScore = 125 local tmr tmr = timer.performWithDelay(25, function(e) score.text = score + e.count) if e.count == gameRoundScore then timer.cancel(tmr); tmr = nil; end end,gameRoundScore);
So probably the text updating is mainly causing the lags, but as I said - even if I remove the text update call and leave some other parameter updates - the lags on collision events are back.
o.
Text bitmap generation is extremely expensive on WP8. Far more expensive than the iOS and Android. We’ve already optimized it the best that we can and it’s not going to get any better unfortunately.
The only way to work-around this is to use bitmap fonts, which is what Microsoft recommends and is what most AAA game studios use when displaying text that are updated frequently. The reason bitmap fonts are faster is because all of the characters are pre-loaded in a single spritesheet and text is then formed/layed-out based on those already loaded characters. There are 3rd party bitmap font tools that can help you with this such as TextCandy, bmGlyph, Font-Manager, etc. In fact, using them will improve the text update performance on Android as well.
That said, the bitmap font technique is only useful for text that’s under your control. That is, you can guarantee that the characters you are using exist in your spritesheet. The display.newText() function should be used for text that’s out of your control, such as text taken from the Internet like Facebook, Twitter, etc… and this will work fine in this case because you’re not going to be updating this text on every frame.
Oh and one other performance gotcha is with the print() function. The print() function on WP8 is extremely slow when you’re running the app under the Visual Studio debugger. This is an issue that all native WP8 developers face as well because the only means (that I’m aware of) to make log output appear in Visual Studio is via the native OutpuDebugString() function, which is famously slow in the Windows development world. If you are not running your app under the Visual Studio debugger, then the performance is fine, but then you’ll have no means of acquiring the printed log output.
Joshua,
Thanks for the tips, I’ll research these bitmap fonts and will remove all the print() calls. I was wondering how to have the output to Visual Studio’s console as well, because now I can see only the “thread terminated with code XXX” stuff.
You can see your print() output via Visual Studio’s “Output” panel, but only if you set up your application’s “Debugger Type” for native. You can do so as follows:
-
Right click on your application project.
-
Select “Properties” from the popup menu.
-
Select the “Debug” tab on the left.
-
Go to the drop-down box under “Debugger Type\UI Task” and select “Native Only”.
-
Run your application in debug mode.
Yeah, the above wasn’t super obvious to me either when I started doing native WP8 development. Later, I’ll look into seeing if it’s possible to output to either Managed or Native debug modes, as long as it doesn’t cause too much of a performance penalty.
Also, a simple means of getting rid of print() support in your app might be to override the print() function in Lua. How about something like this?
-- Have the print() function do nothing on WP8. if (system.getInfo("platformName") == "WinPhone") then print = function() end end
Sounds cool, thanks for the guide!