plurimath / plurimath-js

Plurimath JavaScript module
2 stars 1 forks source link

plurimath-js not practical for frontend use #34

Open gwhitney opened 3 days ago

gwhitney commented 3 days ago

These comments are not meant to be critical, just providing feedback that I really like the functionality but (I presume mostly from the automatic conversion from Ruby) it does not seem that this package can practically be used in a frontend application:

1) It is huge: adds over 2 megabytes uncompressed and half a megabyte compressed to my bundle (more than 50% each way in my case). 2) It causes numerous errors about the use of eval when bundling. 3) It is too slow for human-scale reaction: if I use it to parse an input field to display the corresponding mathml, there is a noticeable lag before the mathml appears. You can see this on your own demo page in the sluggish response to typing in the input field. You can measure it just with the old standby unix command time: the line

const fmla = new plurimath('{n}^3 - {n}^2', 'latex')

added to JavaScript file increases its execution time in node by three tenths of a second very reliably.

I assume a JavaScript-native implementation of the very excellent Plurimath functionality would reduce all of these metrics by orders of magnitude. Hopefully someday WASM or something like that will let us access the Plurimath functionality without this level of baggage. In the meantime, I guess we will have to try different tools.

gwhitney commented 3 days ago

P.S. As I said, this was not meant to be critical, just informative; Plurimath could and likely will be very useful in the backend, although presumably there we would just run the Ruby version natively, which is I assume far faster.

ronaldtse commented 3 days ago

Thank you @gwhitney for the feedback which I believe to be fair. It is unfortunate that the current form does not meet your needs today due to how Opal works. Ideally, we do wish to provide a JS-native/TS version of Plurimath but we are subject to resource requirements...

In the meantime I do wonder if it is possible to address your points 1-3, I will have to defer to @hmdne on this.

hmdne commented 2 days ago

For additional work on bundle size:

Regarding errors, or in particular, warnings, this is likely an easy task to do.

Regarding performance, it should be fairly straightforward to do some profiling, find some hot paths and fix them. In general though, if you wanted the most interactive behavior, it may be a good idea to defer Plurimath to a WebWorker.

Regarding WASM, I am aware of the developments in Ruby space regarding WASM. But here, unfortunately, the issue is you have to include the whole Ruby runtime and that's more than 2MB even (let's say, on https://try.ruby-lang.org/playground/ it's 10.6 MB uncompressed). The performance will be at parts better, at parts worse (WASM runtime itself is in my experience a lot slower than native code, unlike asm.js which is basically dead). Perhaps a better option may be to rewrite Plurimath in C/C++/Rust then use that implementation to be compiled into WASM and shared object respectively.

gwhitney commented 2 days ago

In general though, if you wanted the most interactive behavior, it may be a good idea to defer Plurimath to a WebWorker.

Is there a way (say in a webworker, or not) to get this Plurimath implementation into a listening state where it can respond very quickly to new requests to parse? The difficulty at the moment is that each call to new Plurimath seems to have a great deal of overhead, and so I don't see how putting that into a webworker would solve anything, if we just kept incurring that overhead again and again in the webworker, too.

But it's not clear this direction would be too productive, so don't spend much effort on supporting it. You see, I am not sure what the "etiquette" is for utility libraries like mathjs to spawn their own webworkers; usually I feel like applications want to have direct control over any webworkers created. At least, I don't know of any libraries in popular use that spawn webworkers of their own accord.

hmdne commented 2 days ago

What I mean precisely is that JavaScript in general is single threaded. I am not sure about your usecase, but if, for instance, live WYSIWYG editor is your target, regardless of performance improvements we make, it will consume the main thread, so while converting, it will block rendering, accepting user events etc. so that's why my suggestion was to run it in a WebWorker. It would obviously make no sense to do it inside a library, especially as environments like Node do it differently (as far as I know).

gwhitney commented 2 days ago

Ahh, I was hoping that maybe there could a "hot" listener in a webworker that would have all the ruby init out of the way and turn around new parsing requests really efficiently. Anyhow, the temml package has covered my immediate use case, even if it would be nice to eventually have the much more flexible capabilities of plurimath. Thanks for your advice and thoughts.

sunnyawake5 commented 1 day ago

can we convert ruby version to js version using https://github.com/ruby2js/ruby2js

hmdne commented 1 day ago

@gwhitney the Ruby runtime is initialized once. Yes, it should be possible to run something like a WebWorker server

@sunnyawake5 No. Ruby2JS is mostly just JavaScript with Ruby syntax.