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
perf: Allow stack frames to contain references to other stack frames #337
Comments
ProposalWe have a
With this model, a for loop could have a custom struct that implements the ability to do lookups. That struct might have references in it. We have a @Goncalerta any feedback on this idea? |
So, at the time I first saw this issue I was very busy so I was going to come back to it later, but ended up forgetting about it (sorry!). You mentioned some concepts (decorator structure and arena allocator) that I hadn't heard of before, so I searched them. Correct me if I am wrong:
I tried to understand the model you proposed, however, I must be missing some key aspects, because I couldn't think of a way that would not break the rules of borrowing/lifetimes. Honestly, I must admit that my head started to get very confusing after an hour of trying to wrap my head around this. Could you further explain your model please? In particular, which structure owns the allocator; would there be one allocator per frame or just one for the mutable frame; what exactly would be the role of the decorator of Context; what do trait objects have to do with |
Life gets and things fall by the way for us all. I'm going on 5 months now of barely getting time to do any open source work.
Yes, the term is referring back to the decorator pattern. In this case, the extra functionality we are adding is isolation from the lower level
Yes. we effectively allocate all of the items within the arena. Instead of deallocating an item, we just reference another area within the allocator, ensuring they are all still alive.
Note: anything in
Random notes
To be clear, this might over complicate things to the point of not being worth the gains. I just see our failing in some benchmarks and wanted to brainstorm how we could overcome them rather than just assume we can't. |
So, basically, instead of having a Oh right, the mutable stack is the global one! I was confusing the scopes of liquid with the scopes in rust, as if It bothers me that the allocator is global, wouldn't it become filled with too many values because it couldn't delete them until the end of I thought that maybe we could try avoid keeping the reference to the |
Yes.
Unfortunately :(
This allocator will only be around for the length of the processing and will only fill with things the user has explicitly
It is an interesting idea but I'm also concerned about looking up the variable within the now-possibly-modified version. If the user did an assign, we could have different values, a different length, or be a completely different data type (as you pointed out) I'm also unsure how this will play with iterating over a hashmap. |
However, what if the user does something like this?
Add some more complexity in the template and maybe even some nested loops and suddenly there are a lot of useless variables stuck in the allocator.
Yes, hashmaps would also be a problem. We'd probably need to use a diferent implementation to get around that, and the potential overall performance lost for that might not be worth it. The arena allocator seems to be the least bad solution. |
First, sorry for the long delay. I should be able to at least get back to people in a reasonable time even if I'm slowed down with life. I am also sorry for how long it has taken to get a release out for all that filter work you did. I should be getting one out soon now that I have redone tags/blocks and I've added workspace support to
Great counter example. To be clear, I put this issue as a high risk experiment. It can completely bomb. Feel no obligation towards this. There are a lot of other interesting challenges in liquid or other crates that would probably pay off more. |
Now that we have The current iteration of my idea for this: pub struct Context {
inner: ContextImpl
}
enum ContextImpl {
Core(ContextCore),
StackFrame(&Context),
}
struct StackFrame {
parent: &Context,
name: Option<kstring::KString>,
data: ObjectCow, // ValueCow if making an ObjectCow would be annoyijng
}
struct ContextCore {
// Most of what is in `Context` today
} We then treat the mutable frame specially with it inside of a RefCell (Mutex if needed instead). We always |
perf(runtime): Allow stack frames to contain references to other stack frames #337
Currently, the lifetimes don't work out to allow this.
The downside is that when we do something like a for-loop, we have to
clone
the entire value we'll iterate on to ensure its lifetime. At least we get to reuse each element when we move it into the user-defined variable name.From seeing how Liquid behaves in benchmarks, my gut says the
clone
s mentioned above are some of our biggest hinderancesThe text was updated successfully, but these errors were encountered: