Git Product home page Git Product logo

krausest / js-framework-benchmark Goto Github PK

View Code? Open in Web Editor NEW
6.5K 105.0 811.0 151.66 MB

A comparison of the performance of a few popular javascript frameworks

Home Page: https://krausest.github.io/js-framework-benchmark/

License: Apache License 2.0

CSS 0.07% HTML 2.44% JavaScript 80.66% TypeScript 13.20% Elm 0.18% Vue 0.19% Scala 0.15% PureScript 0.08% Shell 0.04% Clojure 0.21% Nix 0.02% Haskell 0.22% Rust 2.08% Batchfile 0.01% Reason 0.17% Riot 0.08% Dhall 0.01% C# 0.07% Handlebars 0.09% Marko 0.03%

js-framework-benchmark's Introduction

Please note: There's an issue with chrome 124 such that we don't get reliable values. Currently all PRs are blocked by this issue.

js-framework-benchmark

This is a simple benchmark for several javascript frameworks. The benchmarks creates a large table with randomized entries and measures the time for various operations including rendering duration.

Screenshot

Security advice

Currently there are 186 implemenations in this repository. It's of course impossible for me to make a security assessment for all those implementations. npm ci and npm install can execute arbitraty commands, so they should be executed only for packages you trust. Consequently I build on a dedicated virtual private linux server such that I don't have to install the packages for all those implemenations on my laptop. There's a prebuild build.zip for each chrome release you can download such that you can avoid installing the packages from all implementations. (I don't know of any (attempted) case for malicious packages in this repository, so please take it just as a general warning.)

The server implemenation in this repository should only be started on your local machine and access should be restricted to your local machine. I recommend against starting the server such that it can be publically accessed from the internet.

About the benchmarks

The following operations are benchmarked for each framework:

  • create rows: Duration for creating 1,000 rows after the page loaded (no warmup).
  • replace all rows: Duration for replacing all 1,000 rows of the table (with 5 warmup iterations).
  • partial update: Time to update the text of every 10th row for a table with 10,000 rows (with 5 warmup iterations).
  • select row: Duration to highlight a row in response to a click on the row. (with 5 warmup iterations).
  • swap rows: Time to swap 2 rows on a table with 1,000 rows. (with 5 warmup iterations).
  • remove row: Duration to remove a row for a table with 1,000 rows. (with 5 warmup iterations).
  • create many rows: Duration to create 10,000 rows (no warmup)
  • append rows to large table: Duration for adding 1,000 rows on a table of 10,000 rows (no warmup).
  • clear rows: Duration to clear the table filled with 10,000 rows. (no warmup)
  • ready memory: Memory usage after page load.
  • run memory: Memory usage after adding 1,000 rows.
  • update memory: Memory usage after clicking 5 times update for a table with 1,000 rows.
  • replace memory: Memory usage after clicking 5 times create 1,000 rows.
  • repeated clear memory: Memory usage after creating and clearing 1,000 rows for 5 times.
  • update memory: Memory usage after clicking 5 times update for a table with 1,000 rows.
  • startup time: Duration for loading and parsing the javascript code and rendering the page.
  • consistently interactive: The lighthouse metric TimeToConsistentlyInteractive: A pessimistic TTI - when the CPU and network are both definitely very idle. (no more CPU tasks over 50ms)
  • script bootup time: The lighthouse metric ScriptBootUpTtime: The total ms required to parse/compile/evaluate all the page's scripts
  • main thread work cost: The lighthouse metric MainThreadWorkCost: Total amount of time spent doing work on the main thread includes style/layout/etc.
  • total byte weight: The lighthouse metric TotalByteWeight: Network transfer cost (post-compression) of all the resources loaded into the page.

For all benchmarks the duration is measured including rendering time. You can read some details on this article and in the wiki. Starting with chrome 118 the overall performance is computed as a weighted geometric mean.

Official results

Official results are posted on the official results page. My blog has a few articles about the benchmark. Older results of this benchmark are outlined on my blog (round 1, round 2, round 3, round 4, round 5, round 6, round 7 and round 8).

Snapshot of the results

The current snapshot that may not have the same quality (i.e. results might be for mixed browser versions, number of runs per benchmark may vary) can be seen here Results

Keyed vs non-keyed frameworks

Some frameworks like React, Vue.js or Angular, allow you to create a 1:1 relationship between a data item and a DOM node by assigning a “key” attribute (or for Angular, specifying “trackBy” in *ngFor). If you use some identifier of the data as the key, you get the “keyed” mode. Any update to the data will update the associated DOM node. If you reorder the list, the DOM nodes will be reordered accordingly.

The other mode is “non-keyed” and this is what e.g. vue.js uses by default for lists. In this mode, a change to the data items can modify DOM nodes that were associated with other data before. This can be more performant, since costly DOM operations can be avoided (e.g. first removing old nodes and then adding new nodes) and the existing DOM nodes are updated to display the new data. For React and Angular, using the item index as the key uses “non-keyed” mode for those frameworks.

Depending on your requirements, the “non-keyed” mode can be a performance gain or can cause severe problems, so one must carefully choose the mode and check that the framework supports that mode.

Read more here: https://www.stefankrause.net/wp/?p=342

1 Run pre-built binaries for all frameworks

There are currently 186 implementations in this repository. Installing (and maintaining) those can be challenging, but here are simplified instructions how to get started. See the security advice above to read why that might be a good idea.

1.1 Prerequisites

Have node.js (>=v20.9.0) installed. If you want to do yourself a favour use nvm for that. The benchmark has been tested with node v20.9.0. Please make sure that the following command work before trying to build:

> npm
npm -version
10.1.0
> node --version
v20.9.0

1.2 Downloading the pre-built binaries and starting the server

building all frameworks can be challenging. There's a new way that allows to skip that and just run the benchmark without builiding all implementations.

Start with checking out a tagged release like that. Pick the release that you want (e.g. chrome 100):

git clone https://github.com/krausest/js-framework-benchmark.git
cd js-framework-benchmark
git checkout chrome100 -b release
npm ci && npm run install-local

Download the build.zip for that release from https://github.com/krausest/js-framework-benchmark/releases and put the build.zip into the js-framework-benchmark directory and unzip the prebuilt files:

unzip build.zip

You're now ready to start the http-server. Let the server run in the background

npm start

1.3 Running the benchmarks and handling errors

In a new console window you can now run the benchmarks:

npm run bench

This will take some time (currently about 12 hours on my machine). Finally create the results table:

npm run results

Open js-framework-benchmark/webdriver-ts-results/table.html in a browser and take a look at the results. You can open the result table with the link http://localhost:8080/webdriver-ts-results/dist/index.html

