【问题标题】:Can objective c calls be optimized using stack variables?可以使用堆栈变量优化目标 c 调用吗?
【发布时间】:2013-05-20 10:44:25
【问题描述】:

我是否遗漏了什么,或者调用 sendData 我真的需要像这样在堆上创建 3 个 NS 对象吗?或者这甚至是在堆上创建的?反正有没有在堆栈上创建它们?这似乎效率低下!

NSData *data = [NSData dataWithBytes:packet->data length:packet->dataLength];
if(!data)
    return -5;
NSString *player = [NSString initWithCString:(char*)peer->data encoding:NSASCIIStringEncoding];
if(!player)
    return -6;
NSArray *to = [NSArray arrayWithObject:player];
if(!to)
    return -7;

NSError *error;
BOOL success = [[GCHelper sharedInstance].match sendData:data toPlayers:to withDataMode:GKMatchSendDataReliable error:&error];
if (!success) {
    printf("Error sending packet %08x %d\n", packet->data, packet->dataLength);
    return -8;
}

我可以这样做吗?

NSData data;
[data dataWithBytes:packet->data length:packet->dataLength];
NSString player;
[player initWithCString:(char*)peer->data encoding:NSASCIIStringEncoding];
NSArray to;
[to arrayWithObject:player];

抱歉我的无知,我精通 C++,但对 Objective-C 很陌生。

【问题讨论】:

  • 正如 CodaFi 指出的那样,您渴望 C++ 的堆栈分配对象(在某些情况下具有优势,但在某些其他情况下也从根本上被破坏,除非标准已得到修复 - 您可以或可以,最终得到带有错误 vtable 的对象,但我离题了)。如果这不是过早的优化,您可以通过在任何类GCHelper.sharedInstance.match 上声明一个方法来解决该问题,该方法直接采用您的char * 等,并从那些没有将它们包装和解包为堆对象的数据包中构造数据包。 HTH。
  • sendData 是一个 GameKit API 调用,是不是不能像你建议的那样声明另一个函数?
  • 不幸的是,如果你调用一个框架,你需要另一个解决方案。写得太长了,我已经添加了答案。

标签: objective-c optimization memory-management stack


【解决方案1】:

我可以这样做吗?

没有。除了 -init 和朋友们没有实际初始化(看看 NSObject.mm,它所做的只是 return self;)这一事实之外,你只是用这些调用传递 nil。 +alloc 仅用于提供独立于实现的分配器功能;碰巧在堆上分配对象的一种。如果您担心 Objective-C 本身的性能,那么您不必使用它。您可以随时回到 C 和 C++,回到您熟悉和喜爱的堆栈分配变量和复杂指针运算领域。 Objective-C 仍然是一种高性能语言,尽管它“效率低下”。

但请记住:虽然 C 和 C++ 是为内存和处理器效率为王的嵌入式系统和任务关键型应用程序设计的,但 Objective-C 旨在运行在相当一致、高性能和(相对)内存不受限制的硬件上。

【讨论】:

  • 所以我可以创建一个 C++ NSData、NSString 和 NSArray 并将它们传递给 sendData?你知道它们的 C++ 变体叫什么吗?
  • 没有 C++ 变体,即使你制作了它们,也很难将它们桥接到 Objective-C 对象。
  • 谢谢。因此,要进行此 sendData 调用,必须进行 6 次内存分配并检查那些失败的? 3 用于对象,1 用于数据,1 用于播放器字符串,1 用于 NSArray 中的元素。抱歉,如果这不是低效的话,我不知道什么是大声笑。更不用说真正做任何事情的唯一分配是数据分配,其他的只是 API 桥接巴拉克。顺便说一句,是的,这是过早的优化,也许它不会有任何区别,(在 3gs 移动 cpu 上?)但是因为我正在学习 Objective-C,所以我想知道是否有更好的方法来做到这一点。
  • @Rasterman 问题是您称语言本身的设计效率低下(而且它肯定与其他语言相比,我不是在争辩),并且没有办法解决这个问题,但是编写更好的语言或获得低级。
  • 在你教育我之前我才知道,所以谢谢你。一个相关的问题是是否需要对 if(!data) if(!player) 等进行分配检查?这些对象是动态分配的,可能无法正确分配?
【解决方案2】:

如果性能是一个问题。正如您在回答我对这个问题的评论时正确指出的那样,不幸的是,您不能在调用框架时添加自己的方法,该方法将您的数据作为 C 指针。但是,您可以在上一级做类似的事情,您可以创建 NSDataNSString 而无需将数据本身复制到堆中:

NSData *data = [NSData dataWithBytesNoCopy:packet->data
                                    length:packet->dataLength
                              freeWhenDone:NO];
if(!data)
   return -5;

NSString *player = [NSString initWithBytesNoCopy:peer->data
                                          length:strlen(peer->data)
                                        encoding:NSASCIIStringEncoding
                                    freeWhenDone:NO];
if(!player)
   return -6;

NSError *error;
BOOL success = [[GCHelper sharedInstance].match sendData:data
                                               toPlayers:@[player] // array expression
                                            withDataMode:GKMatchSendDataReliable
                                                   error:&error];
if (!success)
{
   printf("Error sending packet %08x %d\n", packet->data, packet->dataLength);
   return -8;
}

这仍然将您的数据包装为堆对象,但NSDataNSString 堆对象都不会直接引用您的数据。当然,您必须确保您的数据在需要时保持有效!

注意:如果您正在使用 Objective-C 并且经常需要此功能,那么您可以将上述代码包装为 GKMatch 上的 category - 作为练习:- )

【讨论】:

  • 现在看来它已经到了某个地方,谢谢!但是有一些问题:1)您不认为 sendData 无论如何都会复制提供的数据,因为它必须缓冲数据并发送它,如果是这样,它不会简单地添加引用提供的分配的 NSData 对象并保留它吗? 2)数组表达式不是仍然分配一个NSArray对象并将其放在堆上,它只是一种更简洁的方法吗?
  • 这提供的唯一好处是您的数据不会被复制到堆中。您仍然无法在堆栈上分配对象。
  • @CodaFi - 没错,但这里“唯一”的衡量标准很重要 - 如果 性能是一个问题,删除冗余缓冲区副本可能很重要。
  • @Rasterman (1) 如果数据在返回之前未被sendData 使用,那么您不想使用...NoCopy 堆栈分配的对象(如在 C++ 中)或者你有麻烦了!在这种情况下,您可能想查看将...NoCopyfreeWhenDone:YES 一起使用 - 预计它将释放一个malloc'ed 块(您没有给出结构的起源,所以我不能说这是否会适合)。 (2) 数组表达式仍然分配一个堆对象,只是更简洁。请注意,分配是 Obj-C 通常很便宜,但当然是 YMMV。
猜你喜欢
  • 2011-04-30
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
相关资源
最近更新 更多