Reputation: 8855
In an app that has many different UITableViews, I have found myself frequently using temporary arrays to import the data used to populate the table view, determine number of rows, sections, headers, footers, etc. I'm wondering if, because these array need to be created for each cell in the table over and over if declaring the static so they don't need to be created again will help performance, because right now these arrays are being created in cellForRowAtIndexPath:
, numberOfRowsInSections:
, numberOfSectionsInTableView:,
footerForSection:`. Would declaring this many static arrays (which might contain a decent amount of information, say a couple thousand doubles and a couple hundred strings), in the long run, help or hurt me? I know that a static array stays in memory for the course of the application's life, so will this many static arrays be detrimental? Assuming that this process occurs in 4-5 view controllers across the course of the app, we are talking about 15-20 copies of this array just sitting around. What is my best option here? Thanks
Edit: I am using a singleton which holds the values. The real reason for the temporary arrays is to keep the code clean. I can do something like
dataArray = [[SingletonDataController sharedSingleton] dataArray]
objectAtIndex:CURRENTLY_SELECTED_DATA_INDEX;
then
myTitleString = [dataArray objectAtIndex:keyTitleStringIndexKey];
instead of grouping it all into one unreadable statement like:
myTitleString = [[[[SingletonDataController sharedSingleton] dataArray]
objectAtIndex:CURRENTLY_SELECTED_INDEX] objectAtIndex:keyTitleStringIndexKey];
I have performed some tests of my own, comparing the time it takes to create the table view with/without static initialization. These are the results:
2012-01-29 18:31:57.539 XXXXXXX[711:707] static average: 0.058798
2012-01-29 18:31:57.543 XXXXXXX[711:707] nonstatic average: 0.058395
As you can see, the static initialization is actually slower than the non-static, but only by a few ten-thousandths of a second. This is probably just a product of inaccurate measurement, but the results say enough to convince me that the difference is small enough to dismiss. Mystery solved.
Upvotes: 2
Views: 540
Reputation: 3006
When you do the above you are not actually creating a new array, just grabbing a pointer to that array. You are not copying the actual data.
By keeping your code clean you are losing only the performance of creating memory for a pointer and assigning a pointer a value. So no, you are not losing performance.
The idea of keeping your code clean is much more important than this marginal difference in an extra pointer here and there.
Edit:
I did some testing between the two and as expected, both options perform very similar.
NSMutableArray *data1 = [[NSMutableArray alloc] init];
NSMutableArray *data2 = [[NSMutableArray alloc] init];
NSArray *all = [[NSArray alloc] initWithObjects:data1,data2,nil];
for(int i=0;i<1000;i++)
{
[data1 addObject:[[NSNumber alloc] initWithInt:arc4random()]];
[data2 addObject:[[NSNumber alloc] initWithInt:arc4random()]];
}
double startTime = CACurrentMediaTime();
for(int i=0;i<1000;i++)
{
NSArray *get1 = [all objectAtIndex:0];
NSArray *get2 = [all objectAtIndex:1];
//int get1Index = arc4random() % [get1 count];
//int get2Index = arc4random() % [get2 count];
//NSLog(@"Object at %d: %f", get1Index, [[get1 objectAtIndex:get1Index] doubleValue]);
//NSLog(@"Object at %d: %f", get2Index, [[get2 objectAtIndex:get2Index] doubleValue]);
NSLog(@"Object at %d: %f", i, [[get1 objectAtIndex:i] doubleValue]);
NSLog(@"Object at %d: %f", i, [[get2 objectAtIndex:i] doubleValue]);
}
NSLog(@"Time with temp array:%f", CACurrentMediaTime() - startTime);
startTime = CACurrentMediaTime();
for(int i=0;i<1000;i++)
{
//int get1Index = arc4random() % [[all objectAtIndex:0] count];
//int get2Index = arc4random() % [[all objectAtIndex:1] count];
//NSLog(@"Object at %d: %f", get1Index, [[[all objectAtIndex:0] objectAtIndex:get1Index] doubleValue]);
//NSLog(@"Object at %d: %f", get2Index, [[[all objectAtIndex:1] objectAtIndex:get2Index] doubleValue]);
NSLog(@"Object at %d: %f", i, [[[all objectAtIndex:0] objectAtIndex:i] doubleValue]);
NSLog(@"Object at %d: %f", i, [[[all objectAtIndex:1] objectAtIndex:i] doubleValue]);
}
NSLog(@"Time without temp array:%f", CACurrentMediaTime() - startTime);
//With random access
//2012-01-28 13:44:12.721 test[23164:f803] Time with temp array:0.924193
//2012-01-28 13:44:13.641 test[23164:f803] Time without temp array:0.919250
//2012-01-28 13:44:44.892 test[23191:f803] Time with temp array:0.926337
//2012-01-28 13:44:45.812 test[23191:f803] Time without temp array:0.920447
//With incremental access
//2012-01-28 13:46:43.948 test[23231:f803] Time with temp array:0.935009
//2012-01-28 13:46:44.927 test[23231:f803] Time without temp array:0.978455
//2012-01-28 13:47:40.317 test[23254:f803] Time with temp array:1.173752
//2012-01-28 13:47:41.307 test[23254:f803] Time without temp array:0.989263
The commented out sections are the sections I used for testing random access, for the incremental access I used the current code. Without temp arrays is a fractions quicker, but not noticeably. Not enough to sacrifice readability. I guess that is just the process of writing it out to a variable that slows it down, but, at the same time, having a temp array that is not embedded is much quicker. If you were using the embedded array many times, you would have to do 2 memory accesses instead of 1. So if you are going to use the embedded array several times I imagine the gain would significantly compensate for the loss of using a temp array.
Upvotes: 3