DTCoreTextFontDescriptor Performance #19

Closed
myell0w opened this Issue Apr 5, 2011 · 19 comments

Projects

None yet

4 participants

@myell0w
myell0w commented Apr 5, 2011
  • (CTFontRef)newMatchingFont :

// fast font creation
matchingFont = CTFontCreateWithFontDescriptor(fontDesc, pointSize, NULL);

This line takes forever, just did a quick Performance-Test with Instruments and this line took ~ 4.5 seconds on my iPhone 4.

@odrobnik
Collaborator
odrobnik commented Apr 5, 2011

No idea what you are talking about. I did extensive testing with instruments.

@odrobnik odrobnik closed this Apr 5, 2011
@myell0w
myell0w commented Apr 5, 2011
  DTAttributedTextView *textView = [[[DTAttributedTextView alloc] initWithFrame:CGRectMake(10, 25, contentView.frameWidth - 20, 200)] autorelease];
  NSData *data = [html dataUsingEncoding:NSUTF8StringEncoding];
  // Create attributed string from HTML
   NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         @"Helvetica", DTDefaultFontFamily,
                         @"gray",DTDefaultTextColor,
                         @"gray", DTDefaultLinkColor, nil];

NSAttributedString *string = [[[NSAttributedString alloc] initWithHTML:data options:options documentAttributes:NULL] autorelease];

Where html is a really short html-string.
Results in:

https://skitch.com/m.yellow/r21h9/instruments
https://skitch.com/m.yellow/r21h5/instruments

@odrobnik
Collaborator
odrobnik commented Apr 5, 2011

what HTML?

On Apr 5, 2011, at 11:20 PM, myell0w wrote:

DTAttributedTextView *textView = [[[DTAttributedTextView alloc] initWithFrame:CGRectMake(10, 25, contentView.frameWidth - 20, 200)] autorelease];
NSData *data = [html dataUsingEncoding:NSUTF8StringEncoding];
// Create attributed string from HTML
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
@"Helvetica", DTDefaultFontFamily,
@"gray",DTDefaultTextColor,
@"gray", DTDefaultLinkColor, nil];

NSAttributedString *string = [[[NSAttributedString alloc] initWithHTML:data options:options documentAttributes:NULL] autorelease];

Where html is a really short html-string.
Results in:

https://skitch.com/m.yellow/r21h9/instruments
https://skitch.com/m.yellow/r21h5/instruments

Reply to this email directly or view it on GitHub:
https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML/issues/19#comment_961278

@myell0w
myell0w commented Apr 5, 2011

Depends on the site I'm parsing, but the sample I tested it with is:

Gerne verwöhnen wir Sie mit unseren feinen Kaffeespezialitäten



wie Melange, Caffee Latte, großer Brauner,...



sowie Süßspeisen und Snacks.





Auf Ihr kommen freut sich das Team!

Am 05.04.2011 um 23:26 schrieb Cocoanetics:

what HTML?

On Apr 5, 2011, at 11:20 PM, myell0w wrote:

DTAttributedTextView *textView = [[[DTAttributedTextView alloc] initWithFrame:CGRectMake(10, 25, contentView.frameWidth - 20, 200)] autorelease];
NSData *data = [html dataUsingEncoding:NSUTF8StringEncoding];
// Create attributed string from HTML
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
@"Helvetica", DTDefaultFontFamily,
@"gray",DTDefaultTextColor,
@"gray", DTDefaultLinkColor, nil];

NSAttributedString *string = [[[NSAttributedString alloc] initWithHTML:data options:options documentAttributes:NULL] autorelease];

Where html is a really short html-string.
Results in:

https://skitch.com/m.yellow/r21h9/instruments
https://skitch.com/m.yellow/r21h5/instruments

Reply to this email directly or view it on GitHub:
https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML/issues/19#comment_961278

Reply to this email directly or view it on GitHub:
https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML/issues/19#comment_961314

@odrobnik
Collaborator
odrobnik commented Apr 5, 2011

