Strange thing in memory management for ios development - objective-c

I have a app in my ipod.
1.Open the app, and look at the memory Instruments (Activity monitor), it's 8.95M
2.click a button, it will add a UIImageView with a large image to the screen, the memory is 17.8M now.
3.Remove the UIImageView from screen, and wait a second, the memory is 9.09M now.
I am sure the UIImageView is released after it removed from screen. That's very simple code.
So when it removed, the status of the app should as the same as before add the UIImageView add to the screen, am I right? But why the memory is 9.09M rather than 8.95M? If you add a more complex View to the screen, the difference is more obvious.

This is normal. It's due to a "lazy grow, lazy shrink" algorithm. What that means is that you have a data structure that can be sized for small numbers of items or large numbers of items. The sizing for small numbers of items uses very little memory but isn't efficient when handling large numbers of items. The sizing for large numbers is very efficient for managing large collections of things, but uses more memory to index the objects.
A "lazy grow, lazy shrink" algorithm tries to avoid the cost of resizing a structure's index by only growing the index if it's much too small and only shrinking it if it's much too big. For example, a typical algorithm might grow the index only if its ideal size is at least three times bigger than it is and shrink it only if it's more than three times its ideal size. This is also needed to prevent large numbers of resize operations if an application rapidly allocates and frees collections of resources -- you want the index size to be a bit 'sticky'.
When you open the large object and consume GUI objects, you make the index much too small, and it grows. But when you close the large object, you make the index only a bit too big, so it doesn't shrink.
If the device comes under memory pressure, the index will shrink. If the application continues to reduce its use of UI resources, the index will shrink. If the application uses more UI resources, the index will not need to grow again quite as soon.
A good analogy might be stacks of paper on your desk. If you have 30 papers you might need to find, you might keep them in 4 stacks. But if you have 5,000 papers, 4 stacks will make searching tedious. You'll need more stacks in that case. So when the number of papers gets too big for 4 stacks, you need to re-index into a greater number of stacks. But then when the number gets small, you won't bother to constantly re-index until you have way too many stacks, because searching is still pretty fast.
When you're done handling all those papers, your desk has a few extra stacks. That saves it from re-indexing the next time it needs to handle a lot of papers.

Related

How to reduce DrawCount in UE4 project? any optimizing professional?

I have a big project to optimize a lot of buildings, trees, and assets. I have a very high BasePass, PrePass, ShadowDepth, and Translucency. See the Image ScreenShot
Any Advice?
Ryzen 7 4800H + RTX 2060 + 16GB RAM
If we're going to reduce draw calls, we're talking about making the engine render fewer objects at once with fewer materials.
Your go to methods for this are:
-Setting up HLOD's to combine distant meshes
https://docs.unrealengine.com/4.26/en-US/BuildingWorlds/HLOD/Overview/
-Setting up HISM's/ISM's (As long as you are using DirectX 12 and not 11. With 11 it will do this by itself). Remember to only do this on objects that are beside each other or the problem can get worse.
https://www.unrealengine.com/marketplace/en-US/product/instance-tool
-Reducing the number of material slots on meshes that don't need so many or combining small meshes with similar materials. Actor merging can be great for this, just be careful of going overboard because it can make light baking & lightmap memory usage a pain.
https://docs.unrealengine.com/4.26/en-US/Basics/Actors/Merging/
-Reducing the max draw distance on some of your smaller meshes that are close to the ground. You can find this in the mesh's rendering settings.
Any of these things would reduce draw calls, just be careful with it. Too much optimization by any one method can always make the problem worse by creating bottlenecks elsewhere. When we're reducing draw calls we're also risking slowing down occlusion calculation times or potentially creating a memory bandwidth bottleneck.
Once you get that draw thread time down the next thing I'd go onto is looking at reducing the number of movable lights, objects casting dynamic shadows, and translucent objects casting dynamic shadows. Those are some common culprits of other optimization issues.

Efficient way to handle large runtime-generated tile maps?

I am coding a 2 dimensional, tile based (orthogonal tiles) iPhone game. All levels are procedurally generated when the app is first played, and then persist until the user wants a new map. Maps are rather large, being 1000 tiles in both width and height, and the terrain is destructible. At the moment it is rather similar to Terraria, but that will change.
To hold map/tile information I am currently using several 2 dimensional c style arrays. This works well, but I am concerned as to the amount of memory this takes up, as the arrays are all defined as short array[1000][1000], which takes up (1000 * 1000 * sizeof(short)) bytes of space.
This is not particularly desirable when the iPhone doesn't have an incredibly large amount of memory to work with, especially when the user is multitasking. The main problem is that there is no way that I can use a specific tile map format such as .tmx, because all the levels are procedurally generated. Performance could also be an issue, because if a tile is destroyed at index(x, y), then I need to change the data in that index. I have also thought about writing tile map data to a text file, but I think there would be difficulties or performance issues when accessing or changing data.
Keeping all this in mind, what would be an efficient and fast way to handle my tile data?
My gut feeling on this is Core Data structured such that each tile element has relationships to the tiles around it. There's some non-trivial overhead here, but the advantage is that you can release tiles that aren't onscreen from memory and fault them back when you need them. As you move in a direction, you can query for the tiles in that direction, and you can fairly cheaply dump memory when you're in the background. This would get rid of the "several" 2D arrays and move all the data into a single object. In principle, the grid could be infinite in size this way, since everything is by relationship rather than coordinate.
You could similarly approach the problem using SQLite, querying for rows and columns in a given range. You might mark the objects as NSDiscardableContent and put them in an NSCache, which could dramatically improve memory performance. You could still generate an effectively-infinite grid as long as you allow coordinates to be both positive and negative.

