objective-c - 如何使用 ARC 优化 Objective-C 单例?

标签 objective-c performance singleton automatic-ref-counting

使用 Objective-C 中单例的标准模式,ARC 仍然会在每次使用单例时自动生成保留和释放调用,即使我们知道该对象永远不会被释放。在性能敏感的代码中,这些 ARC 生成的调用会导致大量的额外开销。有没有办法告诉编译器不要为单例生成保留/释放代码?

就我而言,我正在编写一个性能敏感的日语文本解析器。作为解析的一部分,我经常需要访问汉字字符的 NSCharacterSet,我已在 NSCharacterSet 的类别中定义了该字符集。

+ (id)kanjiCharacterSet
{
    static NSCharacterSet* kanjiCharacterSet = nil;
    static dispatch_once_t onceToken;

    dispatch_once( &onceToken, ^
    {
        NSRange range = { .location = 0x4e00, .length = 0x9faf - 0x4e00 };
        kanjiCharacterSet = [NSCharacterSet characterSetWithRange:range];
    } );

    return kanjiCharacterSet;
}

访问此字符集最常见的地方之一是检查字符串中是否存在汉字字符。此代码位于 NSString 的类别中。

- (BOOL)containsKanji
{
    return [self rangeOfCharacterFromSet:[NSCharacterSet kanjiCharacterSet]].location != NSNotFound;
}

当我通过探查器运行此操作时,[NSString containsKanji] 花费的全部时间中大约 40% 是在保留/释放代码中。至于[NSCharacterSet kanjiCharacterSet],除了我们实际生成字符集的第一个调用之外,每个调用大约有80%的时间花在保留/释放代码上。

如果我在objc_retainobj_releaseobjc_autorelease中设置断点,我可以看到一个retain和一个autorelease被添加到[NSCharacterSet kanjiCharacterSet] 的 return 语句,当收到 [NSCharacterSet kanjiCharacterSet] 返回的值时,在 [NSString containsKanji] 中添加一个保留,当我们从 [NSString containsKanji] 返回时,将添加一个版本。似乎所有这些调用对于单例来说都是不必要的。有没有办法告诉编译器不要生成这些调用?

我找到了一种解决方法,即向 [NSString containsKanji] 添加一个静态变量来存储字符集,但我很想找到一个更通用的解决方案。

最佳答案

在重复调用 kanjiCharacterSet 的方法中,缓存一个副本。显然,只有当性能至关重要时才应该做这种事情。

- (BOOL)containsKanji
{
    static NSCharacterSet* cachedKanji = nil;
    static dispatch_once_t onceToken;

    dispatch_once (&onceToken, ^{
        cachedKanji = [NSCharacterSet kanjiCharacterSet];
    });

    return [self rangeOfCharacterFromSet: cachedKanji].location != NSNotFound;
}

关于objective-c - 如何使用 ARC 优化 Objective-C 单例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21846871/

相关文章:

ios - UILabel 属性文本未更改

iphone - 如何停止 Objective C 中的函数递归?

java - Singleton Factory - 使用 Java 8 实现

java - 面试题: about Java serialization and singletons

c++ - 为什么这个单例类代码工作正常?

iphone - 竞争条件与否?委托(delegate)和多线程

objective-c - 制作第 3 代 iPad 应用程序的注意事项

.net - VS2010 调试/分析时的性能差异

MYSQL使用OR时提高查询性能

c++ - 数组 vector 是否连续?