Here's what you should do when the benchmark run was not successful. Let's assume the benchmark printed the following to the console:

================================
The following benchmarks failed:
================================
Executing frameworks/non-keyed/ef-js and benchmark 04_select1k failed: No paint event found
run was not completely successful Benchmarking failed with errors

You'll now have to run the benchmark again for those that failed like that:

npm run bench -- --framework non-keyed/ef-js --benchmark 04_

The you can then continue with creating the results table npm run results. Another workaround is to delete the folders of frameworks you can't run or you are not interested in.

2 The old and hard way: Building the frameworks and running the benchmark

2.1 Prerequisites

Have node.js (>=v16.14.2) installed. If you want to do yourself a favour use nvm for that and install yarn. The benchmark has been tested with node vv16.14.2. For some frameworks you'll also need java (>=8, e.g. openjdk-8-jre on ubuntu). Please make sure that the following command work before trying to build:

> npm
npm -version
8.5.0
> node --version
v16.14.2
> echo %JAVA_HOME% / echo $JAVA_HOME
> java -version
java version "1.8.0_131" ...
> javac -version
javac 1.8.0_131

2.2 Start installing

As stated above building and running the benchmarks for all frameworks can be challenging, thus we start step by step...

Install global dependencies This installs just a few top level dependencies for the building the frameworks and a local web server.

npm ci

Then install the server:

npm run install-server

We start the local web server in the root directory

npm start

Verify that the local web server works: Try to open http://localhost:8080/index.html. If you see something like that you're on the right track: Index.html

Now open a new terminal window and keep the web server running in background.

2.3 Building and viewing a single framework

We now try to build the first framework. Go to the vanillajs reference implementation

cd frameworks/keyed/vanillajs

and install the dependencies

npm ci

and build the framework

npm run build-prod

There should be no build errors and we can open the framework in the browser: http://localhost:8080/frameworks/keyed/vanillajs/

Some frameworks like binding.scala or ember can't be opened that way, because they need a 'dist' or 'target/web/stage' or something in the URL. You can find out the correct URL in the index.html you've opened before or take a look whether there's a customURL property under js-framework-benchmark in the package.json that represents the url.

2.4 Running benchmarks for a single framework

The benchmark uses an automated benchmark driver using chromedriver to measure the duration for each operation using chrome's timeline. Here are the steps to run is for a single framework:

cd ../../..
cd webdriver-ts

and install the dependencies

npm ci

and build the benchmark driver

npm run compile

now run the benchmark driver for the vanillajs-keyed framework:

npm run bench keyed/vanillajs

Just lean back and watch chrome run the benchmarks. If it doesn't complain then the html for the table should be fine and your categorization as keyed or non-keyed should also be correct.

You should keep the chrome window visible since otherwise it seems like paint events can be skipped leading to wrong results. On the terminal will appear various log statements.

The results for that run will be saved in the webdriver-ts/results directory. We can take a look at the results of a single result:

cat results/vanillajs-keyed_01_run1k.json
{"framework":"vanillajs-keyed","benchmark":"01_run1k","type":"cpu","min":135.532,"max":154.821,"mean":143.79166666666666,"median":141.022,"geometricMean":143.56641695989177,"standardDeviation":8.114582360718808,"values":[154.821,135.532,141.022]}

As you can see the mean duration for create 1000 rows was 144 msecs.

You can also check whether the implementation appears to be compliant to the rules:

npm run isKeyed keyed/vanillajs

If it finds anything it'll report an ERROR.

2.5 Building the result table

Install libraries:

cd ..
cd webdriver-ts-results
npm ci
cd ..
cd webdriver-ts

In the webdriver-ts directory issue the following command:

npm run results

Now a result table should have been created which can be opened on http://localhost:8080/webdriver-ts-results/dist/index.html. There's nothing in table except for the column vanillajs-keyed at the right end of the first table. First Run Results

2.6 [Optional] Updating the index.html file

This simply rebuilds the file used to display the table, not the results.

npm run index

2.7 [Optional] Building and running the benchmarks for all frameworks

This is not for the faint at heart. Please read the security advice before running this command. You can build all frameworks by issuing:

cd ..
npm run rebuild-all

After downloading the whole internet it starts building it. Basically there should be no errors during the build, but I can't guarantee that the dependencies won't break.

You can now run the benchmark for all frameworks by invoking:

npm run bench-all

in the root directory.

After that you can check all results in http://localhost:8080/webdriver-ts/table.html.

3 Tips and tricks

  • You can run multiple implementations by passing their directory names (cd to webdriver-ts): npm run bench keyed/angular keyed/react.
  • You can select multiple frameworks and benchmarks for running with prefixes like in the following example in the webdriver-ts directory: npm run bench -- --benchmark 01_ 02_ --framework keyed/vanillajs keyed/react-hooks runs the test for all frameworks that contain either angular or bob, which means all angular versions and bobril and all benchmarks whose id contain 01* or 02*
  • The memory benchmarks assume certain paths for the chrome installation. If it doesn't fit use npm run bench -- --chromeBinary /usr/bin/google-chrome
  • If you can't get one framework to compile or run, just move it out of the frameworks directory and re-run
  • One can check whether an implementation is keyed or non-keyed via npm run isKeyed in the webdriver-ts directory. You can limit which frameworks to check in the same way as the webdriver test runner like e.g. npm run isKeyed keyed/svelte. The program will report an error if a benchmark implementation is incorrectly classified.

4. Contributing a new implementation

4.1 Example instructions for a real implementation

Thanks @dsvorc41 for providing the following description: TL;DR: demo

  1. Install all of the root-level dependencies
    1. cd js-framework-benchmark/
    2. npm ci or npm i
    3. npm run install-local
  2. Make a new directory for your desired framework, for example Fast framework: mkdir /frameworks/keyed/fast
  3. Set up your new directory in whatever way is appropriate for that framework, for example:
    1. Set up prettier, eslint, dependencies (i.e. @microsoft/fast-element) etc
    2. Create index.html in the root of your folder where your app will be served touch /frameworks/keyed/fast/index.html
    3. Note: your html file must use the global CSS styles <link href="/css/currentStyle.css" rel="stylesheet" />
  4. Serve the page - Test that your html page is loaded properly in the browser
    1. For example put <h1>Hello World - Fast Framework</h1> somewhere
    2. Run the server from the root directory: npm start
    3. Visit your page in the browser (URL follows the folder structure): http://localhost:8080/frameworks/keyed/fast/index.html
    4. Note: Its important to always start the server from the root, because that way you'll get access to global CSS that all apps must share
    5. Note 2: AVOID SHADOW DOM - if your framework relies on Shadow Dom (like Fast framework does), you should turn it off. Otherwise you won't get access to global CSS.
  5. Add the "action triggers" - buttons that all apps must have (see frameworks/keyed/vanillajs/index.html)
    1. Note: Action triggers are simply buttons that are used to run the benchmarks (adding rows, deleting rows, swapping them, etc). Those buttons can be static HTML, or you can render them dynamically (with JS) with your framework of choice
    2. Make sure your HTML elements have the same classes and structure as VanillaJS, otherwise benchmarks won't be able to find your elements on the page, and you will not get the global CSS (Bootstrap)
    3. Add the html example below and open the page. You should see nicely formatted elements on the page, like in the GIF image above.
    4. Example for action triggers
          <body>
            <div id="main">
              <div class="container">
                <div class="jumbotron">
                  <div class="row">
                    <div class="col-md-6">
                      <h1>VanillaJS-"keyed"</h1>
                    </div>
                    <div class="col-md-6">
                      <div class="row">
                        <div class="col-sm-6 smallpad">
                          <button
                            type="button"
                            class="btn btn-primary btn-block"
                            id="run"
                          >
                            Create 1,000 rows
                          </button>
                        </div>
                        <div class="col-sm-6 smallpad">
                          <button
                            type="button"
                            class="btn btn-primary btn-block"
                            id="runlots"
                          >
                            Create 10,000 rows
                          </button>
                        </div>
                        <div class="col-sm-6 smallpad">
                          <button
                            type="button"
                            class="btn btn-primary btn-block"
                            id="add"
                          >
                            Append 1,000 rows
                          </button>
                        </div>
                        <div class="col-sm-6 smallpad">
                          <button
                            type="button"
                            class="btn btn-primary btn-block"
                            id="update"
                          >
                            Update every 10th row
                          </button>
                        </div>
                        <div class="col-sm-6 smallpad">
                          <button
                            type="button"
                            class="btn btn-primary btn-block"
                            id="clear"
                          >
                            Clear
                          </button>
                        </div>
                        <div class="col-sm-6 smallpad">
                          <button
                            type="button"
                            class="btn btn-primary btn-block"
                            id="swaprows"
                          >
                            Swap Rows
                          </button>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
                <table class="table table-hover table-striped test-data"> 
                  <!-- your dynamic content should render here --> 
                </table>
              </div>
            </div>
          </body>
  6. Generate dummy data for rendering
    1. See frameworks/keyed/fast/src/utils/build-dummy-data.ts as an example
    2. Note: id is an important attribute and it must be initialized as 1, and continuously incremented. The only time id resets back to 1 is when the page reloads - otherwise it should just keep incrementing each time a new row is created. Doing anything else will cause errors when benchmarks try to find elements with specific IDs. Trust me, I learned the hard way.
  7. . Your app needs to support several actions that correspond to "Action triggers" listed above. Here's an example from Fast framework frameworks\keyed\fast\src\App.ts and frameworks\keyed\fast\src\components\Table.ts:
    1. Code example:
        export class BenchmarkApp extends FASTElement {
          createOneThousandRows() {}
          createTenThousandRows() {}
          appendOneThousandRows() {}
          updateEveryTenthRowLabel() {}
          deleteAllRows() {}
          swapTwoRows() {}
          deleteSingleRow(rowId: number) {}
        }
      
        export class Table extends FASTElement {
          selectRow(rowId: number) {}
        }
    2. Note: your app doesn't need methods with the same name - you should write idiomatic code and follow the best practices of your framework of choice. The example above is just to give you an idea of which operations must be supported, but how you choose to implement those methods can be very different from one framework to the next.
  8. Manually testing your app - do this before you run the benchmarks
    1. Open your page and click on the buttons, make sure your app adds 1000 rows, then removes them, or swaps them, or adds/removes 10,000 rows.
    2. To do this, you'll probably need to watch your local files and compile them into some sort of a bundle, like frameworks\keyed\fast\dist\bundle.js which will be loaded through a script tag in your HTML file
    3. For example, in Fast folder we have webpack watching our files: "dev": "rimraf dist && webpack --config webpack.config.js --watch --mode=development",
    4. That means we have two terminal tabs running
      1. One for the server from the root folder npm start
      2. And another in our local folder where webpack is watching the files
  9. Run the single benchmark for your framework
    1. Once you manually verified that everything works as expected, run a single benchmark and make sure all of the tests are running
    2. If you forgot something, one of the benchmarks will probably fail - for example it won't be able to find an element on the page or similar
    3. Keep the server in the root folder running npm start, and in another terminal tab, also from the root folder run npm run bench -- --framework keyed/fast (or whatever is your framework keyed/react, keyed/angular, etc.).
    4. The benchmark runner will open and close Chrome multiple times. The whole thing will take a couple of minutes.
  10. Optional: run the benchmark for VanillaJS as comparison
    1. npm run bench -- --framework keyed/vanillajs
  11. Build the report
    1. npm run results
  12. Open the report in your browser (NOTE: the server must still be running if you want to see this page)
    1. http://localhost:8080/webdriver-ts-results/table.html

4.2 Building the app

For contributions it is basically sufficient to create a new directory for your framework that supports npm install and npm run build-prod and can be then opened in the browser. All other steps are optional. Let's simulate that by copying vanillajs.

cd ../frameworks/keyed
cp -r vanillajs super-vanillajs
cd super-vanillajs

Then we edit super-vanillajs/index.html to have a correct index.html:

<title>Super-VanillaJS-"keyed"</title>
...
                    <h1>Super-VanillaJS-"keyed"</h1>

In most cases you'll need npm install and npm run build-prod and then check whether it works in the browser on http://localhost:8080/frameworks/keyed/super-vanillajs/.

(Of course in reality you'd rather throw out the javascript source files and use your framework there instead of only changing the html file.)

4.3 Adding your new implementation to the results table.

(Notice: Updating common.ts is no longer necessary, super-vanillajs is visible in the result table)

Your package.json must include some information for the benchmark. Since you copied it, the important section is already there:

  ...
  "js-framework-benchmark": {
    "frameworkVersion": "",
    "frameworkHomeURL": ""
  },
  ...

This one is a bit exceptional since vanillajs has no version and there no framework involved. If you use a normal framework like react it carries a version information and the framework should have an URL. For most frameworks you'll add a dependency to your framework in package.json. The benchmark can automatically determine the correct version information from package.json and package-lock.json if you specify the package name like that:

  "js-framework-benchmark": {
    "frameworkVersionFromPackage": "react"
    "frameworkHomeURL": "https://www.reactjs.org"
  },

Now the benchmark will fetch the installed react version from package-lock.json in the react directory and use that version number to compute the correct version string. If your library has multiple important packages like react + redux you can put them separated with a colon there like "react:redux". If you don't pull your framework from npm you can hardcode a version like "frameworkVersion": "0.0.1". The other important, but optional properties for js-framework-benchmark are shown in the following example:

"customURL": "/target/web/stage",
"useShadowRoot": true

You can set an optional different URL if needed or specify that your DOM uses a shadow root.

4.4 Submitting your implementation

Please take a look at https://github.com/krausest/js-framework-benchmark/wiki/Process-for-merging-a-pull-request for informations how pull requests are merged.

Contributions are very welcome. Please use the following rules:

  • Name your directory frameworks/[keyed|non-keyed]/[FrameworkName]
  • The package.json in your directory must contain some important information see section 4.2 above.
  • Each contribution must be buildable by npm install and npm run build-prod command in the directory. What build-prod does is up to you. Often there's an npm run dev that creates a development build
  • Every implementation must use bootstrap provided in the root css directory.
  • All npm dependencies should be installed locally (i.e. listed in your package.json). Http-server or other local web servers should not be local dependencies. It is installed from the root directory to allow access to bootstrap.
  • Please use fixed version numbers, no ranges, in package.json. Otherwise the build will break sooner or later - believe me. Updating works IMO best with npm-check-updates, which keeps the version format.
  • Webdriver-ts must be able to run the perf tests for the contribution. This means that all buttons (like "Create 1,000 rows") must have the correct id e.g. like in vanillajs. Using shadow DOM is a real pain for webdriver. The closer you can get to polymer the higher the chances I can make that contribution work.
  • Don't change the ids in the index.html, since the automated benchmarking relies on those ids.
  • Please push only files in your framework folder (not index.html or results.json)
  • Please make sure your implementation is validated by the test tool. cd to the root directory and perform a check npm run rebuild-ci [keyed|non-keyed]/[FrameworkName]. It'll print an error if your framework doesn't build, the benchmark can't be run or behaves other as specified. It'll print a big ERROR explaining if it isn't happy with the implementation. Some common errors include:
    • Your package.json is missing some required fields
    • Incorrect classification (Keyed/NonKeyed)
    • You have gzipped files in /dist (unfortunately the web server prefers these when they exist)
  • Please don't commit any of the result file webdriver-ts/table.html, webdriver-ts-results/src/results.ts or webdriver-ts-results/table.html. I use to run the benchmarks after merging and publish updated (temporary) results.
  • The latest stable chrome can be used regarding web features and language level (babel-preset-env "last 1 chrome versions")
  • The vanillajs implementations and some others include code that try to approximate the repaint duration through javascript code. Implementations are not required to include that measurement. Remember: The real measurements are taken by the automated test driver by examining chrome timeline entries.
  • Please don't over-optimize. This benchmark is most useful if you apply an idiomatic style for the framework you're using. We've sharpened the rules what kind of implementation is considered correct and will add errors or notes when an implementations handles things wrongly (errors) or in a way that looks like a shortcut (notes).
    • The html must be identical with the one created by the reference implementation vanillajs. It also must include all the aria-hidden attributes. Otherwise the implementation is considered erroneous and will be marked with issue #634.
    • Keyed implementations must pass the npm run isKeyed test in the test driver otherwise they are erroneous. Not that this test might not be sufficient, but just necessary to be keyed (from time to time we find new loop holes). There's error #694 for such cases.
    • Using request animation frame calls in client code, especially when applied only for some benchmark operations, is considered bad style and gets note #796 applied. Note that frameworks are free to choose whether they use RAF of not.
    • Manual DOM manipulation (like setting the danger class directly on the selected row) lead to some controversial debates. Depending on the framework you're using it might be idiomatic style or not. In any case it gets note #772 applied.
    • Implementations should keep the selected rows in the state (i.e. not a flag for each row, but one reference, id or index for the table) and use that information for rendering. Keeping a selection flag for each row might be faster, but it's considered bad style. Thus those implementations get note #800.
    • Explicit event delegation is another area where many discussions came up. Implementations that use explicit event delegation in client code get note #801. Frameworks themselves are free to use event delegation.

Helpful tips:

  • Do not start your implementation using vanillajs as the reference. It uses direct DOM manipulation (and thus has note #772) and serves only as a performance baseline but not as a best practice implementation. Instead pick a framework which is similar to yours.
  • Do not forget to preload the glyphicon by adding this somewhere in your HTML: <span class="preloadicon glyphicon glyphicon-remove" aria-hidden="true"></span> or you will get terrible performance.
  • Be careful not to leave gzipped files in your /dist directory. Unfortunately the web server prefers these when they exist and we cannot change that (meaning you could be observing an outdated build).

This work is derived from a benchmark that Richard Ayotte published on https://gist.github.com/RichAyotte/a7b8780341d5e75beca7 and adds more framework and more operations. Thanks for the great work.

Thanks to Baptiste Augrain for making the benchmarks more sophisticated and adding frameworks.

History

Frameworks without significant activity on github or npm for more than a year will be removed (automatic commits like dependabot and minor updates, like docs editions, are ignored).

2023-12-10

The following frameworks were archived after chrome 120. Their last results are included in chrome 120 results.

  • petite-vue

2023-11-07

The following frameworks were archived after chrome 119. Their last results are included in chrome 119 results.

  • sifrr

2023-10-22

The following frameworks were archived after chrome 118. Their last results are included in chrome 118 results.

  • 1more
  • bdc
  • choo
  • domdiff
  • domvm
  • endorphin
  • etch
  • forgo
  • fullweb-helpers
  • fullweb-template
  • heresy
  • hullo
  • lighterhtml
  • neverland
  • resonatejs
  • sledgehammer
  • uhydro

2020-7-9

  • etch Last commit Sep 12, 2018
  • hyperoop Last significant commit Dec 23, 2018
  • faster-dom (to be replaced by a new revact implementation)
  • plastiq (to be replaced by a new Hyperdom implementation)
  • rawact Last commit Dec 3, 2018
  • react-djinn Last NPM publish 2019-05-03 (the Github org a repo aren't available anymore)
  • react-lite Last commit Mar 29, 2019
  • redux-combiner Last commit May 14, 2018
  • surplus Last commit Jan 5, 2019
  • gruu Last commit Jun 23, 2019
  • lite-html Last commit Sep 7, 2018

2019-9-16

  • angular-light Last commit Nov 30, 2017
  • nx. Last commit Feb 2017
  • maik-h Last commit Dec 15, 2017
  • rivets Last commit Oct 22, 2016
  • tsers. Last commit Jun 19, 2016

js-framework-benchmark's People

Contributors

agubler avatar aidenybai avatar aimwhy avatar alexfmpe avatar antonmak1 avatar birkskyum avatar captaincodeman avatar daiyam avatar eavichay avatar fabiospampinato avatar krausest avatar krutsch avatar leeoniya avatar lifeart avatar localvoid avatar lukechu10 avatar michaelboulton avatar mmichlin66 avatar nakrovati avatar nullvoxpopuli avatar pakastin avatar puckowski avatar ryansolid avatar snowbldr avatar stefansarya avatar thysultan avatar trotyl avatar ts-thomas avatar twharmon avatar webreflection avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

js-framework-benchmark's Issues

installation issue

Just wanted to try on my machine, but errors occured at end of npm install:
npm-debug.txt

EDIT: same goes for npm run build, it fails at end with "unknown command 'tsc'"
hope it helps.

unfair benchmarks vs real life tests

I spent a couple of hours going over the last additions of the benchmarks.

I noticed one thing that may be important:
Some frameworks have an extra overhead the first time you interact with the DOM.
You can observe that when you open the console and click several time the "Create 1,000 rows" button.

Some frameworks get a 5x factor on the next calls (the 1rst call is very slow). Among them:

  • ractive
  • riot
  • react
  • ...

Some have always the same performance:

  • angular
  • vue
  • react-lite
    -vidom
    -...

I am still wondering whether it is unfair, or not?
I think the current way of doing this test (inserting a lot of rows on a blank page) is close to a real life test.
Do you?

non-keyed description is not true for Binding.scala

In the section Non keyed results on page http://www.stefankrause.net/js-frameworks-benchmark5/webdriver-ts/table.html:

In consequence inserting or deleting an element in the data array might append after or delete the last table row and update the contents of all elements after the inserting or deletion index.

It's not true for Binding.scala. Thanks to its precise data binding mechanism, the DOM managed by Binding.scala always precisely follows the same changes on upstream data.

Ractive Add Test Optimization

You can optimize the ractive test by using "array.push" rather than providing a completely new array for ractive to process.

add() {
        // this.data = this.data.concat(this.buildData(1000));
        this.data.push.apply(this.data, this.buildData(1000));
    }

Add Elm

Is there any chance we can add Elm to this benchmark, I'd love to see another benchmark like the creator's blog benchmark in this suite of benchmarks!

Let me know if that seems appropriate or not :-)

Webdriver doesn't start on Chrome 54

Webdriver doesn't run, instead throwing an error:

SessionNotCreatedError: session not created exception

If you update chromedriver to 2.24.1 this issue goes away but I can't get chromedriver to open a window. :/

Add build times into the benchmarks

Let's face it – long build times suck. They affect CI and CD builds with automated tests/builds and effect local build times too. I feel it's important to emphasise this in the benchmarks as it's a HUGELY important metric in any job where engineering of software is important.

consider running benchmark with CPU/net throttling

@krausest

Now that the benchmark has been split into keyed/unkeyed, both tables are largely green. They're green in part due to the relatively high specs of the machine on which these benches run. This performance of your Mac is sufficient not to break the the 16ms frame boundary in many cases.

This situation is not great because mobile phones - even modern ones - are much slower...and they account for 50% of web traffic today. Rather than re-scaling the colorization, I propose reducing the max workload (maybe 10k rows -> 5k rows) but running the bench with Chrome's 3x CPU throttling and maybe network throttling at Good 3G that's representative of mobile performance. These changes would help de-greenify the tables and help better assess mobile overhead in real life.

FWIW, in my experience Chrome's throttling can in fact be tweaked to be representative of actual perf i get on my 5 year old, not-so-fast device in 3G. [1]

This should probably wait till after Round 5, which i assume is coming soon.

[1] http://www.gsmarena.com/htc_evo_4g_lte-4665.php

Vue.js measurements missing?

I don't want to create a pull request for that
;-)

'use strict';

var Vue = require('vue');
var {Store} = require('./store');

var store = new Store();

var startTime;
var lastMeasure;
var startMeasure = function(name) {
startTime = performance.now();
lastMeasure = name;
}
var stopMeasure = function() {
var last = lastMeasure;
if (lastMeasure) {
window.setTimeout(function () {
lastMeasure = null;
var stop = performance.now();
console.log(last+" took "+(stop-startTime));
}, 0);
}
}

new Vue({
el: '#main',
data: {
rows: store.data,
selected: store.selected
},
methods: {
add() {
startMeasure("add");
store.add();
this.rows = store.data;
this.selected = store.selected;
stopMeasure();
},
remove(item) {
startMeasure("remove");
store.delete(item.id);
this.rows = store.data;
this.selected = store.selected;
stopMeasure();
},
select(item) {
startMeasure("select");
store.select(item.id);
this.rows = store.data;
this.selected = store.selected;
stopMeasure();
},
run() {
startMeasure("run");
store.run();
this.rows = store.data;
this.selected = store.selected;
stopMeasure();
},
update() {
startMeasure("update");
store.update();
this.rows = store.data;
this.selected = store.selected;
stopMeasure();
},
runLots() {
startMeasure("runLots");
store.runLots();
this.rows = store.data;
this.selected = store.selected;
stopMeasure();
},
clear() {
startMeasure("clear");
store.clear();
this.rows = store.data;
this.selected = store.selected;
stopMeasure();
},
swapRows() {
startMeasure("swapRows");
store.swapRows();
this.rows = store.data;
this.selected = store.selected;
stopMeasure();
}
}
})

Vanilla version can be faster (maybe a lot)

Hi @krausest

Here are some notes on boosting the vanilla impl.

get/setAttribute is slow, use node properties when available:

setAttribute("class") -> .className
elem.getAttribute("data-id") -> elem.dataset.id
elem.setAttribute("data-id") -> elem.dataset.id
elem.innerText -> elem.textContent (when creating) (wont boost perf, but is a better practice)
...and use elem.firstChild.nodeValue (when updating)

.childNodes is slow; firstChild, lastChild, nextSibling, previousSibling are fast.

tr.childNodes[0] -> tr.firstChild
tr.childNodes[1].childNodes[0] -> tr.firstChild.nextSibling.firstChild
removeAllRows() -> tbody.textContent = ""

createDocumentFragment is no longer necessary in modern browsers [1], it's actually slower than plain appendChild and insertBefore

the vanilla version uses event delegation, while many implementations instead attach 1000's of onclick handlers, this is not an apples-to-apples comparison, especially when the libs allow for event delegation (many do).

also, I noticed the vanilla version does not maintain the row highlight (is present) during mutations/appending, etc.

/$0.02

[1] infernojs/inferno#223 (comment)

npm build failure

Thanks @krausest for the npm install fix with dependencies..
npm install 81.69s user 12.57s system 106% cpu 1:28.52 total

running into a build issue:

$ npm run build

> [email protected] build ~/Downloads/js-framework-benchmark
> node build.js


> [email protected] build-prod ~/Downloads/js-framework-benchmark/angular-v1.5.8
> webpack -p -c webpack.config.js

Hash: 7c41281ac1dc4335b953
Version: webpack 1.13.2
Child
    Hash: 7c41281ac1dc4335b953
    Version: webpack 1.13.2
    Time: 5878ms
      Asset    Size  Chunks             Chunk Names
    main.js  250 kB       0  [emitted]  main
       [0] multi main 40 bytes {0} [built]
       [5] ./src/angularmin.js 75 bytes {0} [built]
       [6] ./webpack.config.js 525 bytes {0} [built]
        + 4 hidden modules

    WARNING in main.js from UglifyJs
    Side effects in initialization of unused variable jQuery [./src/main.es6.js:3,4]
    Condition always true [./~/jquery/dist/jquery.js:10035,0]

> [email protected] build-prod ~/Downloads/js-framework-benchmark/angular-v2.0.0
> npm run precompile && node rollup.config.js --prod


> [email protected] precompile ~/Downloads/js-framework-benchmark/angular-v2.0.0
> ngc

The `this` keyword is equivalent to `undefined` at the top level of an ES module, and has been rewritten
The `this` keyword is equivalent to `undefined` at the top level of an ES module, and has been rewritten
closure compiler optimizing...
closure compiler optimizing complete
closure compiler optimizing...
closure compiler optimizing complete
built angular2

> [email protected] prebuild-prod ~/Downloads/js-framework-benchmark/aurelia-v1.0.0
> npm run clean:dist


> [email protected] clean:dist ~/Downloads/js-framework-benchmark/aurelia-v1.0.0
> rimraf dist


> [email protected] build-prod ~/Downloads/js-framework-benchmark/aurelia-v1.0.0
> cross-env NODE_ENV=production npm run webpack -- --progress --profile


> [email protected] webpack ~/Downloads/js-framework-benchmark/aurelia-v1.0.0
> cross-env ./node_modules/.bin/webpack "--progress" "--profile"

Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
 - configuration has an unknown property 'htmlLoader'. These properties are valid:
   object { amd?, bail?, cache?, context?, devServer?, devtool?, entry, externals?, loader?, module?, name?, dependencies?, node?, output?, plugins?, profile?, recordsInputPath?, recordsOutputPath?, recordsPath?, resolve?, resolveLoader?, stats?, target?, watch?, watchOptions? }
 - configuration.entry['app'] should be one of these:
   string | [string]
   The entry point for one output file.
 - configuration.entry should be one of these:
   object { <key>: string | [string] } | string | [string]
   The entry point(s) of the compilation.
 - configuration.resolve has an unknown property 'root'. These properties are valid:
   object { modules?, descriptionFiles?, plugins?, mainFields?, aliasFields?, mainFiles?, extensions?, enforceExtension?, moduleExtensions?, enforceModuleExtension?, alias?, symlinks?, unsafeCache?, cachePredicate?, fileSystem?, resolver? }

npm ERR! Darwin 15.6.0
npm ERR! argv "/usr/local/Cellar/node/6.2.2/bin/node" "/usr/local/bin/npm" "run" "webpack" "--" "--progress" "--profile"
npm ERR! node v6.2.2
npm ERR! npm  v3.9.5
npm ERR! code ELIFECYCLE
npm ERR! [email protected] webpack: `cross-env ./node_modules/.bin/webpack "--progress" "--profile"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] webpack script 'cross-env ./node_modules/.bin/webpack "--progress" "--profile"'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the js-framework-benchmark-aurelia package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     cross-env ./node_modules/.bin/webpack "--progress" "--profile"
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs js-framework-benchmark-aurelia
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls js-framework-benchmark-aurelia
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     ~/Downloads/js-framework-benchmark/aurelia-v1.0.0/npm-debug.log

npm ERR! Darwin 15.6.0
npm ERR! argv "/usr/local/Cellar/node/6.2.2/bin/node" "/usr/local/bin/npm" "run" "build-prod"
npm ERR! node v6.2.2
npm ERR! npm  v3.9.5
npm ERR! code ELIFECYCLE
npm ERR! [email protected] build-prod: `cross-env NODE_ENV=production npm run webpack -- --progress --profile`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build-prod script 'cross-env NODE_ENV=production npm run webpack -- --progress --profile'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the js-framework-benchmark-aurelia package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     cross-env NODE_ENV=production npm run webpack -- --progress --profile
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs js-framework-benchmark-aurelia
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls js-framework-benchmark-aurelia
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     ~/Downloads/js-framework-benchmark/aurelia-v1.0.0/npm-debug.log
child_process.js:529
    throw err;
    ^

Error: Command failed: npm run build-prod
    at checkExecSyncError (child_process.js:486:13)
    at execSync (child_process.js:526:13)
    at ~/Downloads/js-framework-benchmark/build.js:7:3
    at arrayEach (~/Downloads/js-framework-benchmark/node_modules/lodash/lodash.js:520:11)
    at Function.forEach (~/Downloads/js-framework-benchmark/node_modules/lodash/lodash.js:9202:14)
    at Object.<anonymous> (~/Downloads/js-framework-benchmark/build.js:5:3)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)

npm ERR! Darwin 15.6.0
npm ERR! argv "/usr/local/Cellar/node/6.2.2/bin/node" "/usr/local/bin/npm" "run" "build"
npm ERR! node v6.2.2
npm ERR! npm  v3.9.5
npm ERR! code ELIFECYCLE
npm ERR! [email protected] build: `node build.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script 'node build.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the js-framework-benchmark package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node build.js
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs js-framework-benchmark
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls js-framework-benchmark
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     ~/Downloads/js-framework-benchmark/npm-debug.log

consider removing unused bootstrap styles

a large part of this benchmark is browser restyling overhead which has no bearing on lib speed and is a fixed unnecessary cost for everyone. in many cases it also masks lib efficiency. if for no other reason than to allow the benchmark runs to complete in less time, it may make sense to strip out unused styles.

you can use something like https://github.com/purifycss/purifycss to avoid having to figure things out by hand.

Will you be interested in my in-depth comparisons between mobx & redux?

Hi, @krausest . I've done these in branch benchmark/mobx-vs-redux my fork. 8 more columns have been added to the result table. Don't know if you would like a PR for this, as it might goes too much detail into inferno & react, which's a little bit off the intention of this repo.

New comparisons.

  • inferno v0.7.26-mobX-v2.4.4
  • inferno v0.7.26-redux-v3.5.2
  • inferno v0.7.26-redux-v3.5.2-immutable-js-v3.8.1
  • inferno v0.7.26-redux-v3.5.2-immutable-js-v3.8.1-pure-render-mixin-15.3.0
  • react v15.3.0-mobX-v2.4.2
  • react v15.3.0-redux-v3.5.2
  • react v15.3.0-redux-v3.5.2-immutable-js-v3.8.1
  • react v15.3.0-redux-v3.5.2-immutable-js-v3.8.1-pure-render-mixin

Failure postinstall npm dependencies

Is probably not an issue related to this repo on its own, but most likely you guys can let the aurelia owners know that their package seems to be broken:

node v6.2.1
npm  v3.9.3
npm ERR! code ELIFECYCLE
npm ERR! [email protected] postinstall: `jspm install -y`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script 'jspm install -y'.

vanillajs-keyed "replace all rows" baseline is wrong

@krausest

vanillajs-keyed doesnt actually replace rows for "replace all rows", which is why it's so fast while other keyed implementations are slower. at least for the keyed version, it needs to do the correct thing (which should clock in at slightly faster than the kivi impl)

i made a DOM-instrumented version of of vanillajs-keyed [1] [2]. you can watch the console to see a summary of DOM ops performed for any action.

feel free to use my DOMInstr lib (it's MIT) to check what the other implementations do when porting to keyed versions.

[1] https://rawgit.com/leeoniya/js-framework-benchmark/vanillajs-keyed-instrumented/vanillajs-keyed/index.html
[2] leeoniya@8f1acaa

Aurelia specific logic

Can you please, explain why we need this long tsAfter = isAurelia ? tsEventFire : tsEvent; Thanks.

Update all results

There may be some wrong in the result. binding.scala-v10.0.1_06_remove-one-1k should not be as slow as the result.

On my computer, binding.scala-v10.0.1_06_remove-one-1k is 10 times faster than vanillajs_06_remove-one-1k !

after initialized  06_remove-one-1k 0 binding.scala-v10.0.1
after run  06_remove-one-1k 0 binding.scala-v10.0.1
result binding.scala-v10.0.1_06_remove-one-1k [ { type: 'click', ts: 138156995841, dur: 348, end: 138156996189 },
  { type: 'paint', ts: 138157055751, dur: 1099, end: 138157056850 },
  { type: 'gc', ts: 138156900336, mem: 36.346763610839844 } ]
after initialized  06_remove-one-1k 0 vanillajs
after run  06_remove-one-1k 0 vanillajs
result vanillajs_06_remove-one-1k [ { type: 'click', ts: 138258041670, dur: 3743, end: 138258045413 },
  { type: 'paint', ts: 138258123467, dur: 1444, end: 138258124911 },
  { type: 'gc', ts: 138258135172, mem: 41.954978942871094 } ]

I suspect that vanillajs_06_remove-one-1k benchmark was running on a different Chrome version, which is the cause of the difference.

(Moved from #94)

npm install failure

did a brew update.. Have the latest everything.. should I just revert to [email protected] ? or do I need to manually add a repo?

> [email protected] postinstall ~/Downloads/js-framework-benchmark/ember-v2.6.1
> bower install

npm ERR! Darwin 15.6.0
npm ERR! argv "/usr/local/Cellar/node/6.2.2/bin/node" "/usr/local/bin/npm" "install"
npm ERR! node v6.2.2
npm ERR! npm  v3.9.5

npm ERR! No compatible version found: [email protected]
npm ERR! Valid install targets:
npm ERR! 1.0.0-alpha8, 1.0.0-alpha7, 1.0.0-alpha5, 1.0.0-alpha4, 1.0.0-alpha3, 1.0.0-alpha2, 1.0.0-alpha11, 1.0.0-alpha10, 1.0.0-alpha1, 0.8.0-alpha6, 0.8.0-alpha4, 0.8.0-alpha3, 0.8.0-alpha2, 0.8.0-alpha1, 0.7.27, 0.7.26, 0.7.25, 0.7.24, 0.7.23, 0.7.22, 0.7.21, 0.7.20, 0.7.17, 0.7.16, 0.7.15, 0.7.14, 0.7.13, 0.7.12, 0.7.11, 0.7.10, 0.7.9, 0.7.8, 0.7.7, 0.7.6, 0.7.5, 0.7.4, 0.7.3, 0.7.2, 0.7.1, 0.7.0, 0.6.4, 0.6.3, 0.6.2, 0.6.1, 0.6.0, 0.5.22, 0.5.21, 0.5.20, 0.5.18, 0.5.17, 0.5.16, 0.5.13, 0.5.12, 0.5.11, 0.5.10, 0.5.9, 0.5.8, 0.5.7, 0.5.6, 0.5.5, 0.4.5, 0.4.4, 0.4.3, 0.4.0, 0.1.11, 0.1.10, 0.1.9, 0.1.7, 0.1.6, 0.1.4, 0.1.3, 0.1.2
npm ERR!
npm ERR!
npm ERR! If you need help, you may report this error at:
npm ERR!     <https://github.com/npm/npm/issues>

npm ERR! Please include the following file with any support request:
npm ERR!     ~/Downloads/js-framework-benchmark/inferno-v1.0.0-alpha7/npm-debug.log
child_process.js:529
    throw err;
    ^

Error: Command failed: npm install
    at checkExecSyncError (child_process.js:486:13)
    at execSync (child_process.js:526:13)
    at ~/Downloads/js-framework-benchmark/install.js:7:3
    at arrayEach (~/Downloads/js-framework-benchmark/node_modules/lodash/lodash.js:520:11)
    at Function.forEach (~/Downloads/js-framework-benchmark/node_modules/lodash/lodash.js:9202:14)
    at Object.<anonymous> (~/Downloads/js-framework-benchmark/install.js:5:3)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)

npm ERR! Darwin 15.6.0
npm ERR! argv "/usr/local/Cellar/node/6.2.2/bin/node" "/usr/local/bin/npm" "install"
npm ERR! node v6.2.2
npm ERR! npm  v3.9.5
npm ERR! code ELIFECYCLE
npm ERR! [email protected] postinstall: `node install.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script 'node install.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the js-framework-benchmark package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node install.js
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs js-framework-benchmark
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls js-framework-benchmark
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     ~/Downloads/js-framework-benchmark/npm-debug.log

Building (npm run build) doesn't work

Hello!
Building doesn't work, it's log I have

# node --version
v6.4.0

# git clone https://github.com/krausest/js-framework-benchmark
# cd js-framework-benchmark/

# npm install
# npm run build

> [email protected] build /tmp/0/js-framework-benchmark
> node build.js


> [email protected] build-prod /tmp/0/js-framework-benchmark/angular-v1.5.7
> webpack -p -c webpack.config.js

sh: 1: webpack: not found

npm ERR! Linux 3.13.0-93-generic
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "build-prod"
npm ERR! node v6.4.0
npm ERR! npm  v3.10.3
npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn
npm ERR! [email protected] build-prod: `webpack -p -c webpack.config.js`
npm ERR! spawn ENOENT
npm ERR! 
npm ERR! Failed at the [email protected] build-prod script 'webpack -p -c webpack.config.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the js-framework-benchmark-angular package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     webpack -p -c webpack.config.js
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs js-framework-benchmark-angular
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls js-framework-benchmark-angular
npm ERR! There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! Please include the following file with any support request:
npm ERR!     /tmp/0/js-framework-benchmark/angular-v1.5.7/npm-debug.log
child_process.js:526
    throw err;
    ^

Error: Command failed: npm run build-prod
    at checkExecSyncError (child_process.js:483:13)
    at execSync (child_process.js:523:13)
    at /tmp/0/js-framework-benchmark/build.js:7:3
    at arrayEach (/tmp/0/js-framework-benchmark/node_modules/lodash/lodash.js:522:11)
    at Function.forEach (/tmp/0/js-framework-benchmark/node_modules/lodash/lodash.js:9011:14)
    at Object.<anonymous> (/tmp/0/js-framework-benchmark/build.js:5:3)
    at Module._compile (module.js:556:32)
    at Object.Module._extensions..js (module.js:565:10)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)

npm ERR! Linux 3.13.0-93-generic
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "build"
npm ERR! node v6.4.0
npm ERR! npm  v3.10.3
npm ERR! code ELIFECYCLE
npm ERR! [email protected] build: `node build.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] build script 'node build.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the js-framework-benchmark package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node build.js
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs js-framework-benchmark
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls js-framework-benchmark
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /tmp/0/js-framework-benchmark/npm-debug.log

Solution to tracking or non-tracking (keyed vs. non-keyed)

I'd like to ask for feedback to fix the tracking or non-tracking (keyed vs. non-keyed) issue. Please keep all general discussion out of this issue and put it into issue #22 instead.

Problem: Non tracking / non-keyed frameworks are faster than those which track / use keys. Regarding this benchmark non tracking is a correct solution. The "big" frameworks like react and angular can also perform much faster if track by if is disabled as can be seen here.
The real problem is that for real life applications there's a big chance that non-tracking will cause wrong results (e.g. for transitions or dom manipulation outside of the framework).

Goal: Require all frameworks to use a tracking implementation.

Proposal: Add a simple functional requirement: The button to remove a row shall show a zoom transition when holding the mouse button. After releasing the button the transition must be stopped immediately, the next row must not show a zoom effect.
This is a very simple change that just needs an update of the css (74e7436) and might make the results a bit less biased and shouldn't influence the measurement via webdriver.

The following frameworks currently appear to be non-tracking :

  • aurelia
  • cycle.js
  • dio
  • domvm
  • inferno
  • riot
  • TSERS
  • vanillajs
  • vue

(please note that kivi is not included in that list)

What do you think?

Update React to 15.3.0

There’s been an unmounting time regression in 15.x that should be fixed in 15.3.0.
Would be great to see if it improves results!

Allow a nicer way to run for a single framework

The benchmarks seem to take a really long time to run, it would be nice if there was a way to pass an argument in to the mvn command to signal only running for a single framework. Right now I am just using comments to block the others from running so it's doable would just be a nice to have. Thanks for putting this together by the way cool stuff.

mithril v1.0 alpha bug

When I build and run the benchmark...

  1. create 1000 rows (ok, logs run took xxx)
  2. create 1000 rows again. (bug, deletes old rows and creates next 1000 rows, but logs "delete took xxx". Then if I select, it deletes all the items. Or if I append, swap, or update, the log keeps saying "delete took xxx" instead of correct action)
  3. (alternative). append, update, swap, select all work fine until I create a 2nd time.
  4. once I hit clear, things go back to step 1.

i've been trying for a while to fix it, but i can't trace down how doing anything other than .remove() can trigger startMeasure with the name 'delete'.

https://youtu.be/pNpMYPMVduA

split into 2 tables "keyed" and "non-keyed" ?

Looking at the table [which is getting way too wide IMO], the perf numbers are very difficult to compare because many impls are keyed and many are unkeyed. these are really 2 completely different perf profiles.

if you prefer to have a single huge table at the very least, it would make sense to order/group them by keyed vs non-keyed. a trivial way to see this is to assume everything < 130ms for "replace all rows" is unkeyed and > 130ms is keyed.

i think 2 tables will make sense and would provide much more meaningful comparisons (and also not span a 2 x 1080p screens :)

the vanillajs-keyed impl would need to be fixed for this as well: see #103

Update Inferno to 1.2.2

Apparently guys at Inferno managed to boost createElement() by 50%

Might be interesting to bench it ?

[Suggestion] Record Framerates in addition to JavaScript execution times

A lot of these frameworks touch the DOM only sparingly and such frameworks should also measure frame rates in addition to just JavaScript execution times. Even if the JavaScript takes a lot of time to run, frameworks could technically stagger it such that the frame rates are not impacted.

Frame Rates can be calculated in the same way Chromium's perf test suite calculates is - using Log entries like DrawFrame and BenchmarkImplStats. If this is something the project could use, I could send in a pull request with the change.

Inconsistency in implementation of 10th row updates

Howdy. I was looking at a few implementations to see how differences are normalized and noticed some significant differences in how the "every 10th row" code is implemented:

The Inferno implementation mutates the array, where the Ember one rebuilds the entire set of data. Which is the intended implementation?

Further, it seems like the data generation itself should perhaps not be included in the benchmarked values (though if the items in the array are part of a change-tracking solution like Ember objects or MobX it seems unfair to exclude that work, so maybe not).

Add a painfully imperative implementation

@krausest

The vanillajs implementation tries to be a purpose-built vdom lib which means it has to do keyed lookups in the data, do diffing, etc. This is not the fastest possible implementation of the requirements. Since there is no explicit requirement for one-way data flow from a datastore, you could create an implementation that is probably 30%-50% faster (and maybe smaller) with jquery-like semantics. For example, clicking "X" would literally remove the clicked node (via a delegated handler) and simultaneously remove the backing item from the store.

This would really be the true baseline for all other implementations. And you could theoretically drop vanillajs altogether rather than maintaining it with whatever new perf hacks are discovered by fast vdom libs.

If you prefer a bit of fluent sugar without using jQuery, cash.js, sprint.js you can use the tweet-sized bala.js [1].

[1] https://github.com/finom/bala

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.