-
Notifications
You must be signed in to change notification settings - Fork 781
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
Performance and Laziness #75
Comments
There's also no batching for vnodes at the moment, but there used to be. There are more than a couple things we could do to optimize our virtual-dom implementation.
Can you help with that? See also: |
@jbucaran please consider implementing https://github.com/krausest/js-framework-benchmark, it is much more representative of real-world performance. the only thing dbmonster tests is initial creation and |
@leeoniya Thanks! That's next on my list. |
Sure! Let me see what I can do. |
oh wait, I just realized there's no composition of components here... |
@ccorcos What do you mean? |
yes, every similar. there needs to be some way of combining components together. Hyper isnt so scalable in terms of breaking up components and reusing them by combining them together. For example: const TwoCounters = app({
model: {
one: Counter.model,
two: Counter.model,
},
update: {
one: ({one, two}) => ({two, one: Counter.update(one)})
two: ({one, two}) => ({one, two: Counter.update(two)})
},
view: ({one, two}, actions) =>
<div>
{Counter.view(one, actions.one)}
{Counter.view(one, actions.two)}
</div>
}) Then laziness could be introduced where Counter one doesnt need to be rerendered when Counter two changes... |
We are almost like Angular, it's not okey. But yea. Can you add |
from that screenshot, there's not a single recent version lib there; the fastest impl (Mithril) is using an ancient 0.1.21. take my word for it, just bench this: https://github.com/krausest/js-framework-benchmark, don't waste your time with anything else. |
@tunnckoCore You know, this is time consuming, so I can't promise I'll add it right away, but I'll try 👍 @leeoniya I just forked lhorie's implementation of the benchmark and added mine, I wasn't really paying attention to the version of the other libraries. Do you have any idea how to get started with the krausest/js-framework-benchmark benchmarks? The README does an incredible good job at not explaining that and from all the other benchmarks I've seen, this one looks more challenging. |
Yes. The implementation itself is easy, though actually running the bench is less easy - i usually leave the latter to @krausest since he does this for the majority of pull requests and merges. There are two versions of the bench, and you can implement one or both: Other than that, all you have to make sure is that it behaves correctly in the browser, like I would start by pulling the repo, running [1] https://github.com/krausest/js-framework-benchmark/tree/master/domvm-v2.0.1-keyed/src |
@leeoniya Thanks, this is at least a start. By the way, can you elaborate on:
You clearly are aware of something I am not. |
Also, I'm not sure what it means, but FWIW HyperApp was actually the fastest in the async version of the benchmark (mithril was not even close, I wonder what that is about). 😄 |
I've done impls of a lot of benchmarks. This one is by far the most representative of expected perf and highly stable between runs due to its methodology. Basically, this bench tends to accurately reflect the performance results of all other benches and covers enough surface area not to only test a couple specific cases (like dbmon). There's nothing TodoMVC bench will tell you that you won't find out more thoroughly and with better feedback from There are other good ones, like uibench and vdom-benchmark but they don't have the most up-to-date impls of other libs, so it's difficult to compare vs most recent lib versions. They also dont have great output for assessing relative perf in an intuitively-colored scale.
If your implementation or lib is async, rather than relying on the console timers, you should open up chrome's timeline view and record the perf between actions. Then look at "Scripting time", etc in the pie chart. |
I added some hints how to start your implementation in the README of js-framework-benchmark at the bottom. Just let me know if that helps. If you have specific questions don't hesitate to ask. |
@jbucaran I bet the bigger the app, the worse hyper will perform. try that benchmark with a website that has 1000s of components |
@ccorcos of course, absolutely, because each "app" can sucks more than the framework with which it is built. No matter which is the "framework". 2c :D |
well my point is if you wanted to build a custom visualization or some kind of dashboard, the lack of laziness is going to become a problem. i dont mean to be a put-down -- I like what you guys are building here |
Related question: does hyperapp currently re-use old DOM nodes when rendering? (especially when unchanged) |
tl;dr
I followed @leeoniya's suggestion and implemented the js-framework-benchmarks. What benchmarks were used?ResultsHardwareNotes
|
To me the most interesting result is create 1,000 rows where hyperapp is twice as fast as all the others whereas create 10,000 is in the range of others. I think you managed to trick my benchmark runner in this case I'm afraid I wouldn't take that result as granted... |
Yep, that was my mistake when adding the frame, it's fixed already. 🙇 |
Some improvements: #124. |
Just curious, what led you to implement another view renderer instead of using an existing one? File size? |
@nichoth 🤔 I can think of two reasons: one is file size; I am willing to trade some performance for less bytes. If you look at the git history you'll see we went from virtual-dom, to morphodom, then Snabbdom and finally the current custom engine. After #124 lands we'll be 1869 bytes, <=1500 without the Router. So, 1kb is more of a stretch now, but it's still in the same range. Also, speed will have improved significantly. See the js-framework-benchmarks above 🔥. The other reason is: I wanted the entire source of truth in a single place. Whenever I try to understand how some library X works, I'm often disappointed that I have to go through dozens of modules, also with deps themselves, and sometimes not written by the same person, which usually translates to quite different coding styles. |
Should we consider using switch statements for perf improvement? They create lookup tables and are optimized for string evaluation especially. Only a few flat if trees would benefit from this however |
@selfup 🤔 If it makes things any faster, then why not, I guess. Won't switch statements take more space than if else? |
@jbucaran they have low entropy. With gzip it shouldn't matter. |
I think we can close here and continue to track future optimization efforts in #183. Since 0.8.0, and with the introduction of keys, our patch/diff algorithm became more complex (but also more powerful and useful). Performance is now around 1.34~1.37, which is still fine. |
Summary
|
It appears there's no laziness at all in hyperapp -- no diff of props:
https://github.com/hyperapp/hyperapp/blob/f29647bf9da4bc281078abcacd116031f9fb0c3e/src/app.js#L159-L163
Have you tried this out in a large application with 1000s of nodes?
The text was updated successfully, but these errors were encountered: