Text content is appended one character at a time in parseXml

Aperta
#914 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 3 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
56/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
javascript, node.js

Direzione di ricerca

Start in src/xmlparser/OrderedObjParser.js at the parseXml text branch named in the issue. Compare the proposed indexOf and substring approach with the current loop, then run jasmine spec/*spec.js, including the text and preserveOrder cases described in the issue. Done means the specs pass and parsed output stays identical while text heavy input is processed in chunks.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Where

https://github.com/NaturalIntelligence/fast-xml-parser/blob/2460b41927ad94d352c44297a3aa2fa22fe2d65d/src/xmlparser/OrderedObjParser.js#L602-L604

Why it's slow

In parseXml, every character that isn't part of a tag goes through the final else branch and is appended one at a time with textData += xmlData[i]. For documents with long text content (RSS/Atom feeds, articles, descriptions), most of the input goes through this path, so the parser does one loop iteration plus one string concat per text character.

Proposed fix

When the loop hits text, find the next < with indexOf, append the whole run with a single substring, and move i to just before that <. It still uses +=, so text split by a comment (<a>one<!--x-->two</a> -> "onetwo") is joined exactly as before. If there's no further <, the rest of the input is taken.

} else {
  let nextTag = xmlData.indexOf('<', i);
  if (nextTag === -1) nextTag = xmlLen;
  textData += xmlData.substring(i, nextTag);
  i = nextTag - 1;
}
Benchmark

Node 24.12, Apple M4 Pro. The machine was under load during the runs, so I used an in-process A/B: both versions loaded side by side, runs alternated, 31 timed rounds each, median ms per parse. Output was checked to be identical for every file/option pair. Numbers are from the second of two passes (the first pass was similar).

Input Options before (ms) after (ms) speedup
spec/assets/ptest.xml (1.3 KB) default 0.013 0.012 1.08x
preserveOrder 0.010 0.009 1.10x
text-heavy RSS (3 MB, ~800-char descriptions) default 40.6 25.4 1.60x
ignoreAttributes: false 71.0 42.4 1.67x
preserveOrder 70.5 35.7 1.98x
tag-dense (3 MB, short values) default 248.9 257.4 0.97x
ignoreAttributes: false 268.4 270.3 0.99x
preserveOrder 173.4 174.4 0.99x

node benchmark/XmlParser.mjs (on ptest.xml) also went up for fxp and fxp - preserve order in every before/after pair, but run-to-run noise on this machine was too high for its absolute numbers to be useful. Tag-dense input is about the same, within noise.

Tests

On the prototype branch, all 342 specs pass (jasmine spec/*spec.js), including two new ones in spec/data_spec.js: text split by comments, a long text run with entities, and text order with preserveOrder. Branch: https://github.com/TheNetherWatcher/fast-xml-parser/tree/perf/text-chunk

Happy to open a PR with this change if it seems useful/viable.

Lingua principale
JavaScript
Stelle
3.1k
Fork
404
Merge medio
2g 1h
PR unite (30g)
5

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di NaturalIntelligence/fast-xml-parser

Tutte le issue di NaturalIntelligence/fast-xml-parser

Issue simili

Altre issue su JavaScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.