Why does an initial NSAttributedString call using an HTML string take more than 100 times more than subsequent calls?

I needed to display HTML text inside my iOS application. I decided to use the built-in NSAttributedString method, initWithData:options:documentAttributes:error: Actual parsing works just fine, however, it looks like I ran into a very strange error, which, apparently, only appears if I have a debugger.

The first time this method is called, it takes about 1 second and about 1.5 seconds on the 5th generation iPod Touch to run on my iPhone 5S running iOS 7.0.4. The quirk also appears on the simulator, but it is much less noticeable due to the sheer speed of the simulator.

Subsequent calls take about 10-50 ms, which is significantly faster than the initial call.

This is not like caching an input string, as I tested it with multiple input strings in my β€œreal” application.

However, when I run the program without a debugger, it works as expected, about 10-20 ms, which I expect from HTML parsing.

Here is the relevant section of code:

 -(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]; } 

Note A fully working project demonstrating this error can be found here:
https://github.com/richardjrossiii/NSAttributedStringHTMLBug

I've gone crazy? Is something missing here? 1 second is a very large amount of time when I try to optimize my application for performance.

My current solution is to parse the 'dummy' line when the application starts, but this seems like an incredible hacker solution.

+19
ios objective-c cocoa-touch lldb nsattributedstring
Jan 16 '14 at 16:01
source share
1 answer

This is a really good question. It turns out that (at least for me) it is always slower the first time the method is called, regardless of whether the debugger is attached or not. Here's why: the first time you parse an HTML string, iOS loads the entire JavaScriptCore and WebKit engine into memory. Clock:

When you first start the method (before parsing the line), there are only 3 threads: enter image description here

After the string is parsed, we have 11 threads: enter image description here

Now the next time we run this method, most of these network-related threads still exist: enter image description here

This explains why it slows down for the first time and quickly afterwards.

+21
Jan 16 '14 at 16:32
source share



All Articles