2009-06-26 1 views
9

Sto provando a scrivere un'applicazione, che esegue l'analisi dei dati, archiviata in file XML piuttosto grandi (da 10 a 800 MB). Ogni set di dati viene memorizzato come tag singolo, con dati concreti specificati come attrobutes. Attualmente sono saxParse di HaXml e non sono soddisfatto dell'utilizzo della memoria durante il lavoro con esso. Analizzando il file XML da 15 Mb consuma più di 1 GB di memoria, sebbene abbia tentato di non memorizzare i dati negli elenchi e di elaborarli immediatamente. Io uso seguente codice:Quale parser XML per Haskell?

importOneFile file proc ioproc = do 
    xml <- readFile file 
    let (sxs, res) = saxParse file $ stripUnicodeBOM xml 
    case res of 
     Just str -> putStrLn $ "Error: " ++ str; 
     Nothing -> forM_ sxs (ioproc . proc . (extractAttrs "row")) 

dove 'proc' - procedura, che esegue la conversione dei dati da attributi in record e 'IOProc' - procedura, che esegue una certa azione IO - output a schermo, la memorizzazione nel database, ecc.

Come posso ridurre il consumo di memoria durante l'analisi XML? Dovresti passare a un altro parser XML?

Aggiornamento: e quale parser supporta per diverse codifiche di input - utf-8, utf-16, utf-32, ecc.?

risposta

4

Se si è disposti a presupporre che i propri input siano validi, si consideri l'aspetto di TagSoup o Text.XML.Light dalla popolazione di Galois.

Questi prendono stringhe come input, in modo da poter (indirettamente) dar loro da mangiare qualsiasi cosa Data.Encoding capisce, vale a dire

  • ASCII
  • UTF8
  • UTF16
  • UTF-32
  • KOI8R
  • KOI8U
  • ISO88591
  • GB18030
  • BootString
  • ISO88592
  • ISO88593
  • ISO88594
  • ISO88595
  • ISO88596
  • ISO88597
  • ISO88598
  • ISO88599
  • ISO885910
  • ISO885911
  • ISO885913
  • ISO885914
  • ISO885915
  • ISO885916
  • CP1250
  • CP1251
  • CP1252
  • CP1253
  • CP1254
  • CP1255
  • CP1256
  • CP1257
  • CP1258
  • MacOSRoman
  • JISX0201
  • JISX0208
  • ISO2022JP
  • JISX0212
3

Non sono un esperto di Haskell, ma ciò che si sta eseguendo sembra una classica perdita di spazio (cioè, una situazione in cui la pigra valutazione di Haskell sta causando la riserva di memoria più del necessario). Potresti riuscire a risolverlo forzando il rigore sul tuo output saxParse.

C'è anche un buon capitolo sulla profilazione e ottimizzazione Real World Haskell.

EDIT: trovato un'altra buona risorsa sulla profilazione/scoperta colli di bottiglia here.