How to create singleton class of multiple textures in SpriteKit - objective-c

I have around 30-40 texture atlas that need to be pre loaded in an SKScene, How do I create a singleton class for all of them, and call them and preload them at once. Each texture is around 4096*2048 pixels.

Before you start wasting your time, I would propose that you do some math.
A single image 4096*2048 with 32bit pixel format RGBA8888 costs you 32Mb of RAM.
If you want to load 40 of these in your memory you'll end up with 1.2GB
An iPhone 6 Plus only has 1GB of RAM - and you can't use all of it.

Related

Is there any way to allocate more RAM in VB.NET?

I started working on a game recently, and I already coded the 'Resource-Loading-Procedur', which loads all textures, sounds, etc. into the memory. It works perfectly fine with the current 10 to 15 files, but after testing with many more files I got an OutOfMemoryException, because the program can only use 2GB RAM max.
I did a little workaround by opening every file in a FileStream and storing these FileStreams in a list, but this will cause Ingame-Loading to be slower because I have to load every single texture which is being used.
I would appreciate any answers!
Regards,
Mika.
Well, It is not possible to allocate memory in VB.NET.
The default is 2048MB of memory to allocate.
If you want to allocate memory in C# Use:
malloc(16384)
This code will allocate 16MB in memory

UIImage Memory Problems

In my app I am returned from an API the urls of images, which I want to display in the app. This is all well and good, except I started to notice that when I am given, and load, very high-res images my app memory usage spikes 200+mb, often causing it to crash, which is unacceptable.
In one particular example, I am given an image that is of the dimensions 8100*5400 pixels. When the app loaded this image it crashed.
While I first thought the problem was a memory leak I created, but after doing some research, it seems like an unavoidable issue related to the size of the image -- since the image is 43,740,000 pixels and each pixel uses 4 bytes, the memory usage of the image will be a minimum of 174,960,000 bytes, or 174.96 megabytes.
The problem is i cannot control the size of the images sent by the api - they may be any resolution, possibly even larger. Obviously a UIImage will not work for my purposes.
Is there any other way I can display an image with a potentially massive resolution without causing app-crashing memory usage?
Instead of downloading the image as data into memory, which will crash your app, download it as data to disk, which will not.
You can then use the Image I/O framework to load a smaller version of the image which won't take up so much memory.
(Note that you should never attempt to display an image larger than the actual display size that you need, since that's a massive waste of memory. So, even if you can't help downloading the large image, you can at least load and display a version that is the actual much smaller size you need.)

CoreImage very high memory usage

When working with CIImage my memory jumps quite drastically by 50MB-60MB when creating the CIIMage and then my program crashes when I'm trying to create the UIImage result.
CIImage *image = [CIImage imageWithData:data]; // +50MB memory increase (data is jpeg data)
It doesn't happen all the time but it happens more frequently for larger images (3264x2448) and while the app is in background mode.
It leads to frequent crashes. Any ideas?
Core Image has severe limits on image size. iOS 8 lifts those limits to a very large extent; if you're on an earlier system, don't do that (i.e. confine yourself to smaller images). In iOS 7 and before, the GPU is available only for images less than 4K in size, which is very small indeed.
Moreover, use of core image in the background is severely limited, because, after all, how could your app dare to try to reach into the GPU, a small and busy place, from the background, when some foreground app may be using it? You are forced into using the CPU (though again, to some extent this restriction is lifted in iOS 8).
In all probability, therefore, your issues are partly memory related (you're trying to use core image for an image that's too big) and partly threading related (if you're using the CPU, you need to make sure you're on a background thread, because this is going to take a LOOOOONG time and the watchdog will kill you dead if you hang up the main thread).
Another thing to consider is how you're managing memory yourself. You haven't shown any relevant code so it's hard to say, but it may be that you are hanging on to data you don't need. You should show your code, and ideally you should analyze your app with Instruments so you know exactly where the problem lies.
For example, the only line of code you cite is
CIImage *image = [CIImage imageWithData:data]
This suggests you are holding the data in memory. That's totally unnecessary. If you play your cards right, you can get the CIImage straight from the image file on disk and create the output straight to disk without occupying any extra memory. If you are generating large memory just because you formed a CIImage, you might be doing it wrong (a CIImage is just a pointer, not a bitmap); the only moment where any memory is needed is the final rendering, where the bitmap is formed, and you can use ImageIO to get that out to disk without holding it in memory.

recommended limit for memory management in Cocos2d?