Cannot duplicate your result. I copied this HTML into the CurrentTest.html. I copied your options to DemoTextViewController.m. No performance issue. newMatchingFont takes only liek 16.ms, viewDidAppear 40 ms for this file.

@stuartcarnie

I too am trying to figure this out, as it is taking several seconds in my app too. I'll post more when I find what the cause is.

@odrobnik
Collaborator

Are you maybe using a custom font? Those take some time to load from disk.

On Apr 28, 2011, at 6:49 AM, scarnie wrote:

I too am trying to figure this out, as it is taking several seconds in my app too. I'll post more when I find what the cause is.

Reply to this email directly or view it on GitHub:
https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML/issues/19#comment_1068207

@stuartcarnie

No, Helvetica. Here is a reproducible sample:

NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
[attributes setObject:@"Helvetica" forKey:(id)kCTFontFamilyNameAttribute];
[attributes setObject:[NSNumber numberWithFloat:36.0f] forKey:(id)kCTFontSizeAttribute];
CTFontDescriptorRef fontDesc = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)attributes);
CTFontRef matchingFont = CTFontCreateWithFontDescriptor(fontDesc, 36.0f, NULL);
CFRelease(matchingFont);
CFRelease(fontDesc);

I don't think it is your issue - it is definitely something to do with iOS. Perhaps introduced in 4.3?

@odrobnik
Collaborator

can you try it on different OSs, SDKs and on device?

I'll try and see if I can reproduce it.

On Apr 28, 2011, at 7:51 AM, scarnie wrote:

No, Helvetica. Here is a reproducible sample:

NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
   [attributes setObject:@"Helvetica" forKey:(id)kCTFontFamilyNameAttribute];
   [attributes setObject:[NSNumber numberWithFloat:36.0f] forKey:(id)kCTFontSizeAttribute];
   CTFontDescriptorRef fontDesc = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)attributes);
   CTFontRef matchingFont = CTFontCreateWithFontDescriptor(fontDesc, 36.0f, NULL);
   CFRelease(matchingFont);
   CFRelease(fontDesc);

Reply to this email directly or view it on GitHub:
https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML/issues/19#comment_1068341

@stuartcarnie

On device is where the problem lies - in simulator it is fine. I have and iPad 2 (6-700ms) and iPad (1200ms) both on 4.3. I don't think I have any devices left below that :)

@stuartcarnie

I have also raised the issue on the Apple dev forums and created a bug report.

@odrobnik
Collaborator

I think the problem is that it takes time to load the CoreText dynamic library.

If you perform this very test several times in a row the time drops dramatically:

2011-04-28 07:59:05.725 CoreTextExtensions[1348:707] Start
2011-04-28 07:59:06.980 CoreTextExtensions[1348:707] Finish

2011-04-28 07:59:06.983 CoreTextExtensions[1348:707] Start
2011-04-28 07:59:06.995 CoreTextExtensions[1348:707] Finish

2011-04-28 07:59:06.998 CoreTextExtensions[1348:707] Start
2011-04-28 07:59:07.010 CoreTextExtensions[1348:707] Finish

This is on iPhone 4 (3.2.2), 1255 ms down to 12 ms

I also tested it with different sizes:

2011-04-28 08:01:30.979 CoreTextExtensions[1360:707] Start
2011-04-28 08:01:32.229 CoreTextExtensions[1360:707] Finish

2011-04-28 08:01:32.232 CoreTextExtensions[1360:707] Start
2011-04-28 08:01:32.244 CoreTextExtensions[1360:707] Finish

2011-04-28 08:01:32.248 CoreTextExtensions[1360:707] Start
2011-04-28 08:01:32.259 CoreTextExtensions[1360:707] Finish

No change. only first run is slow.

And with different sizes AND different font families:

2011-04-28 08:03:40.112 CoreTextExtensions[1371:707] Start
2011-04-28 08:03:41.374 CoreTextExtensions[1371:707] Finish
2011-04-28 08:03:41.378 CoreTextExtensions[1371:707] Start
2011-04-28 08:03:41.448 CoreTextExtensions[1371:707] Finish
2011-04-28 08:03:41.451 CoreTextExtensions[1371:707] Start
2011-04-28 08:03:41.463 CoreTextExtensions[1371:707] Finish

  • (void)testWithSize:(CGFloat)size family:(NSString *)family
    {
    NSLog(@"Start");
    NSMutableDictionary *attributes = [NSMutableDictionary dictionary];

    [attributes setObject:family forKey:(id)kCTFontFamilyNameAttribute];

    [attributes setObject:[NSNumber numberWithFloat:size] forKey:(id)kCTFontSizeAttribute];
    CTFontDescriptorRef fontDesc = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)attributes);
    CTFontRef matchingFont = CTFontCreateWithFontDescriptor(fontDesc, size, NULL);
    CFRelease(matchingFont);
    CFRelease(fontDesc);
    NSLog(@"Finish");
    }

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    [self testWithSize:10 family:@"Courier New"];
    [self testWithSize:20 family:@"Georgia"];
    [self testWithSize:30 family:@"Helvetica"];

2011-04-28 08:05:12.555 CoreTextExtensions[1382:707] Start
2011-04-28 08:05:13.839 CoreTextExtensions[1382:707] Finish
2011-04-28 08:05:13.843 CoreTextExtensions[1382:707] Start
2011-04-28 08:05:13.882 CoreTextExtensions[1382:707] Finish
2011-04-28 08:05:13.885 CoreTextExtensions[1382:707] Start
2011-04-28 08:05:13.898 CoreTextExtensions[1382:707] Finish

Same result. So the problem - and this is what you should put into your Radar - is that the initialization of the dynamic library is slow. One workaround might be to do something in background that triggers loading of the library without affecting the startup time of the app as well as having CoreText loaded and ready to go when you need it.

cheers
Oliver

On Apr 28, 2011, at 7:57 AM, scarnie wrote:

On device is where the problem lies - in simulator it is fine. I have and iPad 2 (6-700ms) and iPad (1200ms) both on 4.3. I don't think I have any devices left below that :)

Reply to this email directly or view it on GitHub:
https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML/issues/19#comment_1068353

@stuartcarnie

Seems strange that it would take that long to load a dynamic lib, but either way I created this gist to use GDC to preload.

@odrobnik
Collaborator

cool, I'll write a blog post momentarily summarizing our findings. What is the # of your Radar so that I can reference it in mine.

On Apr 28, 2011, at 8:12 AM, scarnie wrote:

Seems strange that it would take that long to load a dynamic lib, but either way I created this gist to use GDC to preload.

Reply to this email directly or view it on GitHub:
https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML/issues/19#comment_1068397

@stuartcarnie

Indeed, the bug number is rdar://9350255

@stuartcarnie

Thanks Oliver. I am fairly confident it is not a dynamic lib loading issue, because the first API call to CoreText (CTFontDescriptorCreateWithAttributes) is not slow. When I profiled into core text, it is a lot time spent in freetype library.

@odrobnik
Collaborator

Well, that's Apple's problem now. :-)

Please add your wise comments to the blog article instead because this is issue 19 is closed.

On Apr 28, 2011, at 8:48 AM, scarnie wrote:

Thanks Oliver. I am fairly confident it is not a dynamic lib loading issue,
because the first API call to CoreText (CTFontDescriptorCreateWithAttributes)
is not slow. When I profiled into core text, it is a lot of code running in
freetype library.

Cheers,

Stu

Stuart Carnie, CTO
manomio http://manomio.com/ | in retro we trust!

On Wed, Apr 27, 2011 at 11:41 PM, Cocoanetics <
reply@reply.github.com>wrote:

Discussion continues here:
http://www.cocoanetics.com/2011/04/coretext-loading-performance/

Reply to this email directly or view it on GitHub:

https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML/issues/19#comment_1068485

Reply to this email directly or view it on GitHub:
https://github.com/Cocoanetics/NSAttributedString-Additions-for-HTML/issues/19#comment_1068506

@ngrilly
ngrilly commented Dec 20, 2012

@scarnie Just curious about this: "When I profiled into core text, it is a lot time spent in freetype library". Does it mean that Core Text uses FreeType or is it your extension that uses it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment