From 4618914ceb46c860fcaca09bc6130884befcfa14 Mon Sep 17 00:00:00 2001 From: Blake Newman Date: Mon, 16 May 2016 21:29:08 +0100 Subject: [PATCH] Added benchmark for SSR (#2842) - Includes `renderToStream` and `renderToString` - Added SSR benchmark README.md - Added npm `bench:ssr` script - Renders table with 1000 rows with 10 columns (10 thousand components) --- benchmarks/ssr/README.md | 13 +++++ benchmarks/ssr/common.js | 86 ++++++++++++++++++++++++++++++++ benchmarks/ssr/renderToStream.js | 26 ++++++++++ benchmarks/ssr/renderToString.js | 15 ++++++ package.json | 3 +- 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 benchmarks/ssr/README.md create mode 100644 benchmarks/ssr/common.js create mode 100644 benchmarks/ssr/renderToStream.js create mode 100644 benchmarks/ssr/renderToString.js diff --git a/benchmarks/ssr/README.md b/benchmarks/ssr/README.md new file mode 100644 index 00000000..3e1c02a3 --- /dev/null +++ b/benchmarks/ssr/README.md @@ -0,0 +1,13 @@ +# Vue.js SSR benchmark + +This benchmark renders a table of 1000 rows with 10 columns (10 thousand components). This benchmark is to demonstrate the overall speeds of Vue.js SSR and time to content comparison between `renderToString` and `renderToStream`. + +To view the results follow the run section. Note that the overall completion time for the results are variable, this is due to other system related variants at run time (available memory, processing ect). In ideal circumstances both should finish within equal times. + +`renderToStream` pipes the content through a stream which gives massive performance benefits over renderToString. This can be observed through the benchmark. + +### run + +``` bash +npm run bench:ssr +``` diff --git a/benchmarks/ssr/common.js b/benchmarks/ssr/common.js new file mode 100644 index 00000000..210b6be2 --- /dev/null +++ b/benchmarks/ssr/common.js @@ -0,0 +1,86 @@ +'use strict' + +const compiler = require('../../dist/compiler.js') +const self = (global || root) + +self.performance = { + now: function () { + var hrtime = process.hrtime() + return ((hrtime[0] * 1000000 + hrtime[1] / 1000) / 1000) + } +} + +function generateGrid (rowCount, columnCount) { + var grid = [] + + for (var r = 0; r < rowCount; r++) { + var row = { id: r, items: [] } + for (var c = 0; c < columnCount; c++) { + row.items.push({ id: (r + '-' + c) }) + } + grid.push(row) + } + + return grid +} + +const gridData = generateGrid(1000, 10) + +var perfMixin = { + computed: { + performance: { + cached: false, + get: function () { + return (self.performance.now() - self.s).toFixed(2) + } + } + } +} + +var gridComponent = { + template: '

{{ performance }}ms

', + mixins: [perfMixin], + components: { + myTable: { + data: function () { + return { + grid: gridData + } + }, + template: '
', + components: { + row: { + props: ['row'], + mixins: [perfMixin], + template: '{{ performance }}ms', + components: { + column: { + mixins: [perfMixin], + template: '{{ performance }}ms' + } + } + } + } + } + } +} + +function createCompiledOptions (options) { + const res = compiler.compileToFunctions(options.template, { + preserveWhitespace: false + }) + Object.assign(options, res) + delete options.template + if (options.components) { + const keys = Object.keys(options.components) + let total = keys.length + while (total) { + const name = keys[total - 1] + options.components[name] = createCompiledOptions(options.components[name]) + total-- + } + } + return options +} + +module.exports = createCompiledOptions(gridComponent) diff --git a/benchmarks/ssr/renderToStream.js b/benchmarks/ssr/renderToStream.js new file mode 100644 index 00000000..5a824fad --- /dev/null +++ b/benchmarks/ssr/renderToStream.js @@ -0,0 +1,26 @@ +'use strict' + +const Vue = require('../../dist/vue.common.js') +const createRenderer = require('../../dist/server-renderer.js') +const renderToStream = createRenderer().renderToStream +const gridComponent = require('./common.js') + +console.log('--- renderToStream --- ') +const self = (global || root) +self.s = self.performance.now() + +const stream = renderToStream(new Vue(gridComponent)) +let str = '' +const stats = [] +stream.on('data', chunk => { + str += chunk + stats.push(self.performance.now()) +}) +stream.on('end', () => { + stats.push(self.performance.now()) + stats.forEach((val, index) => { + const type = index !== stats.length - 1 ? 'Chunk' : 'Complete' + console.log(type + ' time: ' + (val - self.s).toFixed(2) + 'ms') + }) + console.log() +}) diff --git a/benchmarks/ssr/renderToString.js b/benchmarks/ssr/renderToString.js new file mode 100644 index 00000000..b2bbc154 --- /dev/null +++ b/benchmarks/ssr/renderToString.js @@ -0,0 +1,15 @@ +'use strict' + +const Vue = require('../../dist/vue.common.js') +const createRenderer = require('../../dist/server-renderer.js') +const renderToString = createRenderer().renderToString +const gridComponent = require('./common.js') + +console.log('--- renderToString --- ') +const self = (global || root) +self.s = self.performance.now() + +renderToString(new Vue(gridComponent), () => { + console.log('Complete time: ' + (self.performance.now() - self.s).toFixed(2) + 'ms') + console.log() +}) diff --git a/package.json b/package.json index 51934544..24d5f7a9 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "test:unit": "NODE_ENV=development karma start build/karma.unit.config.js", "test:cover": "NODE_ENV=development karma start build/karma.cover.config.js", "test:e2e": "npm run build -- vue.js && node test/e2e/runner.js", - "test:ssr": "npm run build -- vue.common.js,compiler.js,server-renderer.js && NODE_ENV=development VUE_ENV=server jasmine JASMINE_CONFIG_PATH=test/ssr/jasmine.json" + "test:ssr": "npm run build -- vue.common.js,compiler.js,server-renderer.js && NODE_ENV=development VUE_ENV=server jasmine JASMINE_CONFIG_PATH=test/ssr/jasmine.json", + "bench:ssr": "npm run build -- vue.common.js,compiler.js,server-renderer.js && NODE_ENV=production VUE_ENV=server node benchmarks/ssr/renderToString.js && NODE_ENV=production VUE_ENV=server node benchmarks/ssr/renderToStream.js" }, "repository": { "type": "git",