-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Idea: create more functional code for fragments #37
Comments
Anything that makes the VM's job easier is 👍 . I'd be curious to know how much of a benefit there is in moving I do think it's worth striving for readable generated code – one of the nice things about a non-runtime approach is that it's beautifully easy to debug since you're stepping through ~150 lines of code rather than ~20,000 lines of framework. Keeping For SSR I was thinking you'd keep that out of the main compiler altogether, and it would be a totally separate thing (well, same parser, but different generator). Could even be a streaming renderer which would be pretty neat. Not totally sure yet what hydration looks like... |
I think this is something worth exploring, especially since closures make a big difference in V8. @Rich-Harris I highly recommend reading Vyacheslav Egorov's Grokking V8 closures for fun (and profit?) if you're interested in closures' performance characteristics. I reached out to them and they confirmed that post is still 100% relevant in today's V8. I'll try to run some benchmarks on an object-based solution when I get a chance. |
Some hard numbers would sure be nice. I know that it should in theory be better for the vm, surely from a memory usage perspective, since it avoids creating a lot of duplicated function objects, but I have no idea what this means in practice. Anyway, here is a completely outdated branch where I tried a little bit to do this: https://github.com/sveltejs/svelte/commits/functional |
Instead of hacking on the compiler, I decided to first create a simple benchmark by manually editing a generated component. I did a direct closure to object translation instead of making big changes so that we can compare the impact of closures by themselves. Implementing these changes to the compiler shouldn't be too hard as there's close to no distinction. You can find the benchmarks here. On my machine, closures are nearly twice as slow on Chrome, but there's no significant difference on Firefox (although they're generally a few percent points slower). I realize this is a pretty constrained and silly benchmark, but we're talking about a fairly low-level vm optimization, here. I have no reason to believe closures would outperform objects given a realistic use case. A non-closure implementation would also give us more control over the general dependencies/memory layout, so I expect it'd be easier to implement future optimizations. I personally think V8 is too big of a target for us to neglect "those gains." Thoughts? @Swatinem @Rich-Harris |
I did modify the generator to compile into a more object style but the results doesn't look too promesing. There are some gains but I expected it to be much better: Here are the results of the js-framework-benchmark. svelte v1.0.7-test is using the object approche. |
@FWeinb I did the same and got surprisingly close results. 😄 I did it naively at first, adding all references to the object and without extracting event handler closures. Got from 1.12 -> 1.10. I was about to start adding support for Did you implement the distinction between instance members and init-only variables? What about event handlers and |
I just pushed the changes I made to a branch on my fork. You can find it here I did move every element/node creation to |
Talk about some duplicated effort... 😋 |
Okay. We had the same idea! Funny that is looks almost identically. |
Nice work. I’m personally in favor of not using I am personally in favor of also splitting up the state management from the dom manipulation ( #9 ), and ideally, the dom manipulation part would just export a module with static functions for everything, and a tool like rollup could be used to DCE away things you don’t need, like the But that is a quite invasive change :-) |
Yeah, I tried to do a conversion as closely as possible, at first. I'm still wrapping my head around the generator. I don't even know how all For us to really add this to svelte, I think it'd be wise to track identifiers/references scopes/owners as well, instead of adding |
I believe this ticket is specific to Svelte 2, so I'm going to close this. If that's wrong we can reopen - though it may be cleaner to file a new issue with Svelte 3 code examples and consolidated feedback from this ticket in that case |
One thing that actually bothers me when looking at the svelte output is that it uses closures for the
update
andteardown
methods, which might be ok for minification, because it can minify all the variable names, but is actually bad for code reuse inside the VM.I also experimented with a similar code generation idea over a year ago, and I thought to myself, why not make those things functional, like this:
Fragment.create(…) => Instance
appends to the DOM and returns an object with the important dom elementsFragment.update(Instance, …)
instead of using closure upvars or this, we just pass in the object with the dom elementsFragment.teardown(Instance)
same hereAlso, thinking about #1 and #9, we could also have these methods:
Fragment.toString(…)
will render to a string for SSRFragment.hidrate(…) => Instance
will create the element map from already existing DOM elementsI think this can be done internally without changing the public API of components.
What do you think @Rich-Harris?
The text was updated successfully, but these errors were encountered: