ios - ¿Por qué la llamada inicial a NSAttributedString con una cadena HTML toma más de 100 veces más que las llamadas subsiguientes?
objective-c cocoa-touch (1)
Esa es una muy buena pregunta. Resulta que (al menos para mí) siempre es más lento la primera vez que llamo al método, no importa si el depurador está conectado o no. A continuación se explica por qué: la primera vez que analiza una cadena con atributos HTML, iOS carga en la memoria todo un motor JavaScriptCore y WebKit. Reloj:
La primera vez que ejecutamos el método (antes de analizar la cadena) solo existen 3 hilos:
Después de que se analiza la cadena, tenemos 11 hilos:
Ahora, la próxima vez que ejecutemos el método, la mayoría de esos hilos relacionados con la web todavía existen:
Eso explica por qué es lento la primera vez y rápido después.
Tenía la necesidad de mostrar texto HTML dentro de mi aplicación iOS. He decidido que NSAttributedString
el método NSAttributedString
en NSAttributedString
, initWithData:options:documentAttributes:error:
El análisis real funciona de forma excelente, sin embargo, parece que me he encontrado con un error muy extraño, que solo parece manifestarse si tengo el depurador adjunto.
La primera vez que se llama a este método, tarda apenas menos de 1 segundo en ejecutarse en mi iPhone 5S con iOS 7.0.4, y aproximadamente 1.5 segundos en un iPod Touch de quinta generación. La peculiaridad también se manifiesta en el simulador, pero es significativamente menos notable, debido a la velocidad pura del simulador.
Las llamadas subsiguientes solo toman alrededor de 10-50ms, lo que es significativamente más rápido que la llamada inicial.
Esto no parece estar relacionado con el almacenamiento en caché de la cadena de entrada, ya que lo he probado con varias cadenas de entrada en mi aplicación "real".
Sin embargo, cuando ejecuto el programa sin el depurador, se ejecuta como se esperaba, tomando unos 10-20 ms, que es lo que espero que tome el análisis HTML.
Aquí está la sección relevante del código:
-(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];
}
Nota : Un proyecto en pleno funcionamiento que demuestra este error está disponible aquí:
https://github.com/richardjrossiii/NSAttributedStringHTMLBug
¿Estoy loco? ¿Hay algo que me estoy perdiendo aquí? 1 segundo es una cantidad muy grande de tiempo cuando intento optimizar mi aplicación para el rendimiento.
Mi solución actual es analizar una cadena "ficticia" en el lanzamiento de la aplicación, pero esto parece ser una solución increíblemente hacky.