Swizz/snabbdom-pragma

Performance improvements

Swizz opened this issue · 18 comments

Swizz commented

I'm curious to know more about how to measure performance in op/sec, to have a comparison between :

  • snabbdom-pragma 2.1.0
  • snabbdom-pragma 1.10.0
  • snabbdom/h 0.6.6
Swizz commented

Bad news...

Snabbdom-pragma@1  =>  20346 op/s [avg: 0.491ms]
Snabbdom-pragma@2  =>  9622 op/s [avg: 1.039ms]
Snabbdom/h  =>  65803 op/s [avg: 0.152ms]

for

Snabbdom.createElement('div', null, 'Hello', 13)
Swizz commented

Plan to move to Ramda Lodash instead of builtin map/reduce/filter ?

Swizz commented

Partial lodash experiment :

Snabbdom-pragma@1  =>  21607 op/s [avg: 0.462ms]
Snabbdom-pragma@2  =>  27133 op/s [avg: 0.368ms] (lodash here)
Snabbdom/h  =>  67558 op/s [avg: 0.148ms]
  • take note the fact that h is literally doing nothing
Swizz commented

Which is better ? Speed or Weight ?

Swizz commented

I aimed to be dependency free. So what about using is and lodash and produce a dist file which be dependency free with tree shacking ?

Swizz commented

@jvanbruegge Are Snabbdom-pragma performances for Snabbdom and Cyclejs users a priority ?

I would go for dependency free, as this is affecting the users bundle size.
I think Prepack can get rid of the snabbdom-pragma overhead.
Can you test it too?

Swizz commented

I made a brief tests, and seen a tiny difference regarding the lodash implementation ones.

The prepack stuffs need to be done after the project use of Snabbdom.createElement, at our state, this is unrelevant.

Only the dist/index.js is used in most case with the basic import ... from .... So, it could be good to import with tree shacking only the requested functionnalities from Lodash, isnt it ?

what is the compiled js after prepack? Sorry, I'm on mobile

Swizz commented

On mobile too, I'll take a look after lunch.

Swizz commented

Here you are

Prepack isnt in love with exports/require, so it needed to do some hacks to work with..
Prepack didn't replace Array.prototype.map, Array.prototype.reduce, etc.., functions that are costly for us.
Prepack works fine for the finnal duty at the production bundling, not our case.
Prepack will be good after transpiling, to catch Snabbdom.createElement invariant results.

I mean prepack on the file that is using JSX.
I assume that it optimizes snabbdom-pragma away and replaces it with just the correct h call

How much does lodash add to the size?

Swizz commented

Following @caridy response :

It does return just an object, and yes, h() does more, it has a great deal of flexibility in the order of the arguments, and it supports compound sel value, but neither of those are things that you care about because they can't be express in JSX, so, for you it will be the same. I also recommend creating a custom h() for projects that are mores restrictive, and expect better perf by removing all that logic that we have in h().

Snabbdom@2 is not calling h() anymore


In fact, we loose in perf due to the switch from for loop to map/reduce.

Snabbdom-pragma@1 was 2.76 KB (1.67 KB compressed)
Snabbdom-pragma@2 is 4.9 KB (3.0 KB compressed)

I were happy to rewrite Snabbdom-pragma in a more FP way following the Snabbdom contributor advice, but I realise, it was a big loss in all points.

Some ES6 features I overuse result to a big transpiled code. Destructuring, rest operator, etc..


For lodash size, I'll need to try, but we can count 3 or 4 functions : flatten, map, reduce, fromPairs (?).
So we can hope no more than 1 KB.

Swizz commented

I dont know how this is calculated, but npm-cost, give me other results :
https://cost-of-modules.herokuapp.com/?p=snabbdom-pragma@2.2.0
https://cost-of-modules.herokuapp.com/?p=snabbdom-pragma@1.10.0

snabbdom-pragma@1 : 3.49 KB
snabbdom-pragma@2 : 3.56 KB

Snabbdom-pragma@1 => 20346 op/s [avg: 0.491ms]
Snabbdom-pragma@2 => 9622 op/s [avg: 1.039ms]
Snabbdom/h => 65803 op/s [avg: 0.152ms]

How do you get those numbers? I'm interested in trying to improve the performance

Swizz commented

I was using a custom implementation using time/timeEnd.

But we should use mafintosh/nanobench

Do you have any script that i can get and run myself?