1

クラス名とセレクターの組み合わせをキーとしてオブジェクトを格納する辞書があります。ハッシュを計算するために次の関数を使用しています。

+(NSString*) getKeyForClass:(Class) clazz andSelector:(SEL) selector {
    return [NSString stringWithFormat:@"%@_%@",NSStringFromClass(clazz), NSStringFromSelector(selector)];
}

プロファイラーを実行しているときに、この関数が計算のボトルネックであることがわかりました。クラスとセレクターからキーを作成するためのより良い(=より効率的な)方法はありますか?

4

2 に答える 2

3

いくつかの選択肢。

キーとして文字列を使用し続けますが、より速く実行します。

文字列の使用は、実際に必要なものよりも少し重いですが、少なくとも簡単です。

使用-[NSString stringByAppendingString]する方が速くなります。フォーマット文字列の解析は大変な作業です。

return [[NSStringFromClass(clazz) stringByAppendingString:@"_"] stringByAppendingString:NSStringFromSelector(selector)];

NSMutableString中間の文字列を作成する代わりに、単一の文字列を使用する方がよい場合があります。プロファイルして見てください。

NSMutableString* result = [NSStringFromClass(clazz) mutableCopy];
[result appendString:@"_"];
[result appendString:NSStringFromSelector(selector)];
return result;

キーとしてカスタムオブジェクトを使用します。

クラスとセレクターを参照するキーとしてカスタムオブジェクトを作成できます。NSCopying-isEqual:を実装-hashして、辞書のキーとして使用できるようにします。

@interface MyKey : NSObject <NSCopying>
{
    Class _clazz;
    SEL _selector;
}

- (id)initWithClass:(Class)clazz andSelector:(SEL)selector;

@end

@implementation MyKey

- (id)initWithClass:(Class)clazz andSelector:(SEL)selector
{
    if ((self = [super init])) {
        _clazz = clazz;
        _selector = selector;
    }
    return self;
}

- (id)copyWithZone:(NSZone*)zone
{
    return self; // this object is immutable, so no need to actually copy it
}

- (BOOL)isEqual:(id)other
{
    if ([other isKindOfClass:[MyKey class]]) {
        MyKey* otherKey = (MyKey*)other;
        return _clazz == otherKey->_clazz && _selector == otherKey->_selector;
    } else {
        return NO;
    }
}

// Hash combining method from http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html
#define NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger))
#define NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (NSUINT_BIT - howmuch)))

- (NSUInteger)hash
{
    return NSUINTROTATE([_clazz hash], NSUINT_BIT / 2) ^ (NSUInteger)_selector;
}

@end

+ (MyKey*)keyForClass:(Class)clazz andSelector:(SEL)selector
{
    return [[MyKey alloc] initWithClass:clazz andSelector:selector];
}

仲介者を排除する:

キーオブジェクトからクラスとセレクターを引き出す必要がない場合は、上記で計算された、に格納されているハッシュを使用できますNSNumber

// Hash combining method from http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html
#define NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger))
#define NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (NSUINT_BIT - howmuch)))

+ (NSNumber*)keyForClass:(Class)clazz andSelector:(SEL)selector
{
    NSUInteger hash = NSUINTROTATE([clazz hash], NSUINT_BIT / 2) ^ (NSUInteger)selector;
    return [NSNumber numberWithUnsignedInteger:hash];
}
于 2013-01-20T20:16:22.003 に答える
0

SEL■ それ自体がユニークです。NSValueを使用して、それだけをラップできます。

[NSValue valueWithBytes:&selector objCType:@encode(SEL)];
于 2013-01-20T19:59:01.660 に答える