Hi,
I've had some complaints about my App crashing on startup and not running on older devices. I found out this was an issue of not having enough memory, which surprised me because it only uses 20MB of ram running on windows. I ran the Xcode activity monitor and see my App using 123MB of ram! Same graphics and music, same code. Why the huge difference? I have about 7MB of PNG's loaded as sprites, 1.1MB of wav files as sounds, and 1MB of mp3 loaded as music. Any help in getting my App down to size would be appreciated :)
QuoteI have about 7MB of PNG's loaded as sprites...
It's this - 99% sure.
PNGs are compressed images - when you use them in your app they use as much memory as when uncompressed. Try converting them to bmp to see how much memory they actually take.
Under windows, your images are "sent" to video memory and that's the reason why only 20MB are taken. Windows Task manager doesn't show video memory usage, it only shows how much RAM your app uses.
All your images/textures are stored on graphics card memory, actually.
On iPhone, all RAM is shared between everything (graphics, app, OS, whatever - it all has to fit into 128MB)
I figured it was, but didn't understand the discrepancy. The video ram makes sense. Some of the PNGs I have are fullscreen. If I reduce them by 50%, then display them with zoomsprite at 2x, would memory be reduced any, or would it get used in the zoom function?
Scaling a sprite should save memory as it should only be dealing with the original sprite and placing onto the already defined back buffer. Of course, that comes at the expense of scaling an object, which if you have a lot, could slow things down.
When do you load them? Originally (when only using a PC) I loaded the lot when the program first runs, but now (for iOS) I tend to only load everything for a particular section (eg. main menu) then unload it all after I leave the section. Some sections that I have that are graphic intensive I tend to only load the sprites when they are needed the first time (ie. first time they are seen as somethings might not be seen at all by the user if they don't select an option. eg. a different graphic for a button highlight when pressed).
Cheers
I have a few fullscreen animations (20-30 frames) that I'm sure are the main culprits. If I load on-demand, I don't know that it would be fast enough to keep up with the animation speed. I think I can get by with scaling them, as basically the only thing the game is doing at that time is displaying 1-5 images, then waiting 30-50ms for the next frame.
20-30 frames of full Retina resolution? That would be quite a bit. Try loading in each frame into the same sprite and showing that each time. Might be fine for a simple animation that updates only every 30ms or so. Then only using the one sprite bank to show it, and can unload that when finished with the animation.
Scaling is a good idea though. Something I did (game selector screen) had all the game pictures for a level on one screen and initially I just scaled (stretchsprite or whatever) the main level pictures down on the fly. No worries. However when changed level it was a bit too slow (felt like was slow to react). Instead I just manually made smaller scaled versions myself and loaded them instead for that screen (keeping the large pictures for the actual game). Was much better. In the future I plan to make a routine to load all sprites at the beginning of the program, detect the iOS resolution (always have media for max), then scale down everything accordingly and save out the sprites in the correct sizes for next time. Plus still load and unload them when I need them (not actually load all sprites for the complete game into sprite banks at the beginning). Should work a treat.
Cheers
Yeah I knew it was a lot when the artist had the idea (even the 480x320 we settled on instead of full resolution) but it seemed to work in testing and I didn't have any issues on my development ipod (4th gen, though). When I started getting ipad and 2nd gen ipod users with issues I looked into it (I didn't know Xcode had profiling tools, shows how much I've used it). There's a few things that should be ok with loading on-demand (the full-screen tutorial images, for example, since they only change when the user taps a button). I will do some testing to see whether on-demand loading is fast enough for realtime animation or not. Thanks all for the advice so far :)
If you don't use all the resources at once, consider loading in each level or phase. Try to compress the wavs (16 bit instead 32 bits and mono instead stereo) or use a compressed format like mp3 or ogg. I don't know if this formats works in iPhone.
Yeah the problem is all the resources are pretty much used at once. It's a card game, no levels or anything so there's no real clear breaks for loading or unloading. I'll look into the wav size and how many buffers are being used as well (should only need one).
Yes - the router I've got from my ISP is a bit too security concious :)
Thanks guys, using a bit of both techniques I got memory usage from 123MB down to 50MB :)
Ok, I didn't know how to track memory in XCode until someone mentioned it above. I'm using the "Run with Performance tool option" and looking at "Allocations" and I can see that my memory keeps building in certain places regardless of what I do to clear things. Is this the right tool to use though?
I thought using loadsprite "",spriteid would clear out the memory for a sprite which is what I am using all over the place and my simple PC task manager checks seemed fine (I see now from this thread that it doesn't check video card memory). So using the performance tool in XCode I used this code:-
CLEARSCREEN
ttime=GETTIMERALL()
LOADSPRITE "",padlock
WHILE GETTIMERALL()-ttime<10000
PRINT "1",0,0,kern
SHOWSCREEN
WEND
CLEARSCREEN
ttime=GETTIMERALL()
LOADSPRITE "Media/padlock.png",padlock
WHILE GETTIMERALL()-ttime<10000
PRINT "2",0,0,kern
SHOWSCREEN
WEND
CLEARSCREEN
ttime=GETTIMERALL()
LOADSPRITE "",padlock
WHILE GETTIMERALL()-ttime<10000
PRINT "3",0,0,kern
SHOWSCREEN
WEND
CLEARSCREEN
ttime=GETTIMERALL()
LOADSPRITE "Media/padlock.png",padlock
WHILE GETTIMERALL()-ttime<10000
PRINT "4",0,0,kern
SHOWSCREEN
WEND
Pretty simple really, and I tried it with showing the print lines and then afterwards without (just to make sure the font prints weren't effecting things). Both show the memory keeps being used up more and more. My final test showed a usage of 5.06mb at step 1, which went to 5.34mb at step 2, 5.33mb at step 3 (did it just clear out the pointer and not the actual sprite graphic?), and then 5.61 at step 4. Obviously showing that memory was being taken up even with my use of loadsprite "",padlock.
Am I using the wrong memory clearing command for sprites on the iPhone, or is there a problem with clearing sprites using this method using loadsprite?
Cheers
Just a bit more info. I put this code in:-
ttime=GETTIMERALL()
ttotal=0
tsprite=GENSPRITE()
WHILE 1=1
IF GETTIMERALL()-ttime>100
LOADSPRITE "Media/1-1.png",tsprite
INC ttotal
ttime=GETTIMERALL()
ENDIF
PRINT ttotal,0,0,10
SHOWSCREEN
WEND
And it eventually crashes out. The allocation program shows it steadily using more memory, but frees up a tiny bit each time (seen by peaks on the graph). Note I also added LOADSPRITE "",tsprite directly after the loadsprite command and it makes no difference.
Cheers
[attachment deleted by admin]
I am having similar problems.
Please try loading an unexistent file instead "" (loadsprite "prrt",1)
Hmm, ok I will try that later this weekend. It's a bit worrying though considering my last code above loads the same png into the same sprite bank and it still uses more and memory. Loadsprite, at least on the iPhone looks like it needs better data clearing.
Out if interest after gaining about 40 years and losing the entire afternoon yesterday I finally submitted my first app to the store. Does anyone know if I am allowed to alter my metadata while waiting for review? This was because the description I put was fairly brief thinking it was only for the tester, but am I right in thinking it was actually what is put on the store? Would like to change that. Also I changed my target profiles to be a distribution profile to allow the submit to validate but do I need to change back to development profile to test again on my iPhone? Or should I not touch it and make a separate project for the next update? Slightly confused about this bit.
Cheers
Yes, you can. The thing you can not change is the tags, until you submit a new version.
Just remember to add as tag your company name, son when you have more than one app in the appstore, you can launch from your apps a netwebend for a search of all your programs, so you can set a button "show more programs by me"
Ok ta for that. Will do later. Ooh didn't know about tags. Am using command kitty posted for store apps by me. Will deffo do that in a bit. Thanks a lot!
Cheers
App submission (and everything that goes with it - developing, certification etc. etc. etc. ) causes you to lose hair and/or turn grey overnight!
Good luck :)
What's the app you submitted?
If you're asking me, Tic Tac Blam! (now at version 1.1 after a week of waiting for review)