is there a recommended limit for the images in Cocos2d, whether there are too big and take too much memory? Are there some rules, in dimensions or in Kb, to avoid slowing the game down? (for the background image, or the graphics of my characters (even if i use a batch node)?)
Thanks for your answer
First of all, memory usage has very, very, very little to do with performance. You can fill up the entire memory with textures, the game won't care. It's when you render them where there will be a difference. And then it only matters how much of the screen area you're filling with textures, how heavily they're overlayed, batched, rotated, scaled, shaded and alpha-blended. Those are the main factors in texture rendering performance. Memory usage plays a very insignificant role.
You may be interested in the cocos2d sprite-batch performance test I did and the general cocos2d performance analysis. Both come with test projects.
As for the maximum texture sizes have a look at the table from my Learn Cocos2D book:
Note that iPhone and iPhone 3G devices have a 24 MB texture memory limit. 3rd generation (iPhone 3GS) and newer devices don't have that limit anymore. Also keep in mind that while a device may have 256 MB of memory installed, significantly less memory will be available for use by apps.
For example, on the iPad (1st gen) it is recommended not to use more than 100 MB of memory, with a maximum available memory peaking at around 125 MB and memory warning starting to show as early as around 80-90 MB memory usage.
With iOS 5.1 Apple also increased the maximum texture size of the iPad 2. The safest and most commonly usable texture size is 2048x2048 for Retina textures, and 1024x1024 for standard resolution textures.
Not in the table are iPod touch devices because they're practically identical to the iPhone models of the same generation, but not as easily identifiable. For example the iPod touch 3rd generation includes devices with 8, 16 and 32GB of flash memory, but the 8GB model is actually 2nd generation hardware.
The dimensional size of images and textures depends on the device you are supporting. Older devices supported small layers, I think 2048x2048 in size. I don't think such limitation exists on current devices.
For large images, you definitely want to use batch nodes as they have been tested to demonstrate the largest performance gain when dealing with large images. Though it is a good idea to use them for as much as possible in general.
As for how much you can load, it really depends on the device. The new iPad has 1 GB of memory and is designed to have much more available memory for large images. A first-gen iPad has 1/4 this amount of memory, and in my experience I start to see an app crash when it gets around 100 MB of memory used (as confirmed using Instruments).
The trick is to use only as much memory as you need for the current app's operation, then release it when you move to a new scene or new set of images/sprites/textures. You could for example have very large tiled textures where only the tiles nearest the viewport are loaded into memory. You could technically have an infinite sized view that stretches forever if you remove from memory those parts of the view that are not visible onscreen.
And of course when dealing with lots of resources, make sure your app delegate responds appropriately to its memory warnings.
As per my knowledge.. A batch node of size 1024x1024 takes around 4 MB of space which is only texture memory.. And an application has maximum limit of 24 MB. So game slows down as you reach this 24 MB space and crashes after that. To avoid slowness I used maximum of 4 Batch Nodes at one time i.e.16 MB. Rest 8 MB was left for variables and other data. Before using more batch node I used to clean memory and remove unused batch nodes.. I don't know about memory limit in 4s but in case of iPhone 4 this was what I learnt.
Using this logic in mind I used to run my game smoothly.

MFMailComposeViewController uses too much memory

When I try to send images as attachements(summar size ~4mb) by using MFMailCompose, activity monitor says, what 100(+-2)mb of memory is used. After sending or cancelling memory is freeing ~20 megabytes, but what happened to the remaining 80 megabytes if shared item with images is deallocated?
Thanks!:)
An image's file size and the amount of memory it consumes when displayed are two completely different things.
Images such as JPEGs and PNGs are compressed. When they are drawn to the screen they are uncompressed.
A quick rule of thumb to figure out how much memory an image will consume when displayed is
memory consumed = (width * height) * 4
Example, a image that is 2 KB on disk, but is 62 x 52 pixels will actually consume 12,896 bytes or 12 KB. I imagine an image that is 4 MB on disk will consume a lot more than 4 MBs.
The problem is that MFMailComposer displays the images in it's compose view when you add them as attachments and as a result they are decompressed, consuming memory. So your 4 MBs of images actually consume a lot more than you think they do.
Perhaps try sending only one image at a time. You also need to be conscious that you're releasing the images and the MFMailComposeViewController when you're done with them, or that would surely be the source of the leak.
Also be aware of how you initially load your images. UIImage's imageNamed: method actually caches images. Cached images are only purged in low memory situations, so they can hang around for a while if you're not hitting the limits.
Finally, you've noted that you're seeing the memory consumption in Instruments, but have you actually verified that it is actually a problem? Are you experiencing app crashes due to low memory when testing your app while it is not connected to Instruments or the debugger?
No body is perfect - and that goes for Apple too. There have been documented cases in the past where Apple's frameworks have shown memory leaks (UIImage's caching leaked in iOS 2.x), but I wouldn't be so quick to blame the frameworks when you notice a spike in memory consumption. If the leaks instrument is not showing any leaks, and the analyser isn't showing any issues, the likeliest scenario is that it's just simply memory consumption and not a leak.
Its important to remember that iOS devices don't have gigabytes of RAM like computers do. You need to be conservative with the memory that you use. If that means not sending XX MBs of images at the same time, then that's the way it has to be.