为什么使用HTML字符串对NSAttributedString的初始调用比后续调用长100多倍?

Ric*_*III 21 cocoa-touch objective-c nsattributedstring ios lldb

我需要在我的iOS应用程序中显示HTML文本.我决定使用内置方法NSAttributedString,initWithData:options:documentAttributes:error:.实际的解析工作非常好,但是,我似乎遇到了一个非常奇怪的错误,如果我附加调试器,它似乎只会表现出来.

第一次调用此方法时,在运行iOS 7.0.4的iPhone 5S上运行时间不到1秒,在iPod Touch第5代上运行约1.5秒.这个怪癖也体现在模拟器上,但由于模拟器的绝对速度,它明显不那么引人注目.

后续呼叫只需要大约10-50毫秒,这比初始呼叫要快得多.

这似乎与输入字符串的缓存无关,因为我在我的"真实"应用程序中使用多个输入字符串对其进行了测试.

但是,当我在没有调试器的情况下运行程序时,它按预期运行,大约需要10-20ms,这是我希望HTML解析所采用的.

以下是相关的代码部分:

-(void) benchmarkMe:(id)sender {
    NSData *data = [testString dataUsingEncoding:NSUTF8StringEncoding];

    NSTimeInterval startTime = [[NSDate date] timeIntervalSinceReferenceDate];

    // So the complier doesn't keep complaining at me.
    __attribute__((unused))
    NSAttributedString *parsed = [[NSAttributedString alloc] initWithData:data
                                                                  options:@{
                                                                        NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                                                        NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)
                                                                    }
                                                       documentAttributes:nil
                                                                    error:nil];

    NSTimeInterval endTime = [[NSDate date] timeIntervalSinceReferenceDate];

    NSString *message = [NSString stringWithFormat:@"Took %lf seconds.", endTime - startTime];

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Benchmark complete!"
                                                        message:message
                                                       delegate:nil
                                              cancelButtonTitle:@"Ok"
                                              otherButtonTitles:nil];
    [alertView show];
}
Run Code Online (Sandbox Code Playgroud)

注意:可以在此处获得演示此错误的完整工作项目:https:
//github.com/richardjrossiii/NSAttributedStringHTMLBug

我疯了吗?这里有什么我想念的吗?当我尝试优化应用程序的性能时,1秒是非常大的时间.

我目前的解决方案是在应用程序启动时解析一个"虚拟"字符串,但这似乎是一个令人难以置信的hacky解决方法.

Joh*_*rug 30

这是一个非常好的问题.事实证明(至少对我而言)无论是否附加调试器,它在第一次调用方法时总是更慢.原因如下:第一次解析HTML属性字符串时,iOS会将整个JavaScriptCore引擎和WebKit加载到内存中.看:

我们第一次运行该方法(在解析字符串之前)只存在3个线程:

截图1

解析字符串后,我们有11个线程:

截图2

现在,下次我们运行该方法时,大多数与Web相关的线程仍然存在:

截图3

这就解释了为什么它第一次变慢而之后很快.

  • @ RichardJ.RossIII我不知道它为什么要加载JSC.我知道它正在加载WebKit,因为解析HTML字符串很昂贵:必须构建,解析和(甚至可能)应用CSS样式的DOM树.因此,即使只解析`<b>粗体</ b>`,也必须启动整个HTML解析机制. (2认同)
  • 这里的人非常有趣.考试不错 (2认同)