-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Text decoding performance abysmally slow. #3163
Comments
Just a quick note: reading operation is actually very fast ( |
This is a very good note. I did not think to check that and just assumed it was the read operation, but I suppose that doesn't make much sense. |
It remains that reading a file to a string is horribly inefficient and CPU heavy, due to the decoding step. Should I update the issue to be about the decoding? |
Yes please |
I think perhaps the TextDecoder code should be moved to Rust, as I have a feeling it's the fact that it's in JS that's slowing it down. It's an operation that needs to be high performance (for purposes of ingesting large files, and likely more). An alternative to that (though that is still preferable) would be to provide a I'm not sure there's any high performance way to implement the |
Hmmm... it is going to be tricky to do this fast given our current op model. There is the zero copy buffer, but Rust doesn't generate JavaScript strings, which is what we need to end up with. The way this is done in the likes of Chromium is injecting the decode function into the isolate, which then utilises native C++ to perform it. The other option is to author it in Rust, transpile it to WASM and utilise that in the runtime. It would be good to add this to the benchmarks, because obviously string encoding and decoding is pretty important. Also, should do more research into other JavaScript implementations that might be more performance tuned. We maybe doing something silly. |
I believe that is the case, we've got GC all over the place:
700MB of memory to decode 25MB suggest there's a problem in our decoder implementation. |
If we could get a benchmark on the benchmarks page, I will happily invest the time to make it faster / use less memory. It's not at all obvious that doing it in rust would be faster. Boundary crossing is a significant cost and V8 optimizes code very well.
Indeed. Maybe it's a just a small fix to the JS. |
Yes, on second thought that's probably right. I did some research on high performance UTF-8 decoding and looked at some algorithm options and will be working on creating a high performance UTF-8 decoder in JavaScript soon. I will make a comment on this issue with a link to it when I'm satisfied with it, where hopefully someone can implement it in Deno. (I would do it myself and make a PR, but I really can't stand using git more than I have to.) |
@qwerasd205 feel free to contribute however you wish, would be glad to get it to fit into Deno. |
I've created a UTF-8 decode function in JavaScript that does 80-130 MB/s on my machine, which I think would be more than sufficient. The function can be found at this gist. Can't wait to see it in Deno! |
@qwerasd205 Please supply a benchmark program and I will do the work of getting it in for you. |
@ry A program that benchmarks the TextDecoder decode function? What should the format of the output be? |
No output - I just need it to do something that's currently expensive. |
Okay, can do. |
@ry feels like we should also invert it to... keep track of |
@ry here's a script which randomly generates 10MB of utf-8 data and feeds it to the text decoder: https://gist.github.com/qwerasd205/a7616010915180b0fde08a52454e4fe4 |
It takes ~2.8 seconds for TextDecoder, and ~0.16 seconds for my decode function. |
Actually I just noticed my generate random utf-8 function is flawed, I copied it from somewhere without thinking, but it gets the point across. |
Fixes denoland#3163 Co-authored-by: Kitson Kelly <me@kitsonkelly.com> Co-authored-by: Qwerasd <qwerasd205@users.noreply.github.com>
Fixes #3163 Co-authored-by: Kitson Kelly <me@kitsonkelly.com> Co-authored-by: Qwerasd <qwerasd205@users.noreply.github.com>
This issue was originally focused on file reading performance but it was brought to my attention that the issue is in fact with the text decoding, and that the file read operation does not take very long. This issue does still directly impact reading large files as strings, though.
The following paragraph is from the original issue, and still holds true to an extent. I have updated the rest of the issue to talk about the text decoding, though.
The file reading performance of Deno is, well, abysmal. On my machine it takes 9.25 seconds to read a 25mb file using deno_std's fs
readFileStrSync
function, and additionally, while it's reading the file it pins CPU usage at 100%+. For comparison, perl5 reads the same file in 0.025 seconds.I have updated the Repro code below to be a test of the text decoder speed. When you run the code, note the 100%+ CPU usage.
Repro code:
Deno:
Example output:
Decode finished in 6.134s
There must be something wrong somewhere with the
file readingtext decoding for it to take so long (and to pin the CPU usage at 100%+ while it's at it). Until this is fixed I can't really continue working on my project in Deno which involves saving and loading significant amounts of data, because as it is, with ~30mb of data between two files it's taking 10+ seconds to load.macOS Catalina 10.15 Beta
The text was updated successfully, but these errors were encountered: