I'm new to Gideros and evaluating whether I can jump ship from Corona SDK over here. I absolutely love the fast testing turnaround with Gideros player and the fact that you have a standard OOP framework built-in.
One problem I have, which might be a bit of a show-stopper for me is the speed of texture loading. Basically, I have some long animations that can't all fit into a single texture sheet so I need to page the next section in after the first one has finished playing (or better still, WHILE the first one is playing).
Since I can't find any multi-threading capability inside Gideros , I'm looking at loading the next texture in sequence dynamically after the animation of the first one has finished. Now, I hear you say, that will never work and you're right. However, it does work okay on Corona (just about) because the texture loading seems so much faster. For example with a 1024x1024 texture on an iPad 1:
Gideros:
TexturePack.new of 1024x1024 png texture takes 900-120ms
Texture.new of 800x500 png image takes 80ms
Corona
SpriteGrabber load of 1024x1024 png texture takes 50ms
display.newImage of 800x500 png image takes 40ms
You see that there is a lot of difference here, which makes me think that something is in need of optimizing somewhere. Has anyone else experienced this?
Comments
TexturePack.new of 1024x1024 png texture takes 900-1200ms
After your post, I've created a 1024x1024 texture pack with 74 texture regions in it. The size of the resulting .png file is 433kb. On iPad 1, loading times are:
Texture.new -> 220ms
TexturePack.new -> 235ms
And I think 900-1200ms is very high and there is something wrong there.
In Gideros, we're using zlib+libpng to load png files. And in my tests, libpng takes ~%80 of the loading time.
For some time, I was planning to use stb_image.c from http://nothings.org/ which is widely used (in game programming community) and it's a robust image loader. My main aim was to decrease the executable size, but it may decrease the image loading time also.
Now I'll do some tests on Corona.
You need a true multithreading library like Lua Lanes. http://kotisivu.dnainternet.net/askok/bin/lanes/
Seeing as you've mentioned Lanes, however, does that work with Gideros?
I think it's worth to try Lua Lanes as a plugin My first guess is it will crash Gideros. On the other hand, making texture loading thread-safe is not that hard.
On iPad 1, with Corona loading the same texture took 275ms. Is there a possibility that you've done this test on simulator (instead of real iPad 1)?
No I've definitely done the tests on a real iPad 1.
However, now I come to experiment a bit more I find that only the first texture load (of the whole run) is stupidly fast under Corona (??). Subsequent ones are more around the 150-300ms mark. This agrees more with what you saw. Also, I'm afraid I reported the texture size incorrectly. I imagine that the load times will depend on the contents and size of the textures. The three PNG segments I'm using are 550K, 1.1Mb and 750K on disk. The actually sizes that I'm using are not 1024x1024. They are 1000x1800, 2048x2048, 1100x1900. Sorry about that.
This means that running my animation at 15fps (which would *just* about be good enough) I get a small stutter between segments under Corona. I've thought of a way of covering these up by choosing the segment boundaries carefully and other disguises in the game which would mean that I could (barely) get by in Corona.
I've rechecked the Gideros version along similar lines (i.e. by not only reporting the first segment load) and I'm getting better times between 500-800ms but the results are definitely significantly slower. The end result is that the "stutter" between segment is simply not disguisable under Gideros and is consistent with being about 1/3 the speed of the Corona version. So I have these approx times across all three textures:
Gideros (approx times):
TexturePack.new takes 800-1200ms
Corona (approx times)
SpriteGrabber load takes 150-300ms
Also the times I'm seeing under Gideros are a bit all over the place. I think I may be being caught out by the garbage collector. I'm not sure when the Bitmaps and Textures are being freed after the first loop through. Under Corona I am explicitly releasing the objects but there doesn't appear to be this option in Gideros (unless I'm missing something). I really need to put together an example to demonstrate all this but it's a bit tricky as I'll have to manufacture some non-game artwork since I can't publicly expose the real stuff just yet.
I had thought of a plugin solution, perhaps starting a separate thread in a plugin that calls back into Gideos and does the load in the Lua callback (protected by an NSLock). I haven't tried plugins yet so don't know if that would stand a chance of working? I'll take a look at Lua Lanes too since that sounds like a more general solution but it might be a bit beyond me as I stand right now.
Thanks for looking at this and your suggestions so far.
Would it be possible to write a plugin that uses stb_image.c as you suggest but actually fills in a proper Gideos Texture object? Is the format of this set out anywhere?
Unfortunately, I couldn't say anything without images or code. If possible, can you send me the images (maybe with a big watermark on it) and test codes. So that I can test more and try to find the bottleneck.
Currently, embedding is stb_image.c as a plugin is impossible. Because we haven't give access to the internals of rendering engine through plugins.
In Gideros, if a Bitmap and Texture object doesn't have any reference, they will be garbage collected with the next cycle. And we don't call collectgarbage() internally. Also if a texture is still on memory, loading that texture again is very fast and consumes very little memory.
Okay, I've rebuilt my tests with some dummy graphics and created a Gideros project and a Corona project that try do do the same thing. Since the Corona project uses their built-in sprite library (via a module called SpriteGrabber) it operates a little differently from the Gideros version where the animation is "roll your own".
I've reduced the size of each segment to incorporate 50 frames in each, out of a total of 255. Typically, the Corona times are a bit higher than I got before and the Gideros times are a bit lower. I'm not sure why this would be although the original graphics were rather more complex so would take longer to decompress, I guess. The ratio is still about 1.7:1 but I admit that is rather better than the 3:1 ratio I was seeing before.
You can download the two projects here:
http://dl.dropbox.com/u/2242074/GiderosTest.zip
Here are the times for the first run only (to avoid GC and caching issues) of each test:
Corona: 382, 414, 233, 185, 144
Gideros: 648, 658, 333, 311, 328
My feeling is that unless there is some way to speed up the Gideros load times substantially to be able to even beat the Corona ones then I'm going to have to look at some sort of background loading approach.
Author of Learn Lua for iOS Game Development from Apress ( http://www.apress.com/9781430246626 )
Cool Vizify Profile at https://www.vizify.com/oz-apps
@OZApps totally agree. I'll do it.
Sorry, my bad, I did miss some files out. Although only the ones for Corona, I think. I have updated the download so that the missing Corona files are present. You can get it from the same link:
http://dl.dropbox.com/u/2242074/GiderosTest.zip
One other question. Is there a way of forcing a GC in Gideros or explicitly unloading textures in the same way I do in Corona? I noticed with some of my previous tests with larger textures that the app would crash towards the end of the first loop, presumably because the iPad is running out of texture memory because old unreferenced textures are not being GC'd in time.
Does Gideros/Lua using reference counting or a sweeping GC. I presume the latter, but if that is the case there needs to be some way to force a collection or for the GC to respond to a low memory situation. I imagine you already do this but perhaps you are only doing it for low system memory and not low texture memory?
Best regards
I've downloaded the zip file but it seems animatedsprite.lua is wrong. It refers to the file "../../../../../../../../Applications/Gideros Studio/Examples/Graphics/Texture Pack/animatedsprite.lua"
Gideros and Lua uses sweeping GC and therefore handle cyclic references without a problem. If a Texture object is not referenced by any other object, I'll be garbage collected with the next GC cycle, or by explicitly calling collectgarbage() function.
We don't call collectgarbage() internally. But now I'm putting a call to collectgarbage() to the low memory warning function of iOS.
cheers
http://dl.dropbox.com/u/2242074/GiderosTest.zip
Regarding GC. In the meantime, before you've added the collectgarbage() call as a result of the low memory warning, could I add a plugin that just calls lua_gc() explicitly. I assume that will work.
Best regards
Yes you can:
1. Add a gc.cpp to Plugins with this content:
Although your solution is better in the general case, I still think that on occasion it might be helpful to be explicitly force a GC. In the case of my "Bouncy" example code, if I force a GC after each new texture load then the memory use is kept low and the times reported are always correct each time around the loop because there is no caching.
With that in mind, here is my modified version of your GC plugin so in Lua one can use:
I've done a one-pass of optimization to the texture loading functions but the loading times remained same.
Obviously I haven't seen your code or anything - but...
If you have multiple pages of animation, couldn't you just load all the pages at the same time (store a table of page references) and then expand your sprite animation player so that it know's which page the required frame is on and pick that one.
In my experience the devices can hold plenty of full screen images and the texture state change when uploading the texture to the GPU video memory is pretty fast.
Failing that you could always use some kind of custom plugin (something which Corona DOESN'T have) to manage the images yourself at the OpenGL level. ???
Just my $0.02
Jon...
#MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill