frejs / fre

:ghost: Tiny Concurrent UI library with Fiber.
https://fre.deno.dev
MIT License
3.71k stars 350 forks source link

+ to benchmarks #271

Open tomByrer opened 3 years ago

tomByrer commented 3 years ago

Very interesting take on JSX!

Would be helpful to compare performance: https://github.com/krausest/js-framework-benchmark I'm guessing a bit better than Inferno?

relevant discussion

yisar commented 3 years ago

@tomByrer This issue is hard to measure.

What time slicing improves is response performance, which can make your page no longer blocked.

However, the total time of page rendering is longer than that of synchronous rendering (such as Inferno).

So it's unfair for fre to just measure the rendering time.

Can you understand me?

yisar commented 3 years ago

微信图片_20210606191240

I refactor the algorithm again, and then used a new technique called ofscreen rendering

This is a technology similar to DocumentFragment. It operates DOM in memory and finally paints to the screen at final time.

Now fre is super fast, even faster than vanilla js.

tomByrer commented 3 years ago

Oh wow, cheers!

yisar commented 3 years ago

cc @ryansolid , Hey my friend, I saw your reply on twitter. My country forbids me to login twitter. I want to reply to you here.

This optimization is also called Offscreen rendering. It was inspired by IOS UIkit / Opengl and so on.

Fre operates DOM in memory and paint them to the screen once at the last time.

https://thoughtbot.com/blog/designing-for-ios-graphics-performance

I haven't used the DocumentFragment API, just that their ultimate behavioral results are similar.

I generate an effect list in reverse order in the reconcile phase, and insert them into the screen in reverse order in the commit phase.

This is a pure data structure and algorithm optimization.

Of course, Fiber structure and two-phase traversal do provide convenience, but other singlepass frameworks (such as Vue or preact) are not completely impossible to implement this algorithm.

It is worth mentioning that offscreen rendering is an optimization during the commit phase, It has little to do with concurrent mode, and time slicing is not necessary.

ryansolid commented 3 years ago

To be clear I don't doubt the algorithmic/scheduling improvement. Just when people say faster than vanillajs, some clarification is needed as vanillajs(hand crafted and optimized for the specific solution) by its very nature should be the fastest. So generally I treat that claim with skepticism.

yisar commented 3 years ago

its very nature should be the fastest. So generally I treat that claim with skepticism.

The runtime algorithm with off-screen rendering is faster than vanillajs without off-screen optimization. Maybe it’s more appropriate to say that?

yisar commented 3 years ago

@ryansolid 微信图片_20210607231854 微信图片_20210607231906

In order to verify the results, I tested again. I was an i7 7700k windows computer, using an M6000 graphics card.

The actual test of fre off-screen rendering has been faster than vanillajs, while solidjs and vanillajs are almost the same.

I tested on another low configuration computer and found that the fre off-screen rendering still can be close to vanillajs , which is much better than other vdom frameworks.

ryansolid commented 3 years ago

Where/what is this test? When you say offscreen rendering are you also including the cost of applying it on screen. If JS Framework is no good to show this off.. maybe like UIBench(https://github.com/localvoid/uibench)? Its basically tailored for comparing VDOM reconcilers.

EDIT: What is particularly good about it is it can measure the pure reconciler time or the time + paint. I usually ignore the non-paint scores but it can be useful to look at our algorithm speeds. One of the weirdest things about Solid is the non-paint times are slower comparatively to VDOM libraries, but when you add the paint in suddenly things are much closer. I'm gathering it is because the way it is measured and Solid's use of synchronous updates. Solid literally mutates the DOM immediately so even if we aren't capturing paints you would be capturing DOM mutations. Anyway I digress. This is probably a better comparison with peers.

mindplay-dk commented 3 years ago

I went ahead and built out a benchmark:

https://github.com/krausest/js-framework-benchmark/compare/master...mindplay-dk:fre2-keyed

Apparently it's the second time I've done that, but I forgot, haha - this one is a bit cleaner though, with a simpler Rollup build.

Unfortunately, the latest published release 2.2.0 appears to have a console.log statement in it. 😬

@yisar can you publish a fresh release, please? (the console.log statement is present in the dist/fre.js but not in the source files, so you probably did this accidentally while debugging...)

I've only been able to run it by manually entering the URL after manually building - I don't have all the system dependencies set up, and the instructions in the README didn't work for me, I think they're outdated.

@ryansolid presumably you have it running? Maybe you can pull my branch and try it? so we can see what's what. 🙂

yisar commented 3 years ago

@mindplay-dk v2.2.1 has been released. You can see the specific forces here https://github.com/yisar/fre/blob/master/demo/src/benchmark.tsx

yisar commented 3 years ago

@mindplay-dk As last time, this test seems unable to accurately test the framework with time slicing. Almost all frameworks use microtask.

971d20476bd076e4f7383e0d1fcba61

yisar commented 3 years ago

@mindplay-dk I played the benchmark this afternoon today, but it seems to be slower than expected. Next, I will make some adjustments for the test. At present, it seems that we should do diff props in advance, not here: https://github.com/yisar/fre/blob/master/src/dom.ts#L4 Wait for me.

lxsmnsyc commented 3 years ago

There's a lot of improvements to be made:

Still trying to find some core issues. To summarize, most FP methods of arrays are generally slow due to spec-related implementation. It would be better if you can implement/simplify your own array transformations just to provide faster paths. I may be wrong on some of the details I provided, feel free to rebench.

yisar commented 3 years ago

@LXSMNSYC Thank you. You're right, but the most important thing is to implement fre.memo This is more important for that benchmark use case. This is also the reason why fre slows down. Especially when the speed is reduced by 16 times. You said that the optimization of codes is also very reasonable. I will modify them slowly. Thank you!

d84bc8846c7e0e027efb6add45c8b78

lxsmnsyc commented 3 years ago

Yes. That's one of the issues with Vue before up until 3.2 when they decided to introduce v-memo. If you can implement that then that would provide a lot of render skip process.

aleclarson commented 2 years ago

Is this a regression, or does Fre really use that much more memory and take that long for a partial update?

image

yisar commented 2 years ago

No, the current benchmark performance metrics for fre are mainly due to the fact that the fre.memo API is not implemented, resulting in thousands of duplicate component updates. https://github.com/krausest/js-framework-benchmark/blob/master/frameworks/keyed/react-hooks/src/main.jsx#L67