Closed timfish closed 3 years ago
I've thought of another way:
I assume that your constants data is expensive to prepare and are not themselves constants (i.e. they change values when called a different time), so they must be prepared at the time of the script evaluation, not before. Otherwise, it is a simple matter of making a scope with all prepared constant values once, then reusing that scope many times for script calls.
Currently No.1 is probably your best bet, but it is volatile. If you disable eval
then it is workable, but with eval
it is not.
No.4 is interesting and doable, but since you're using straight variable access (not a map.property
access) for your constants, you'll still need to push a large number of wrappers into the scope.
I can also add an AST-walking function to dump variables usage (actually code is already there to handle closures).
Come to think of it, No.3 which is to add an on_var
callback is probably the most versatile way to resolve this, with the least amount of runtime overheads. I'll put that in.
If you want the new functionality, you'll probably need to pull from the development repo for the time being.
Currently all the variables are in memory so copying them to scope isn't a problem behind an Arc
, but I'm in the process of adding a file backed store so loading everything into scope could potentially be very expensive. My wrapping type contains huge vectors of samples.
1 is simplest from my perspective because I wouldn't have to implement a caching layer so multiple uses if the same variable doesn't become slower. Also wouldn't have to worry about bloating the scope.
I've thought of another way to do this that doesn't require any changes in rhai. Since iterators are lazily evaluated, I can add cloneable iterators to the scope in a wrapping type + operator overloaded can chain extra integrators on top. It's only once the resulting iterator is collected that the expensive stuff happens. My only concern here is that dynamic dispatch of chained iterators over millions of iterations is going to suck!
@timfish Please pull from this repo. There is a new feature added: variable resolver.
Check out the new docs: https://schungx.github.io/rhai/vnext/patterns/dynamic-const.html
This is awesome! I'll give it a try.
@timfish how is it working out?
I think it's working well, thank you. I'll close this issue once I've given it a more thorough test!
@timfish see if you have any more issues with this feature, otherwise this can be closed! Thanks!
Beware, I just released version 0.19.3
which has a slight change to the function signature of the on_var
closure...
Thanks, this is all good
We're using Rhai to evaluate equations on large blocks of captured data. We do this using a custom type which wraps large Vecs and override operators for that custom type which do the maths on the large blocks of data. This is working really well!
However, we currently load all the possible variables into the scope which is wasteful because creating the wrapping types involves large allocations and the equation might not use all (or even most) of them.
Things I've considered:
A * 2
=>A() * 2
. I don't think this will work because we'd have to pre-define a function for each possible variable.What are your thoughts?