読者です 読者をやめる 読者になる 読者になる

Pragmatic ball boy

iOSを中心にやってる万年球拾いの老害エンジニアメモ

Objective-Cの性能・フットプリント

Objectiv-CではC++と比べて、開発者が楽になるようにいくつか仕組みが入っています。
それを効果的に使うことによって開発の生産性をあげることが可能ですが、よく知らずにつかっていると、性能を劣化させたり、フットプリントが大きくなり無駄に大きいアプリになってしまう恐れがあります。

このような問題が発生しやすいポイントについて記載します。

プロパティ
Objective-Cでは、アクセッサ、いわゆるただ値をインスタンス変数に読み書きするだけのGet/Setメソッドを開発者が記載する手間を省くのを手助けしてくれます。
それがプロパティです。

・プロパティを使わない場合

@interface ClassA : NSObject {
NSArray* array;
}
- (NSArray*)getArray;
- (void)setArray:(NSArray*)inArray;
@end
@implementation ClassA
- (NSArray*)getArray
{
return array;
}
- (void)setArray:(NSArray*)inArray
{
if ( array != inArray ) {
[array release];
array = [inArray retain];
}
}
@end

・プロパティを使った場合

@interface ClassA : NSObject {
    NSArray* array;
}
@property (nonatomic, retain) NSArray* array;
@end
@implementation ClassA
@synthesize array;
@end

という風に見れば一目ですが、プロパティのほうが書くコーディングの量が全然違ってきますし、retainとかcopyとか指定すればそのとおりに実現してくれるので大変楽なので使ったほうがよいです。

しかし、プログラムの書く量が少ないからといって、プログラム自体(実行ファイル)が小さくなるわけではありません
プロパティを使ったとしても実際にコンパイルすると、プロパティを使わない場合と同等の量の実行ファイルが生成されることになります。

逆にGet/Setの片方しか使わない場合は、プロパティを使わないほうが小さいプログラムとなります。
ですので、なんでもかんでもインスタンス変数をプロパティにしてしまうのはプログラムサイズとしてはよくありません。

また、性能面でも少し影響がでる場合があります。

自分のクラスのインスタンス変数にアクセスする場合、以下の2パターンあります。
(arrayはプロパティとして宣言されてる場合です)

・①

array = [NSArray new];
・②

self.array=[NSArray new];


①と②は、C++をやっていた人にはこれは同じに見えますが、これは別物です

①は単純な代入ですが、②はアクセッサをつかって代入をしています。
プロパティでassignだったら結果は同じですが、retainなどをしていると②のほうはretainされます。

ですので、retainするために、②を使うのは正しいですが、単に代入するのに②を使うと①に比べて関数を呼び出す分だけオーバーヘッドが生じます。

ひとつひとつではたいしたオーバーヘッドではありませんが、大きいプログラムとなると小さな積み重ねも大きくなることもあるので、そのことを理解しておく必要はあると思います。

Autorelease
つぎにAutoreleaseです。
AutoreleaseはガベージコレクションGC)みたいで楽なイメージがするかもしれませんが、もちろんGCとは全然違います。

最も気にすべき違いはメモリを開放するタイミングです。

GCは実装によって様々あるので、特に触れませんが、Objective-CのAutoreleaseがメモリを開放するタイミングは、GUIからのイベントを受け取る実行ループでAutoreleaseプールがあるので、一回の実行ループ毎にAutoreleaseプールは開放されます。

つまりひとつのイベント処理が止まるまでAutoreleaseしたメモリは消されずにひたすら溜まりっぱなしということになります。
ですので、ひとつのイベント処理でメモリを大量に使うようなプログラムでAutoreleaseばっかり使っているとメモリ不足になる危険性があります。

これを回避するにはAutoreleaseの使用をできるだけ避けてreleaseで開放するか、独自のAutoreleaseプールを作成して、それを適宜開放するかです。

Autoreleaseは使わざるを得ない場合もあり、完全に回避することは難しいので、両方使うのが望ましいと思います。

-----------------------------------------------------------------------------------------------------------
嘘とか間違いなど指摘していただけると幸いです。

Objective-Cの理解に役立つ本

Objective-Cの言語の本はこれしか読んだことがないので・・。