Objective-c 中的静态变量和性能

发布于 2024-12-29 18:55:54 字数 1273 浏览 2 评论 0原文

在具有许多不同 UITableView 的应用程序中,我发现自己经常使用临时数组来导入用于填充表视图的数据,确定行数、节数、页眉、页脚等。我想知道是否,因为这些数组如果声明静态,则需要一遍又一遍地为表中的每个单元格创建,因此不需要再次创建它们将有助于提高性能,因为现在这些数组正在 cellForRowAtIndexPath: 中创建, numberOfRowsInSections:,numberOfSectionsInTableView:footerForSection:`。从长远来看,声明这么多静态数组(其中可能包含大量信息,例如几千个双精度数和几百个字符串)对我有帮助还是有害?我知道静态数组在应用程序的整个生命周期中都会保留在内存中,那么这么多静态数组会有害吗?假设这个过程在应用程序的整个过程中发生在 4-5 个视图控制器中,那么我们讨论的是该数组的 15-20 个副本。我在这里最好的选择是什么?谢谢

编辑:我正在使用一个保存值的单例。使用临时数组的真正原因是为了保持代码整洁。我可以做类似的事情

dataArray = [[SingletonDataController sharedSingleton] dataArray] 
    objectAtIndex:CURRENTLY_SELECTED_DATA_INDEX;

myTitleString = [dataArray objectAtIndex:keyTitleStringIndexKey]; 

而不是将其全部分组为一个不可读的语句,例如:

myTitleString = [[[[SingletonDataController sharedSingleton] dataArray] 
    objectAtIndex:CURRENTLY_SELECTED_INDEX] objectAtIndex:keyTitleStringIndexKey];

我自己执行了一些测试,比较了使用/不使用静态初始化创建表视图所需的时间。结果如下:

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

正如您所看到的,静态初始化实际上比非静态初始化,但仅慢了千分之几秒。这可能只是测量不准确的结果,但结果足以让我相信差异小到足以忽略不计。谜团解开了。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风苍溪 2025-01-05 18:55:54

当您执行上述操作时,您实际上并没有创建一个新数组,只是获取指向该数组的指针。您没有复制实际数据。

通过保持代码干净,您只会损失为指针创建内存和为指针分配值的性能。所以不,你不会损失性能。

保持代码整洁的想法比各处额外指针的边际差异重要得多。


编辑:

我在两者之间做了一些测试,正如预期的那样,两个选项的性能非常相似。

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

注释掉的部分是我用于测试随机访问的部分,对于增量访问我使用当前代码。如果没有临时数组,速度会快一点,但并不明显。不足以牺牲可读性。我想这只是将其写入变量的过程,这会减慢速度,但同时,拥有未嵌入的临时数组要快得多。如果您多次使用嵌入式数组,则必须进行 2 次内存访问,而不是 1 次。因此,如果您要多次使用嵌入式数组,我想增益将显着补偿使用临时数组的损失。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文