Best cache size for iOS apps

I'm currently developing an application that loads lots of images from the internet and saves them locally (I'm using SDURLCache). However, old images have get removed from the disk again so I was wondering what the best cache size is.
The advantage of a big cache is obviously that more images get saved which leads to better UX.
The disadvantage is that images need a lot of space and the user will run out of disk space faster. The size I am thinking of is 20MB. It seems so big to me though so I'm asking you what you're opinion is.
The best way to decide on an appropriate cache size is to test. Run the app under Instruments to measure both performance and battery usage. Keep increasing the cache size until you can't discern a difference in performance. That's the largest size you'd need, at least under the test conditions. Once you've established that size, reduce the size until performance is just barely acceptable to determine the smallest acceptable size.
The right size is somewhere between those two sizes, depending on what you think is important. If you can't determine a right size, then either pick a size or add a slider to the app's settings to let the user decide. (I'd avoid making it user-adjustable if you can -- users shouldn't have to think about such things.)
Considering that the smallest iDevices have 8GB of storage, I don't think a 20MB cache is too big, especially if it significantly improves the performance of the app. Also, keep in mind the huge advantage a network cache can have for battery life, since network usage is very expensive in battery time.
Determining the ideal size however is hard without some more information. How often is the same picture accessed? How large is each picture (i.e. how many pictures can 20MB hold). How often will images need to be removed from the cache to add new ones?
If you are constantly changing the images in the cache, it could actually have an adverse effect on the battery life due to the increased disk usage.

Trying to work out some leaks for iPad game

I have a slight problem where when the user plays my game for more than 20 minutes or so it begins to slow quite considerably. However I have been trying to work through the issues pretty hard as of late but still no luck. I have tried the leaks instrument and I now have that squared away, but I read at "bbum's weblog" about using the Allocations Instrument and taking heap shots. But i dont quite understand what i am looking at, could some one give me a hand with this?
My game involves users selecting words. I took a heap shot after each word was selected, but i am not too sure how exactly to read this. Is the heap Growth column what is currently running or is it was has been added to what is currenlly running?
And what is the # Persistent?
Also why is the # Persistent jump so much? Could that be my memory problem?
Thanks for all the help!
The heap growth column represents all of the allocations in that iteration that did not exist prior to that iteration but continue to exist in all subsequent iterations.
I.e. Heapshot 4 shows a 10.27KB permanent growth in the size of your heap.
If you were to take an additional Heapshot and any of the objects in any of the previous iterations were deallocated for whatever reason, the corresponding iteration's heapshot would decrease in size.
In this case, the heapshot data is not going to be terribly useful. Sure; you can dive in an d look at the various objects sticking around, but you don't have a consistent pattern across each iteration.
I wrote considerably more about this in a weblog post.
If it's slowing down, why not try CPU profiling instead? Unless you're
getting memory warnings, what makes you think it's a leak?
Tim's comment is correct in that you should be focusing on CPU usage. However, it is quite effective to assume that an app is slowing down because of increased algorithmic cost associated with a growing working set. I.e. if there are more objects in memory, and those objects are still in use, then it takes more time to muck with 'em.
That isn't the case here; your heap isn't growing that significantly and, thus, it sounds like you have a pure algorithmic issue if your app is truly slowing down.
Does your game save files to NSUserDefaults or to an any arrays. If so as the game is played and more and more stuff is added to the array it would take longer to loop through it hence gradually slowing down the game.

Per frame optimization for large datasets

Summary
New to iPhone programming, I'm having trouble picking the right optimization strategy to filter a set of view components in a scrollview with huge content. In what area would my app gain the most performance?
Introduction
My current iPad app-in-progress let's users explore fairly large binary tree structures. The trees contain between 30 to 900 nodes, and when drawing inside a scrollview (with limited zoom) it looks like this.
The nodes' contents are stored in a SQLite backed Core Data model. It's a binary tree and if a node has children, there are always exactly two. The x and y positions are part of the model, as are the dimensions of the node connections, shown as dotted lines.
Optimization
Only about 50 nodes fit the screen at any given time. With the largest trees containing up to 900 nodes, it's not possible to put everything in a scrollview controlled and zooming UIView, that's a recipe for crashes. So I have to do per frame filtering of the nodes.
And that's where my troubles start. I don't have the experience to make a well founded decision between the possible filtering options, and in addition I probably don't know about that really fast special magic buried deep in Objective-C or Cocoa Touch. Because the backing store is close to 200 MB in size (some 90.000 nodes in hundreds of trees), it's very time consuming to test every single tree on the iPad device. Which is why I'd like to ask you guys for advice.
For all my attempts I'm putting a filter method in the scrollViewDidScroll: and scrollViewDidZoom:. I'm also blocking the main thread with the filter, because I can't show the content without the nodes anyway. But maybe someone has an idea in that area?
Because all the positioning is present in the Core Data model, I might use NSFetchRequest to do the filtering. Is that really fast though? I have the idea it's not a very optimized method.
From what I've tried, the faulted managed objects seem to fit in memory at once, but it might be tricky for the larger trees once their contents start firing faults. Is it a good idea to loop over the NSSet of nodes and see what items should be on screen?
Are there other tricks to gain performance? Would you see ways where I could use multi threading to get the display set faster, even though the model's context was created on the main thread?
Thanks for your advice,
EP.
Ironically your binary tree could be divided using Binary Space Partitioning done in 2D so rendering will be very fast performant and a number of check close to minimum necessary.