├── client ├── versions.js ├── benchmarks.js ├── main.js ├── utils │ └── sequence.js ├── measurements.js ├── components │ ├── Results.html │ ├── BenchmarkResult.html │ └── Main.html └── run.js ├── .gitignore ├── scripts ├── build.js ├── install.js └── build-tools.js ├── selenium ├── measurements.js └── run.js ├── server └── index.js ├── README.md ├── benchmarks ├── hello-world │ └── Main.html ├── create-large-table │ └── Main.html └── dbmonster │ ├── Main.html │ └── ENV.js ├── public └── index.html ├── rollup.config.js ├── versions.json ├── .eslintrc.json ├── package.json └── yarn.lock /client/versions.js: -------------------------------------------------------------------------------- 1 | export default __VERSIONS__; -------------------------------------------------------------------------------- /client/benchmarks.js: -------------------------------------------------------------------------------- 1 | export default __BENCHMARKS__; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | public/benchmarks 4 | public/bundle* 5 | versions/ -------------------------------------------------------------------------------- /client/main.js: -------------------------------------------------------------------------------- 1 | import Main from './components/Main.html'; 2 | 3 | const app = new Main({ 4 | target: document.querySelector( 'main' ) 5 | }); -------------------------------------------------------------------------------- /client/utils/sequence.js: -------------------------------------------------------------------------------- 1 | export default function sequence ( array, fn ) { 2 | return array.reduce( ( promise, item ) => { 3 | return promise.then( () => Promise.resolve( fn( item ) ) ); 4 | }, Promise.resolve() ); 5 | } -------------------------------------------------------------------------------- /scripts/build.js: -------------------------------------------------------------------------------- 1 | const { build } = require('./build-tools'); 2 | 3 | const versions = require( '../versions.json' ); 4 | 5 | versions.forEach( version => { 6 | const dir = `versions/${version}`; 7 | build( version, dir ); 8 | }); -------------------------------------------------------------------------------- /client/measurements.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | id: 'create:cold' 4 | }, 5 | { 6 | id: 'create:warm' 7 | }, 8 | { 9 | id: 'run:cold' 10 | }, 11 | { 12 | id: 'run:warm' 13 | }, 14 | { 15 | id: 'destroy:cold' 16 | }, 17 | { 18 | id: 'destroy:warm' 19 | } 20 | ]; -------------------------------------------------------------------------------- /selenium/measurements.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | id: 'create:cold' 4 | }, 5 | { 6 | id: 'create:warm' 7 | }, 8 | { 9 | id: 'run:cold' 10 | }, 11 | { 12 | id: 'run:warm' 13 | }, 14 | { 15 | id: 'destroy:cold' 16 | }, 17 | { 18 | id: 'destroy:warm' 19 | } 20 | ]; -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | const fs = require( 'fs' ); 2 | const path = require( 'path' ); 3 | const relative = require( 'require-relative' ); 4 | const express = require( 'express' ); 5 | const { rollup } = require( 'rollup' ); 6 | 7 | const app = express(); 8 | 9 | app.use( express.static( `public` ) ); 10 | 11 | app.listen( 3000, () => { 12 | console.log( `Listening on localhost:3000` ); 13 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svelte-bench 2 | 3 | Benchmarks for [Svelte](https://svelte.technology). Work-in-progress. 4 | 5 | ## Running the benchmarks 6 | 7 | You must have [Yarn](https://yarnpkg.com) installed. 8 | 9 | ```bash 10 | git clone https://github.com/sveltejs/svelte-bench 11 | cd svelte-bench 12 | yarn 13 | yarn start 14 | ``` 15 | 16 | Navigate to [localhost:3000](http://localhost:3000). 17 | -------------------------------------------------------------------------------- /benchmarks/hello-world/Main.html: -------------------------------------------------------------------------------- 1 |

hello {{name}}!

2 | 3 | -------------------------------------------------------------------------------- /scripts/install.js: -------------------------------------------------------------------------------- 1 | const { execSync } = require( 'child_process' ); 2 | const sander = require( 'sander' ); 3 | 4 | const versions = require( '../versions.json' ); 5 | 6 | versions.forEach( version => { 7 | sander.writeFileSync( `versions/${version}/package.json`, JSON.stringify({ 8 | dependencies: { 9 | svelte: version 10 | } 11 | })); 12 | 13 | execSync( `yarn`, { 14 | cwd: `versions/${version}`, 15 | stdio: 'inherit' 16 | }); 17 | }); -------------------------------------------------------------------------------- /client/components/Results.html: -------------------------------------------------------------------------------- 1 |
2 | {{#each benchmarks as benchmark}} 3 | 4 | {{/each}} 5 |
6 | 7 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | svelte-bench 8 | 9 | 14 | 15 | 16 | 17 |

svelte-bench

18 | 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /benchmarks/create-large-table/Main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {{#each rows as row}} 13 | 14 | 15 | 16 | 17 | 18 | 19 | {{/each}} 20 | 21 |
abcd
{{row[0]}}{{row[1]}}{{row[2]}}{{row[3]}}
22 | 23 | 39 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import replace from 'rollup-plugin-replace'; 3 | import svelte from 'rollup-plugin-svelte'; 4 | import commonjs from 'rollup-plugin-commonjs'; 5 | import resolve from 'rollup-plugin-node-resolve'; 6 | 7 | // TODO should this list be automatically generated somehow? 8 | const versions = require( './versions.json' ); 9 | 10 | const benchmarks = fs.readdirSync( 'benchmarks' ).filter( d => d[0] !== '.' ); 11 | 12 | export default { 13 | entry: 'client/main.js', 14 | dest: 'public/bundle.js', 15 | format: 'iife', 16 | sourceMap: true, 17 | plugins: [ 18 | resolve(), 19 | commonjs(), 20 | replace({ 21 | __BENCHMARKS__: JSON.stringify( benchmarks ), 22 | __VERSIONS__: JSON.stringify( versions ) 23 | }), 24 | svelte() 25 | ] 26 | }; -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | "1.22.0", 3 | "1.21.0", 4 | "1.20.2", 5 | "1.20.1", 6 | "1.20.0", 7 | "1.19.1", 8 | "1.19.0", 9 | "1.18.2", 10 | "1.18.1", 11 | "1.18.0", 12 | "1.17.2", 13 | "1.17.1", 14 | "1.17.0", 15 | "1.16.0", 16 | "1.15.1", 17 | "1.15.0", 18 | "1.14.1", 19 | "1.14.0", 20 | "1.13.7", 21 | "1.13.6", 22 | "1.13.5", 23 | "1.13.4", 24 | "1.13.3", 25 | "1.13.2", 26 | "1.13.1", 27 | "1.13.0", 28 | "1.12.1", 29 | "1.12.0", 30 | "1.11.4", 31 | "1.11.3", 32 | "1.11.2", 33 | "1.11.1", 34 | "1.11.0", 35 | "1.10.3", 36 | "1.10.2", 37 | "1.10.1", 38 | "1.10.0", 39 | "1.9.1", 40 | "1.9.0", 41 | "1.8.1", 42 | "1.8.0", 43 | "1.6.11", 44 | "1.6.10", 45 | "1.6.9", 46 | "1.6.8", 47 | "1.6.7", 48 | "1.6.6", 49 | "1.6.5", 50 | "1.6.4", 51 | "1.6.3", 52 | "1.6.2", 53 | "1.6.1", 54 | "1.6.0", 55 | "1.5.0", 56 | "1.4.0", 57 | "1.3.1", 58 | "1.3.0", 59 | "1.2.5", 60 | "1.2.4", 61 | "1.2.3", 62 | "1.2.2", 63 | "1.2.1", 64 | "1.2.0", 65 | "1.1.3", 66 | "1.1.2", 67 | "1.1.1", 68 | "1.1.0", 69 | "1.0.7", 70 | "1.0.6" 71 | ] 72 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "rules": { 4 | "indent": [ 2, "tab", { "SwitchCase": 1 } ], 5 | "semi": [ 2, "always" ], 6 | "keyword-spacing": [ 2, { "before": true, "after": true } ], 7 | "space-before-blocks": [ 2, "always" ], 8 | "space-before-function-paren": [ 2, "always" ], 9 | "no-mixed-spaces-and-tabs": [ 2, "smart-tabs" ], 10 | "no-cond-assign": 0, 11 | "no-unused-vars": 2, 12 | "object-shorthand": [ 2, "always" ], 13 | "no-const-assign": 2, 14 | "no-class-assign": 2, 15 | "no-this-before-super": 2, 16 | "no-var": 2, 17 | "no-unreachable": 2, 18 | "valid-typeof": 2, 19 | "quote-props": [ 2, "as-needed" ], 20 | "one-var": [ 2, "never" ], 21 | "prefer-arrow-callback": 2, 22 | "prefer-const": [ 2, { "destructuring": "all" } ], 23 | "arrow-spacing": 2, 24 | "no-inner-declarations": 0 25 | }, 26 | "env": { 27 | "es6": true, 28 | "browser": true, 29 | "node": true, 30 | "mocha": true 31 | }, 32 | "extends": [ 33 | "eslint:recommended", 34 | "plugin:import/errors", 35 | "plugin:import/warnings" 36 | ], 37 | "parserOptions": { 38 | "ecmaVersion": 6, 39 | "sourceType": "module" 40 | }, 41 | "settings": { 42 | "import/core-modules": [ "svelte" ] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-bench", 3 | "version": "1.0.0", 4 | "description": "Svelte benchmarks", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "npm run build:benchmarks && npm run build:client && node server", 8 | "build:client": "rollup -c", 9 | "build:benchmarks": "node scripts/build", 10 | "postinstall": "node scripts/install", 11 | "dev": "rollup -c -w", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/sveltejs/svelte-bench.git" 17 | }, 18 | "keywords": [ 19 | "svelte", 20 | "benchmark", 21 | "perf" 22 | ], 23 | "author": "Rich Harris", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/sveltejs/svelte-bench/issues" 27 | }, 28 | "homepage": "https://github.com/sveltejs/svelte-bench#readme", 29 | "devDependencies": { 30 | "eslint": "^3.17.1", 31 | "eslint-plugin-import": "^2.2.0", 32 | "require-relative": "^0.8.7", 33 | "rollup": "^0.41.5", 34 | "rollup-plugin-buble": "^0.15.0", 35 | "rollup-plugin-commonjs": "^8.0.2", 36 | "rollup-plugin-node-resolve": "^2.0.0", 37 | "rollup-plugin-replace": "^1.1.1", 38 | "rollup-plugin-svelte": "^1.6.0", 39 | "rollup-watch": "^3.2.2", 40 | "sander": "^0.6.0", 41 | "uglify-js": "^2.8.12" 42 | }, 43 | "dependencies": { 44 | "chalk": "^1.1.3", 45 | "chroma-js": "^1.2.2", 46 | "express": "^4.15.2", 47 | "minimist": "^1.2.0", 48 | "selenium-webdriver": "^3.3.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /benchmarks/dbmonster/Main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{#each dbs as db}} 4 | 5 | 8 | 9 | 14 | 15 | {{#each db.lastSample.topFiveQueries as query}} 16 | 23 | {{/each}} 24 | 25 | {{/each}} 26 | 27 |
6 | {{ db.dbname }} 7 | 10 | 11 | {{ db.lastSample.nbQueries }} 12 | 13 | 17 | {{ query.formatElapsed }} 18 |
19 |
{{ query.query }}
20 |
21 |
22 |
28 | 29 | 63 | 64 | -------------------------------------------------------------------------------- /client/components/BenchmarkResult.html: -------------------------------------------------------------------------------- 1 |
2 |

{{benchmark}}

3 | 4 | 5 | 6 | 7 | 8 | 9 | {{#each measurements as measurement}} 10 | 11 | {{/each}} 12 | 13 | 14 | 15 | 16 | {{#each rows as row}} 17 | 18 | 19 | 20 | {{#each row.measurements as cell}} 21 | 25 | {{/each}} 26 | 27 | {{/each}} 28 | 29 |
versionsize{{measurement.id}}
{{row.version}}{{row.size}} 22 |
23 | {{cell.label}} 24 |
30 |
31 | 32 | 63 | 64 | -------------------------------------------------------------------------------- /client/run.js: -------------------------------------------------------------------------------- 1 | /*global Component */ 2 | export function createAndDestroy () { 3 | if ( window.error ) { 4 | window.opener.postMessage({ 5 | type: 'error', 6 | message: window.error 7 | }, '*' ); 8 | 9 | window.opener.postMessage({ 10 | type: 'done' 11 | }, '*' ); 12 | 13 | return; 14 | } 15 | 16 | const now = () => window.performance.now(); 17 | const wait = window.setImmediate ? 18 | () => new Promise( fulfil => setImmediate( fulfil ) ) : 19 | () => new Promise( fulfil => setTimeout( fulfil, 0 ) ); 20 | 21 | function runCold () { 22 | let component; 23 | 24 | return Promise.resolve() 25 | .then( () => { 26 | // component create 27 | const t = now(); 28 | component = new Component({ 29 | target: document.body 30 | }); 31 | const duration = now() - t; 32 | 33 | window.opener.postMessage({ 34 | type: 'create:cold', 35 | value: duration 36 | }, '*' ); 37 | }) 38 | .then( wait ) 39 | .then( () => { 40 | // component run 41 | let duration = 0; 42 | 43 | if ( component.run ) { 44 | const t = now(); 45 | component.run(); 46 | duration = now() - t; 47 | } 48 | 49 | window.opener.postMessage({ 50 | type: 'run:cold', 51 | value: duration 52 | }, '*' ); 53 | }) 54 | .then( wait ) 55 | .then( () => { 56 | // component destroy 57 | const t = now(); 58 | if ( component.destroy ) { 59 | component.destroy(); 60 | } else { 61 | component.teardown(); 62 | } 63 | const duration = now() - t; 64 | 65 | window.opener.postMessage({ 66 | type: 'destroy:cold', 67 | value: duration 68 | }, '*' ); 69 | }); 70 | } 71 | 72 | function runWarm () { 73 | const iterations = 5; 74 | 75 | // warm up 76 | let i = 50; 77 | while ( i-- ) { 78 | const component = new Component({ 79 | target: document.body 80 | }); 81 | 82 | if ( component.run ) { 83 | component.run(); 84 | } 85 | 86 | if ( component.destroy ) { 87 | component.destroy(); 88 | } else { 89 | component.teardown(); 90 | } 91 | } 92 | 93 | // time warm runs 94 | i = iterations; 95 | 96 | let createTotal = 0; 97 | let runTotal = 0; 98 | let destroyTotal = 0; 99 | 100 | function go () { 101 | let component; 102 | 103 | return Promise.resolve() 104 | .then( () => { 105 | const t = now(); 106 | component = new Component({ 107 | target: document.body 108 | }); 109 | createTotal += now() - t; 110 | }) 111 | .then( wait ) 112 | .then( () => { 113 | if ( component.run ) { 114 | const t = now(); 115 | component.run(); 116 | runTotal += now() - t; 117 | } 118 | }) 119 | .then( wait ) 120 | .then( () => { 121 | const t = now(); 122 | if ( component.destroy ) { 123 | component.destroy(); 124 | } else { 125 | component.teardown(); 126 | } 127 | destroyTotal += now() - t; 128 | }) 129 | .then( () => { 130 | if ( --i > 0 ) return go(); 131 | }); 132 | } 133 | 134 | return go().then( () => { 135 | window.opener.postMessage({ 136 | type: 'create:warm', 137 | value: createTotal / iterations 138 | }, '*' ); 139 | 140 | window.opener.postMessage({ 141 | type: 'run:warm', 142 | value: runTotal / iterations 143 | }, '*' ); 144 | 145 | window.opener.postMessage({ 146 | type: 'destroy:warm', 147 | value: destroyTotal / iterations 148 | }, '*' ); 149 | }); 150 | } 151 | 152 | runCold() 153 | .then( runWarm ) 154 | .then( () => { 155 | window.opener.postMessage({ 156 | type: 'done' 157 | }, '*' ); 158 | }); 159 | } -------------------------------------------------------------------------------- /scripts/build-tools.js: -------------------------------------------------------------------------------- 1 | const path = require( 'path' ); 2 | const sander = require( 'sander' ); 3 | const { rollup } = require( 'rollup' ); 4 | const buble = require( 'rollup-plugin-buble' ); 5 | const UglifyJS = require( 'uglify-js' ); 6 | const zlib = require( 'zlib' ); 7 | const relative = require( 'require-relative' ); 8 | 9 | const benchmarks = sander.readdirSync( 'benchmarks' ).filter( d => d[0] !== '.' ); 10 | 11 | module.exports.build = function ( version, dir, custom ) { 12 | const svelte = path.basename( dir ) === 'svelte' ? require(dir) : relative( 'svelte', dir ); 13 | 14 | let promise = Promise.resolve(); 15 | benchmarks.forEach( benchmark => { 16 | promise = promise.then(() => { 17 | const dest = `public/benchmarks/${benchmark}/${version}`; 18 | 19 | return ( custom ? Promise.resolve( false ) : sander.exists( dest ) ).then( exists => { 20 | if ( exists ) return; 21 | 22 | return rollup({ 23 | entry: `benchmarks/${benchmark}/Main.html`, 24 | plugins: [ 25 | { 26 | name: 'svelte', 27 | 28 | transform ( code, id ) { 29 | if ( !/\.html$/.test( id ) ) { return null; } 30 | 31 | const name = path.basename( id ).replace( /\.html$/, '' ); 32 | 33 | return svelte.compile( code, { 34 | name, 35 | filename: id, 36 | format: 'es', 37 | shared: custom ? path.join( dir, 'shared.js' ) : relative.resolve( 'svelte/shared.js', dir ), 38 | 39 | onerror ( err ) { 40 | let message = ( err.loc ? `(${err.loc.line}:${err.loc.column}) ` : '' ) + err.message; 41 | if ( err.frame ) message += `\n${err.frame}`; 42 | 43 | const err2 = new Error( message ); 44 | err2.stack = err.stack; 45 | 46 | throw err2; 47 | } 48 | }); 49 | } 50 | }, 51 | buble() 52 | ] 53 | }).then( bundle => { 54 | return bundle.generate({ 55 | format: 'iife', 56 | moduleName: 'Component' 57 | }).code; 58 | }, err => { 59 | console.error( err.message ); 60 | return `window.error = ${JSON.stringify( err.message )};`; 61 | }) 62 | .then( code => { 63 | const minified = UglifyJS.minify( code, { fromString: true }); 64 | const zipped = zlib.gzipSync( minified.code ); 65 | 66 | return Promise.all([ 67 | sander.writeFile( `${dest}/component.js`, code ), 68 | sander.writeFile( `${dest}/index.html`, ` 69 | 70 | 71 | 72 | 73 | 74 | 75 | ${benchmark}/${version} 76 | 77 | 82 | 83 | 84 |

${benchmark}/${version}

85 | 86 |
87 | 88 | 103 | 104 | ` ), 105 | sander.writeFile( `${dest}/component.json`, JSON.stringify({ 106 | code, 107 | size: zipped.length 108 | })) 109 | ]); 110 | }); 111 | }); 112 | }); 113 | }); 114 | 115 | return promise; 116 | }; 117 | -------------------------------------------------------------------------------- /client/components/Main.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | -------------------------------------------------------------------------------- /benchmarks/dbmonster/ENV.js: -------------------------------------------------------------------------------- 1 | var first = true; 2 | var counter = 0; 3 | var data; 4 | var _base; 5 | (_base = String.prototype).lpad || (_base.lpad = function(padding, toLength) { 6 | return padding.repeat((toLength - this.length) / padding.length).concat(this); 7 | }); 8 | 9 | function formatElapsed(value) { 10 | var str = parseFloat(value).toFixed(2); 11 | if (value > 60) { 12 | minutes = Math.floor(value / 60); 13 | comps = (value % 60).toFixed(2).split('.'); 14 | seconds = comps[0].lpad('0', 2); 15 | ms = comps[1]; 16 | str = minutes + ":" + seconds + "." + ms; 17 | } 18 | return str; 19 | } 20 | 21 | function getElapsedClassName(elapsed) { 22 | var className = 'Query elapsed'; 23 | if (elapsed >= 10.0) { 24 | className += ' warn_long'; 25 | } 26 | else if (elapsed >= 1.0) { 27 | className += ' warn'; 28 | } 29 | else { 30 | className += ' short'; 31 | } 32 | return className; 33 | } 34 | 35 | function countClassName(queries) { 36 | var countClassName = "label"; 37 | if (queries >= 20) { 38 | countClassName += " label-important"; 39 | } 40 | else if (queries >= 10) { 41 | countClassName += " label-warning"; 42 | } 43 | else { 44 | countClassName += " label-success"; 45 | } 46 | return countClassName; 47 | } 48 | 49 | function updateQuery(object) { 50 | if (!object) { 51 | object = {}; 52 | } 53 | var elapsed = Math.random() * 15; 54 | object.elapsed = elapsed; 55 | object.formatElapsed = formatElapsed(elapsed); 56 | object.elapsedClassName = getElapsedClassName(elapsed); 57 | object.query = "SELECT blah FROM something"; 58 | object.waiting = Math.random() < 0.5; 59 | if (Math.random() < 0.2) { 60 | object.query = " in transaction"; 61 | } 62 | if (Math.random() < 0.1) { 63 | object.query = "vacuum"; 64 | } 65 | return object; 66 | } 67 | 68 | function cleanQuery(value) { 69 | if (value) { 70 | value.formatElapsed = ""; 71 | value.elapsedClassName = ""; 72 | value.query = ""; 73 | delete value.elapsed; 74 | delete value.waiting; 75 | } else { 76 | return { 77 | query: "***", 78 | formatElapsed: "", 79 | elapsedClassName: "" 80 | }; 81 | } 82 | } 83 | 84 | function generateRow(object, keepIdentity, counter) { 85 | var nbQueries = Math.floor((Math.random() * 10) + 1); 86 | if (!object) { 87 | object = {}; 88 | } 89 | object.lastMutationId = counter; 90 | object.nbQueries = nbQueries; 91 | if (!object.lastSample) { 92 | object.lastSample = {}; 93 | } 94 | if (!object.lastSample.topFiveQueries) { 95 | object.lastSample.topFiveQueries = []; 96 | } 97 | if (keepIdentity) { 98 | // for Angular optimization 99 | if (!object.lastSample.queries) { 100 | object.lastSample.queries = []; 101 | for (var l = 0; l < 12; l++) { 102 | object.lastSample.queries[l] = cleanQuery(); 103 | } 104 | } 105 | for (var j in object.lastSample.queries) { 106 | var value = object.lastSample.queries[j]; 107 | if (j <= nbQueries) { 108 | updateQuery(value); 109 | } else { 110 | cleanQuery(value); 111 | } 112 | } 113 | } else { 114 | object.lastSample.queries = []; 115 | for (var j = 0; j < 12; j++) { 116 | if (j < nbQueries) { 117 | var value = updateQuery(cleanQuery()); 118 | object.lastSample.queries.push(value); 119 | } else { 120 | object.lastSample.queries.push(cleanQuery()); 121 | } 122 | } 123 | } 124 | for (var i = 0; i < 5; i++) { 125 | var source = object.lastSample.queries[i]; 126 | object.lastSample.topFiveQueries[i] = source; 127 | } 128 | object.lastSample.nbQueries = nbQueries; 129 | object.lastSample.countClassName = countClassName(nbQueries); 130 | return object; 131 | } 132 | 133 | function getData(keepIdentity) { 134 | var oldData = data; 135 | if (!keepIdentity) { // reset for each tick when !keepIdentity 136 | data = []; 137 | for (var i = 1; i <= ENV.rows; i++) { 138 | data.push({ dbname: 'cluster' + i, query: "", formatElapsed: "", elapsedClassName: "" }); 139 | data.push({ dbname: 'cluster' + i + ' slave', query: "", formatElapsed: "", elapsedClassName: "" }); 140 | } 141 | } 142 | if (!data) { // first init when keepIdentity 143 | data = []; 144 | for (var i = 1; i <= ENV.rows; i++) { 145 | data.push({ dbname: 'cluster' + i }); 146 | data.push({ dbname: 'cluster' + i + ' slave' }); 147 | } 148 | oldData = data; 149 | } 150 | for (var i in data) { 151 | var row = data[i]; 152 | if (!keepIdentity && oldData && oldData[i]) { 153 | row.lastSample = oldData[i].lastSample; 154 | } 155 | if (!row.lastSample || Math.random() < ENV.mutations()) { 156 | counter = counter + 1; 157 | if (!keepIdentity) { 158 | delete row.lastSample; 159 | } 160 | generateRow(row, keepIdentity, counter); 161 | } else { 162 | data[i] = oldData[i]; 163 | } 164 | } 165 | first = false; 166 | return { 167 | toArray: function() { 168 | return data; 169 | } 170 | }; 171 | } 172 | 173 | var mutationsValue = 0.5; 174 | 175 | function mutations(value) { 176 | if (value) { 177 | mutationsValue = value; 178 | return mutationsValue; 179 | } else { 180 | return mutationsValue; 181 | } 182 | } 183 | 184 | var body = document.querySelector('body'); 185 | var theFirstChild = body.firstChild; 186 | 187 | var sliderContainer = document.createElement( 'div' ); 188 | sliderContainer.style.cssText = "display: flex"; 189 | var slider = document.createElement('input'); 190 | var text = document.createElement('label'); 191 | text.innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%'; 192 | text.id = "ratioval"; 193 | slider.setAttribute("type", "range"); 194 | slider.style.cssText = 'margin-bottom: 10px; margin-top: 5px'; 195 | slider.addEventListener('change', function(e) { 196 | ENV.mutations(e.target.value / 100); 197 | document.querySelector('#ratioval').innerHTML = 'mutations : ' + (ENV.mutations() * 100).toFixed(0) + '%'; 198 | }); 199 | sliderContainer.appendChild( text ); 200 | sliderContainer.appendChild( slider ); 201 | body.insertBefore( sliderContainer, theFirstChild ); 202 | 203 | const ENV = { 204 | generateData: getData, 205 | rows: 50, 206 | timeout: 0, 207 | mutations: mutations 208 | }; 209 | 210 | export default ENV; -------------------------------------------------------------------------------- /selenium/run.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const {Builder, By, until} = require('selenium-webdriver'); 3 | const chalk = require('chalk'); 4 | const minimist = require('minimist'); 5 | const {build} = require('../scripts/build-tools'); 6 | 7 | const command = minimist(process.argv.slice(2)); 8 | 9 | const capabilities = command.capabilities ? JSON.parse(command.capabilities) : []; 10 | const server = command.server || null; 11 | const browsers = command.browsers ? command.browsers.split(',') : []; 12 | const iterations = command.iterations ? +command.iterations : 5; 13 | const output = command.output || null; 14 | 15 | const allVersions = require('../versions.json').map(version => { 16 | const split = version.split('.'); 17 | return { 18 | major: +split[0], 19 | minor: +split[1], 20 | patch: +split[2] 21 | }; 22 | }); 23 | const benchmarks = fs.readdirSync('benchmarks').filter(d => d[0] !== '.'); 24 | const measurements = require('./measurements'); 25 | 26 | const versions = []; 27 | allVersions.forEach(version => { 28 | if (versions.length < 5) { 29 | versions.push(`${version.major}.${version.minor}.${version.patch}`); 30 | } else if (versions.length < 10 && allVersions.filter(other => other.major === version.major && other.minor === version.minor && other.patch > version.patch).length === 0) { 31 | versions.push(`${version.major}.${version.minor}.${version.patch}`); 32 | } 33 | }); 34 | console.log('Running versions', versions.join(', ')); 35 | 36 | const combinations = []; 37 | 38 | if (command.custom) { 39 | build('custom', command.custom, true).then(run); 40 | versions.unshift('custom'); 41 | } else { 42 | run(); 43 | } 44 | 45 | if (output && fs.existsSync(output)) { 46 | fs.unlinkSync(output); 47 | } 48 | 49 | function createDriver(results, browser, cap) { 50 | let driverInstance; 51 | 52 | let builder = new Builder(); 53 | if (server) { 54 | builder = builder.usingServer(server); 55 | } 56 | if (browser) { 57 | builder = builder.forBrowser(browser); 58 | } 59 | if (cap) { 60 | builder = builder.withCapabilities(cap); 61 | } 62 | 63 | const capString = browser || `${cap.browserName} ${cap.version} (${cap.platform})`; 64 | 65 | driverInstance = builder.build(); 66 | driverInstance.manage().timeouts().setScriptTimeout(5 * 1000); 67 | return sequence(combinations, ({version, benchmark, code, size}) => { 68 | console.log('Testing', version, benchmark, 'in', capString); 69 | 70 | results[benchmark][version] = {}; 71 | 72 | results[benchmark][version].size = size; 73 | 74 | const base64 = Buffer.from(` 75 |