@Ilija:あなたがそれを手放したと言って投稿した場合、あなたはまだそれを手放していません。;)コメントを明確にできるかどうか見てみましょう:
-(NSString *) album
{
return self->album;
}
-(NSDictionary *) albumAndArtist
{
return @{ @"album":self.album, @"artist":self.artist };
}
上記のalbum
方法は、Objective-Cコンパイラが自動的に生成するものです。*このalbumAndArtist
方法は、元の質問に対する私の回答で提案したものです。ここで、Clangにこれら2つのメソッドをC(clang -rewrite-objc test.m -o test.cc
)に下げるように依頼すると、次のようになります。
static NSDictionary * _I_iTunesTrack_albumAndArtist_albumAndArtist(iTunesTrack * self, SEL _cmd) {
return ((NSDictionary *(*)(id, SEL, const id *, const id *, NSUInteger))(void *)
objc_msgSend)(objc_getClass("NSDictionary"), sel_registerName("dictionaryWithObjects:forKeys:count:"),
(const id *)__NSContainer_literal(2U, ((NSString *(*)(id, SEL))(void *)objc_msgSend)
((id)self, sel_registerName("album")), ((NSString *(*)(id, SEL))(void *)objc_msgSend)
((id)self, sel_registerName("artist"))).arr, (const id *)__NSContainer_literal(2U,
(NSString *)&__NSConstantStringImpl_test_m_0, (NSString *)&__NSConstantStringImpl_test_m_1).arr, 2U);
}
または、人間の言葉で言えば、
-(NSDictionary *) albumAndArtist
{
id album = objc_msgSend(self, sel_registerName("album"));
id artist = objc_msgSend(self, sel_registerName("artist"));
id *values = calloc(2, sizeof(id)); values[0] = album; values[1] = artist;
id *keys = calloc(2, sizeof(id)); keys[0] = @"album"; keys[1] = @"artist";
Class dict_class = objc_getClass("NSDictionary");
id result = objc_msgSend(dict_class, sel_registerName("dictionaryWithObjects:forKeys:count:"), values, keys, 2);
free(values); free(keys);
return result;
}
それをチェックしてください:3sel_registerName
秒、1秒objc_getClass
、3objc_msgSend
秒、2calloc
秒、および2free
秒。これは、コンパイラで生成されたalbum
メソッドと比較すると、かなり非効率的です。
技術的には、コンパイラによって生成されるalbum
メソッドは次のようになります。
-(NSString *) album
{
return objc_getProperty(self, _cmd,
__OFFSETOFIVAR__(struct iTunesTrack, album), /*atomic*/ YES);
}
しかし、それは元々がとして宣言されていなかったからnonatomic
です。の意味については、ここobjc_getProperty
を参照してください; しかし、基本的には、以前よりも高速です。)objc_msgSend
そのため、余分な作業が行われているため、明らかに、albumAndArtist
よりもはるかに遅くなります。album
しかし—あなたは尋ねます—もし私たちがそのすべての仕事を取り除き、ただ戻ったらどうなるself.album
でしょうか?さて、生成されたコードは、コンパイラがalbum
ゲッター用に生成したものよりもまだ毛深いです:
-(NSString *) albumAndArtist_stripped_down
{
// return self.album;
return objc_msgSend(self, sel_registerName("album"));
}
プログラムがを呼び出すとmyTrack.album
、プログラムはメソッドobjc_msgSend
を呼び出す必要があることを理解するために1回呼び出しalbum
、次にその内部album
でを呼び出しますobjc_getProperty
。それは2つの呼び出しです。(数えると3つselector_registerName("album")
。)
プログラムがを呼び出すとmyTrack.albumAndArtist_stripped_down
、 1回呼び出してメソッドobjc_msgSend
を呼び出す必要があることを確認し、次に2回目の呼び出しを行ってから、を呼び出します。それは3つの呼び出しです。(数えると5つ。)albumAndArtist_stripped_down
objc_msgSend
objc_getProperty
selector_registerName
albumAndArtist_stripped_down
したがって、それ自体の約2倍の速度(または5/3の速度)にする必要があることは私には理にかなっていalbum
ます。
オリジナルalbumAndArtist
の場合、関数呼び出しを数えるだけで、約5倍遅くなると思いますが、少なくとも3つのメモリ割り当てを行っているため、album
もちろんそれよりもはるかに遅くなります。一方、album
何もしていません。はそれ自体が複雑なアルゴリズムであるため、メモリの割り当てとクリーンアップは非常にコストがかかります。malloc
これで問題が解決することを願っています。:)