2017-01-12 2 views
5

Ich bin Parsen Tab-separierte Werte:Wie zu beschleunigen UTF-8-String-Verarbeitung

pub fn parse_tsv(line: &str) -> MyType { 
    for (i, value) in line.split('\t').enumerate() { 
     // ... 
    } 
    // ... 
} 

perf oben enthält str.find. Wenn ich in den generierten Assembler-Code schaue, gibt es viel Arbeit in Bezug auf die UTF-8-Codierung der Symbole in &str.

Und es ist relativ veeeeery langsam. Es dauert 99% der Ausführungszeit.

Aber zu finden \t Ich kann nicht einfach nach einem Byte \t in einer UTF-8-Zeichenfolge suchen.

Was mache ich falsch? Was macht Rust stdlib falsch?

Oder vielleicht in Rust gibt es eine einige String-Bibliothek, die Strings einfach durch 'u8' Bytes darstellen kann? Aber mit allen split(), find() und anderen Methoden?

+1

kompilieren Sie mit Optimierungen auf? ('- Freigabe 'mit Ladung) – huon

+0

@huon natürlich – vladon

+0

Was ist der Geschwindigkeitsunterschied, wenn Sie stattdessen" "\ t" 'verwenden? – Shepmaster

Antwort

7

Solange Ihre Zeichenkette ASCII ist oder Sie keine Übereinstimmung mit UTF-8-Skalaren benötigen (zB in Ihrem Fall, wo Sie nach Tabs suchen), können Sie sie einfach als Bytes mit der Methode behandeln danach operiere auf u8 Zeichen (Bytes) anstelle von char s (UTF-8 Skalare). Dies sollte viel schneller sein. Mit &[u8], die ein slice, können Sie Methoden für &str Scheiben wie split(), find() usw.

let line = String::new(); 
let bytes = line.as_bytes(); 

pub fn parse_tsv(line: &[u8]) { 
    for (i, value) in line.split(|c| *c == b'\t').enumerate() { 

    } 
} 

fn main() { 
    let line = String::new(); 
    let bytes = line.as_bytes(); 

    parse_tsv(&bytes) 
} 
+0

wow, ich kann split auf '& [u8]' verwenden, ich wusste nichts davon, danke! – vladon