Make parsing of text be non-quadratic. #579
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
In Python, appending strings is not guaranteed to be constant-time, since they are documented to be immutable. In some corner cases, CPython is able to make these operations constant-time, but reaching into ETree objects is not such a case.
This leads to parse times being quadratic in the size of the text in the input in pathological cases where parsing outputs a large number of adjacent text nodes which must be combined (e.g. HTML-escaped values). Specifically, we expect doubling the size of the input to result in approximately doubling the time to parse; instead, we observe quadratic behavior:
Switch from appending to the internal
str
, to appending text to an array of text chunks, as appends can be done in constant time. Usingbytearray
is a similar solution, but benchmarks slightly worse because the strings must be encoded before being appended.This improves parsing of text documents noticeably:
Old flamegraph:
![](https://private-user-images.githubusercontent.com/28347/308321675-e060490a-fa41-4a04-aca3-27f20a4deb72.svg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQxMjg0NzMsIm5iZiI6MTcyNDEyODE3MywicGF0aCI6Ii8yODM0Ny8zMDgzMjE2NzUtZTA2MDQ5MGEtZmE0MS00YTA0LWFjYTMtMjdmMjBhNGRlYjcyLnN2Zz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MjAlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODIwVDA0MjkzM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTg5ZGVkNWVlMWEwN2VjOTlkMDQyN2JhYTVhM2NiNzQyNzlkZjJhNjNhODk4YTA5MmY2ZDY4Yjc1MDY5NzVmMTUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.__Ec7Jew67sfsiXD7h07vnIKGn0Qte889LJVEvt1scg)
New flamegraph:
![](https://private-user-images.githubusercontent.com/28347/308321701-038f1577-38d6-4c0b-aa0d-425a7590b8b4.svg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQxMjg0NzMsIm5iZiI6MTcyNDEyODE3MywicGF0aCI6Ii8yODM0Ny8zMDgzMjE3MDEtMDM4ZjE1NzctMzhkNi00YzBiLWFhMGQtNDI1YTc1OTBiOGI0LnN2Zz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MjAlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODIwVDA0MjkzM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTMzMWMxYmRkNmZlZDhkN2MwZjE1ZDE1Nzg3NWM2OTdjMjZlZjZhZDAyMTUwY2QwYzEyY2E3MDc3NDI4NTcyNDImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.3YBQYiKkTk9uMEXyGL9m_KjjthpmlSu-9ibZASX24TI)