Ich musste HTML-Text in meiner iOS App anzeigen lassen. Ich habe beschlossen, dass ich die eingebaute Methode auf NSAttributedString
, initWithData:options:documentAttributes:error:
verwenden werde. Das eigentliche Parsen funktioniert hervorragend, allerdings scheint mir ein sehr merkwürdiger Bug aufgetaucht zu sein, der sich nur dann zu manifestieren scheint, wenn ich den Debugger angehängt habe.Warum dauert der erste Aufruf von NSAttributedString mit einer HTML-Zeichenfolge mehr als 100 Mal länger als nachfolgende Aufrufe?
Das erste Mal, dass diese Methode aufgerufen wird, dauert es knapp unter 1 Sekunde auf meinem iPhone 5S mit iOS 7.0.4 und etwa 1,5 Sekunden auf einem iPod Touch der 5. Generation. Die Eigenart manifestiert sich auch am Simulator, ist aber aufgrund der schieren Geschwindigkeit des Simulators deutlich weniger auffällig.
Nachfolgende Anrufe dauern nur etwa 10-50 ms, was deutlich schneller ist als der erste Anruf.
Dies scheint nicht im Zusammenhang mit der Zwischenspeicherung der Eingabezeichenfolge zu stehen, da ich es mit mehreren Eingabezeichenfolgen in meiner "echten" Anwendung getestet habe.
Wenn ich jedoch das Programm ohne den Debugger ausführen, wird es wie erwartet ausgeführt und dauert etwa 10-20ms, was ich erwarten HTML-Parsing zu nehmen.
Hier ist der relevante Abschnitt des Codes:
-(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];
}
Hinweis: Ein volles Projekt arbeiten, diese Fehler demonstriert hier verfügbar:
https://github.com/richardjrossiii/NSAttributedStringHTMLBug
Bin ich verrückt? Gibt es etwas, das mir hier fehlt? 1 Sekunde ist unglaublich viel Zeit, wenn ich versuche, meine App für die Leistung zu optimieren.
Meine aktuelle Lösung ist es, eine "Dummy" Zeichenfolge beim Start der Anwendung zu analysieren, aber das scheint wie eine unglaublich hacky Workaround.
Warum in der Welt würde JavaScriptCore verwenden? Scheint wie eine schreckliche Idee ... Wie auch immer, nachdem ich einige eigene Instrumente erstellt habe, stimmt es mit deinen Entdeckungen überein. –
@RichardJ.RossIII Ich habe keine Ahnung, warum es JSC lädt. Ich verstehe, dass es WebKit lädt, weil das Parsen einer HTML-Zeichenfolge teuer ist: Es muss eine DOM-Struktur erstellt, geparst und (möglicherweise sogar) CSS-Stile angewendet werden. Selbst wenn nur 'bold' geparst wird, muss eine ganze HTML-Parsing-Maschine gestartet werden. –
Unglaublich interessante Beobachtungen hier Jungs. Schöne Untersuchung – mattsven