What is advantage of using arrayWithCapacity than using array? - iphone

It is not necessary to specify array size when creating array, right?
Then, why is arrayWithCapacity necessary?
And if I set the size of array smaller than actually needed, is it OK?

arrayWithCapacity is an optimization - it is not necessary. If you know the number of elements ahead of time, the system can allocate storage in one system call and in one chunk of memory. Otherwise, the system has to resize the array later as you add more elements and that tends to be slow, requiring additional allocations and possibly copying data from the old buffer to the new buffer.

array creates an empty array (and allocs memory when you add an object) while arrayWithCapacity creates an array with enough memory allocated to hold those objects, but you can always expand it when needed.

Related

Are recently accessed Realm objects kept in memory?

Suppose I fetch a list of Realm objects and access all the data from the results (causing the data to be loaded into memory). Next, with the reference to the list of objects still around, I fetch one of those objects directly by its primary key. Am I correct to assume that, in this case, the object will be returned without having to hit the disk? What if I no longer had a reference to that original list of results? Might it still be in memory?
Just curious to understand how objects are cached internally by Realm, so I don't unnecessarily try to optimize things in my code (e.g. holding onto objects that I think I'll use again soon) if it's not needed.
Realm memory-maps the file, and only accesses it when you actually read the properties on objects. This means that recent-accessed data will still be in memory until the OS has to discard it to free up that RAM for something else, and there is no difference in terms of disk i/o from obtaining a new object from Realm and holding on to an existing object.

Memory Efficient and Speedy iPhone/Android Dictionary Storage/Access

Im having trouble with memory on older generation iPhones (ipod touch 1st gen, 2nd gen e.t.c). This is due to the amount of memory allocated when I load and store a 170k word dictionary.
This is the code (very simple):
string[] words = dictionaryRef.text.Split("\n"[0]);
_words = new List<string>(words);
This allocates on start around 12mb of storage, iphone has around 43mb I think. So that + textures + sounds + the OS it tends to break.
Speed wise, accessing using a binary search is fine. But its storing it in memory more efficiently (and loading it more efficiently).
The text.Split appears to take up alot of heap memory.
Any advice?
You can't count too much on how much memory these pre-3.0 devices have available on startup. 43 MB is rather optimistic. Is your app just checking to see if the word is in the list or not? You might want to roll your own hash table instead of using a binary search. I'd search some of the literature and stack overflow to look for efficient ways to store a large dictionary with the particular word sizes you have. A google search on hash table might give you a better implementation.
Use SQLite. It will use less memory and be faster. Create an index on your words column and voila, you have binary search, without having the whole dictionary loaded in memory.
First if dictionaryRef.text is a string (and it looks so) then you already got something huge being allocated (2 bytes per characters). Check this it might well account for a large (near half) amount of the total memory being allocated. You should think about caching this (the database idea is a good one, but a file could do to then use File.ReadAllLines in future execution).
Next you can try do a bit better than Mono's Split method. It creates a List and then turn it into an array (calling ToList) at the end - which you end up creating a new List from. Since your requirement (only '/n') is fairly basic I suggest you to roll your own Split method (or copy/paste/reduce the one from Mono) and avoid the temporary memory allocations.
In any case take a lot of (memory) measurements since allocations, even more for strings, often occurs where we don't look ;-)
I would have to agree with Morningstar that using a SQLite backend for your word storage sounds like the best solution to what you are trying to do.
However, if you insist on using a word list, here's a suggestion:
It looks to me like dictionaryRef.text is constructed by reading a text file in its entirety (File.ReadAllText() or some such).
Instead of doing that, why not use TextReader.ReadLine() to read 1 word at a time from the file into a List, thus avoiding the need to use String.Split() and using tons of temporary storage space?
Ultimately that seems to be what you want anyway... and ReadLine() will "split" on \n for you.

Can a block of memory be partially freed?

I'm writing a very memory intensive program that will have dozens of malloc'd arrays. When the app receives a low memory warning, I want to dump the lower half of each of these arrays. Is there any way to do this?
I need some way that I can preserve half of the memory in each array. Obviously, if the app has low memory, I can't allocate a smaller array, copy half of my data into it, and then free the old array. Is there any function that can free a block of memory starting at pointer A and ending at pointer B or something like that?
Realloc() can return the trailing portion of the memory of a malloc back to the allocation pool, but can't return it to the OS.
Realloc() also won't help with memory fragmentation, which is likely a problem in a low-memory situation.
If they are NSMutableArrays, you can replace the objects in the lower end with a single instance of [NSNull null], thereby releasing all of those objects.
NSNull Class Reference

Objective C iPhone performance issue

Ok guys I am developing an iPhone app I have a Model class which follows a Singleton design pattern.
Now I have an NSArray in it which is initialized to around some 1000 NSStrings in the init method.
Now I need to use this data in some view controller. so I import Model.h, I create an array of NSString objects in view controller & set the data to it. But now the problem is that now I have 2000 NSStrings currently allocated, which I believe is not a good thing on iPhone due to memory considerations.
releasing model object wont help because I've overrided release method to release nothing according to the pattern & I cannot change the design now because now a lot of code works on the assumption of model being a singleton.
& in future maybe the initial NSStrings may grow to 2000 or even more & then I'll have 4000 NSStrings allocated at one time ....
I am a little confused on how to go about it any suggestions
A few thousand strings take barely any memory at all. 4000 strings would take a couple of hundred kB, depending on length. (Rule of thumb here is string length + 20).
Edit: Probably more like string length + 30 or 40, actually; I'm not certain how much overhead NSArray adds.
Reedit: Given the information from the below question; you could probably get away with loading a few hundred strings at the most; just around the area you are browsing; basically turning your SQLite access into a sparse array that caches a few strings around the search area. Not, of course, that I believe it to be necessary; if the strings are location names they probably have an average byte size of 20-30 bytes; giving a (very) rough estimate of 300k of memory to keep them all in memory permanently, greatly reducing access time and giving a better user experience. The iPhone doesn't have a lot of RAM; but you can afford, at the very least a fair few megabytes; 300k isn't going to break your back.
It's difficult to offer specific suggestions without knowing more about your implementation--where do your strings come from? In general, the best performance optimization for this sort of situation is lazy loading. Here are some examples of ways to have a reduced memory footprint with different technologies if you have a table view:
Core Data: Not usually a problem, since objects are faulted and fetched automatically.
SQLite: Again, not usually a problem--you query the database every time you need a particular value (such as when a table view cell needs to display a string).
Internet: Start a request (usually via a thread) when the table view cell is visible.
XML: Trickier, but use SAX (event)-based parsing to find values instead of DOM parsing (which loads the entire document to memory).
That being said, if you made design decisions that are difficult to reverse, it may not be possible to significantly reduce your memory footprint without major refactoring.
EDIT: As per other answers, it's probably not worrying about, but if you were to optimize for memory, you would not load all the SQLite values at application launch, but instead fetch each value from SQLite in cellForRowAtIndexPath. These sorts of problems are made much easier using Core Data--I would highly recommend using Core Data instead of straight SQLite (although it sounds as if you might be too far into development to switch at this point).
If your Model object really is a singleton, then all you need to do is get your strings from the model object in the view controller and use them. I don't see why you would get duplicates.
With NSString, as long as the strings are immutable, the copy method should just retain the object to copy and return the same object to you. Also, if your strings are constant strings i.e. defined like so:
NSString* foo = #"bar";
they are actually part of the executable and will take up no extra RAM at run time.

Memory leak tool tells me zero leaks but memory footprint keeps rising

I'm running through some memory profiling for my application in SDK 3.2 and I used the 'Leak' profiler to find all my memory leaks and I plugged all of them up. This is a scrollView navigationController application where there are tiles and you click a tile which goes to a new view of tiles and so on, I can go many levels deep and come all the way back to the top and the 'Leak' profiler says everything is cool.
However, if I watch the memory footprint in the 'ObjectAlloc' profiler the memory footprint goes up and up as I go deeper (which seems reasonable) but as I back out of the views the memory footprint doesn't go down as I'd expect.
I know this is a vague description of the app but I can't exactly post a gillion lines of code :) Also it should be noted I'm using coreData to store image data as I go so the database is growing in size as more nodes are chosen, dunno if/when that is released from memory.
What gives?
This sounds like it could be one of a few things:
Memory not given back to OS after deallocation. This is a common design for C runtimes. When you do an allocation the C runtime allocates more memory for its use and returns a chunk of it for you to use. When you do a free the C runtime simply marks it as deallocated but doesn't return it back to the OS. Thus if the Leak Tool is reading OS level statistics rather than C runtime statistics the Leak tool will fail to report a corresponding decrease in memory usage.
Misleading values reported by Leak Tool Memory. The Leak Tool could be looking at different values than the C runtime and is reporting values that will cause you concern even though nothing is wrong (just as people try to use Task Manager in Windows for detecting leaks and get very confused with the results because it is a very poor tool indeed for that job).
Fragmentation. It is possible that your application is suffering from memory fragmentation. That is when you allocate, then deallocate then allocate, subsequent attempted allocations are larger than the "holes" left by deallocations. When this happens you fragment the memory space, leaving unusable holes, preventing large contiguous memory blocks and forcing the usage of more and more memory space until you run out of memory. This is a pathological condition and the fix is typically application specific.
I think the first of these three suggestions is most likely what is happening.
Depending on how you have your object graph constructed in Core Data, it's memory use can grow unexpectedly large.
A common mistake is to store objects inside a complex and often faulted (loaded into memory) entity. This cause the big blob to be loaded/remain in memory whenever any other part of the entity is referenced. As you object graph grows, it eats more and more memory unless you actively delete objects and then save the graph.
For example: You have an person entity with lots of text info e.g. name, address, etc as well as a large photo. If you make the photo an attribute of the person entity it will be in memory anytime the person entity is faulted. If you get the attribute name, then the photo attribute is in memory as well.
To avoid this, blobs should be in their own entity and then linked to other entities in relationships. Since relationship objects are not faulted until they are called directly they can remain out of memory until needed.
Just because there are no refcount-based leaks, doesn't mean that you're not stuffing something off in a Dictionary "cache" and forgetting about it; those won't show up as leaks because there are valid references to it (the dict is still valid, and so are the refs to all its children). You also need to look for valid, yet unnecessary refs to objects.
The easiest way is to just let it run for too long, then sort object counts by type and see who has a gigantic number - then, track down the reference graph (might be hard in Obj-C?). If Instruments doesn't do this directly, you can definitely write a DTrace script to do so.
To reiterate:
char *str1 = malloc(1000);
char *str2 = malloc(1000);
.
.
.
char *str1000 = malloc(1000);
is not a memory leak, but
char *str1 = malloc(1000);
char *str1 = malloc(1000); //Note! No free(str1) in between!
is a memory leak
The information on core data memory management is good info and technically the answer by Arthur Kalliokoski is a good answer re: the difference between a leek and object allocation. My particular problem here is related to an apparently known bug with setBackgroundImage on a button in the simulator, it creates a memory 'leak' in that it doesn't release ever release the memory for the UIImage.
You can have a continuously growing program without necessarily leaking memory. Suppose you read words from the input and store them in dynamically allocated blocks of memory in a linked list. As you read more words, the list keeps growing, but all the memory is still reachable via the list, so there is no memory leak.