mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-16 12:14:14 +02:00
Benchmark consistence && Allow users to select benches to run (#1765)
* Use slate rather than relative path * Move benchmark to one dir * Use slate-* instead of relative path * Before and After Function * Remove un-necessary cross-env * Hard fix * Lint the hard fix * Reset memory in bench() * Working on Benchmark Frameworks * Rename to slate-dev-benchmark * Add packages * Fix prettier bug * Benchmark framework is in working * Do not log in test * max times test * mute logger in test * add hr time * Better support for maxTime; add support of split runs to save memory space * Fix maxTries * Add global.gc * Global gc for each bench * Better test interface * Test max-time * Test max-time done * Add Benchmark among packages * Starting to get benchmark running * Pure Node lib * Change babelrc for pure Node benchmark * Moving Benchmarks * Get benchmark and test running * Get benchmark for slate-html-serializer * add slate-react * add slate/changes * all benchmarks are converted * Run benchmark by yarn * Run benchmark with expose-gc * Annotate Bench.js * Do not bundle slate-dev-benchmark in rollup * Add annotation * Allow config file to enable part benchmark compare * Add config for compare * support compare.js * Do not re-allocate memory; due to a large heap taken influence result * Render with Decorations * get active marks at range * Fix bug in showing percents * Fix percent showing bug * chore: add more benches * Better output of benchmark * Fix linting * decoration and normal as different benchmark test * Fix deserialize benchmark * README.md * Fix Readme.md * README.md * block-spacing config * safer user config loading * use package.json to load package in test * Consistent linting * move components to parent directory * Annotation styling in package * margin line before multi-line block * Fix naive bug * Fix naive bug * Fix a blank line * only log user and hr * Better name * Better annotation for runBundleTasks * Fix typo * Better logger * Move async to test * Omit skip * Only log the user space time * Single line async sleep * file name fix * Fix annotation * Better output of compare * Remove get-characters(-at-range) benchmarks * Restore emoji * Capitalize types * Remove compare to another area * Add grep and config interface * Linting files * Linting benchmarks * Linting benchmarks * Update yarn.lock
This commit is contained in:
committed by
Ian Storm Taylor
parent
09c93a6cd4
commit
8f9bfdac2b
14
.babelrc
14
.babelrc
@@ -23,7 +23,19 @@
|
|||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"presets": [
|
"presets": [
|
||||||
"env",
|
["env", {
|
||||||
|
"exclude": ["transform-regenerator"]
|
||||||
|
}],
|
||||||
|
"react",
|
||||||
|
"stage-0"
|
||||||
|
],
|
||||||
|
"plugins": ["transform-runtime"]
|
||||||
|
},
|
||||||
|
"benchmark": {
|
||||||
|
"presets": [
|
||||||
|
["env", {
|
||||||
|
"exclude": ["transform-regenerator"]
|
||||||
|
}],
|
||||||
"react",
|
"react",
|
||||||
"stage-0"
|
"stage-0"
|
||||||
],
|
],
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -21,3 +21,6 @@ packages/*/yarn.lock
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
# Editor files
|
||||||
|
.tern-port
|
||||||
|
@@ -90,6 +90,16 @@ yarn benchmark
|
|||||||
|
|
||||||
There will be some subtle changes in iteration speed always, but the comparison reporter will highlight any changes that seem meaningful. You can run `benchmark` multiple times to ensure the speed up persists.
|
There will be some subtle changes in iteration speed always, but the comparison reporter will highlight any changes that seem meaningful. You can run `benchmark` multiple times to ensure the speed up persists.
|
||||||
|
|
||||||
|
### Run Selected Benchmarks
|
||||||
|
|
||||||
|
To run selected benchmarks, create `tmp/benchmark-config.js` with `module.exports.include`. For example, to run slate-core benchmarks only with `get-*`, we can create a `tmp/benchmark-config.js` as
|
||||||
|
|
||||||
|
```
|
||||||
|
module.exports.include = {
|
||||||
|
slate: /^get/
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Adding Browser Support
|
## Adding Browser Support
|
||||||
|
|
||||||
Slate aims to targeted all of the modern browsers, and eventually the modern mobile platforms. Right now browser support is limited to the latest versions of [Chrome](https://www.google.com/chrome/browser/desktop/), [Firefox](https://www.mozilla.org/en-US/firefox/new/), and [Safari](http://www.apple.com/safari/), but if you are interested in adding support for another modern platform, that is welcomed!
|
Slate aims to targeted all of the modern browsers, and eventually the modern mobile platforms. Right now browser support is limited to the latest versions of [Chrome](https://www.google.com/chrome/browser/desktop/), [Firefox](https://www.mozilla.org/en-US/firefox/new/), and [Safari](http://www.apple.com/safari/), but if you are interested in adding support for another modern platform, that is welcomed!
|
||||||
|
115
benchmark/compare.js
Normal file
115
benchmark/compare.js
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
const chalk = require('chalk')
|
||||||
|
const figures = require('figures')
|
||||||
|
const emojis = require('emojis')
|
||||||
|
const { resolve } = require('path')
|
||||||
|
|
||||||
|
const baseline = require(resolve(process.cwd(), 'tmp/benchmark-baseline'))
|
||||||
|
const comparison = require(resolve(process.cwd(), 'tmp/benchmark-comparison'))
|
||||||
|
const { existsSync } = require('fs')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let THRESHOLD = 0.333
|
||||||
|
const configPath = '../../tmp/benchmark-config.js'
|
||||||
|
|
||||||
|
if (existsSync(configPath)) {
|
||||||
|
const alternative = require(configPath).THRESHOLD
|
||||||
|
|
||||||
|
if (typeof alternative === 'number' && alternative > 0) {
|
||||||
|
THRESHOLD = alternative
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print.
|
||||||
|
*/
|
||||||
|
|
||||||
|
console.log()
|
||||||
|
console.log(` benchmarks`)
|
||||||
|
|
||||||
|
baseline.forEach((suite, i) => {
|
||||||
|
console.log(` ${suite.name}`)
|
||||||
|
|
||||||
|
suite.benchmarks.forEach((base, j) => {
|
||||||
|
const compared = { user: {}, hr: {} }
|
||||||
|
|
||||||
|
for (const key of Object.keys(compared)) {
|
||||||
|
const comp = comparison[i].benchmarks[j]
|
||||||
|
if (!comp) return
|
||||||
|
const b = base.iterations / base[key] * 1000
|
||||||
|
const c = comp.iterations / comp[key] * 1000
|
||||||
|
const balancePercent =
|
||||||
|
b > c ? Math.round(Math.abs(b - c) / c * 100) : (c - b) / b * 100
|
||||||
|
|
||||||
|
const output = `${b.toFixed(2)} -> ${c.toFixed(2)} ops/sec`
|
||||||
|
compared[key].baseOutput = output
|
||||||
|
|
||||||
|
compared[key].percentOutput = `${balancePercent.toFixed(2)}% ${
|
||||||
|
c > b ? 'faster' : 'slower'
|
||||||
|
}`
|
||||||
|
|
||||||
|
compared[key].percentValue = balancePercent
|
||||||
|
compared[key].b = b
|
||||||
|
compared[key].c = c
|
||||||
|
compared[key].isFaster = c > b
|
||||||
|
|
||||||
|
if (balancePercent > 1000) {
|
||||||
|
compared[key].percentOutput += emojis.unicode(' :scream: ')
|
||||||
|
} else if (balancePercent > 100) {
|
||||||
|
if (c > b) {
|
||||||
|
compared[key].percentOutput += emojis.unicode(' :raised_hands: ')
|
||||||
|
} else {
|
||||||
|
compared[key].percentOutput += emojis.unicode(' :worried: ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { user, hr } = compared
|
||||||
|
|
||||||
|
if (
|
||||||
|
user.percentValue < THRESHOLD * 100 &&
|
||||||
|
hr.percentValue < THRESHOLD * 100
|
||||||
|
) {
|
||||||
|
console.log(
|
||||||
|
chalk.grey(
|
||||||
|
` ${figures.tick} ${base.name}: ${user.baseOutput} (${
|
||||||
|
user.percentOutput
|
||||||
|
})`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.isFaster === hr.isFaster) {
|
||||||
|
if (user.isFaster) {
|
||||||
|
console.log(chalk.green(` ${figures.star} ${base.name}:`))
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
` user: ${user.baseOutput} (${user.percentOutput})`
|
||||||
|
)
|
||||||
|
|
||||||
|
console.log(` real: ${hr.baseOutput} (${hr.percentOutput})`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.red(` ${figures.cross} ${base.name}:`))
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
` user: ${user.baseOutput} (${user.percentOutput})`
|
||||||
|
)
|
||||||
|
|
||||||
|
console.log(` real: ${hr.baseOutput} (${hr.percentOutput})`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.red(` ${figures.questionMarkPrefix} ${base.name}:`))
|
||||||
|
console.log(` user: ${user.baseOutput} (${user.percentOutput})`)
|
||||||
|
console.log(` real: ${hr.baseOutput} (${hr.percentOutput})`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log()
|
39
benchmark/config.js
Normal file
39
benchmark/config.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
const { resolve } = require('path')
|
||||||
|
const { existsSync } = require('fs')
|
||||||
|
const program = require('commander')
|
||||||
|
|
||||||
|
program
|
||||||
|
.option('-g, --grep []', 'Add grep pattern to filter running benchmarks')
|
||||||
|
.option('-c, --config [file]', 'Add config to filter running benchmarks')
|
||||||
|
.parse(process.argv)
|
||||||
|
|
||||||
|
const { grep } = program
|
||||||
|
|
||||||
|
if (grep) {
|
||||||
|
const pattern = new RegExp(grep)
|
||||||
|
|
||||||
|
module.exports.include = {
|
||||||
|
slate: pattern,
|
||||||
|
'slate-html-serializer': pattern,
|
||||||
|
'slate-plain-serializer': pattern,
|
||||||
|
'slate-react': pattern,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let { config = 'tmp/benchmark-config.js' } = program
|
||||||
|
config = resolve(config)
|
||||||
|
|
||||||
|
const userConfig = existsSync(config) ? require(config) : {}
|
||||||
|
|
||||||
|
if (userConfig.include) {
|
||||||
|
module.exports.include = userConfig.include
|
||||||
|
} else if (userConfig.default) {
|
||||||
|
module.exports.inlcude = userConfig.default
|
||||||
|
} else {
|
||||||
|
module.exports.include = {
|
||||||
|
slate: /^/,
|
||||||
|
'slate-html-serializer': /^/,
|
||||||
|
'slate-plain-serializer': /^/,
|
||||||
|
'slate-react': /^/,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
benchmark/generate-report.js
Normal file
57
benchmark/generate-report.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
const { writeFileSync } = require('fs')
|
||||||
|
|
||||||
|
function convertRepo(report) {
|
||||||
|
const result = []
|
||||||
|
|
||||||
|
for (const name in report) {
|
||||||
|
const suite = report[name]
|
||||||
|
|
||||||
|
result.push({
|
||||||
|
name,
|
||||||
|
type: 'suite',
|
||||||
|
benchmarks: convertSuite(suite),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertSuite(suite) {
|
||||||
|
const result = []
|
||||||
|
|
||||||
|
for (const name in suite) {
|
||||||
|
const bench = suite[name]
|
||||||
|
const { user, cycles } = bench
|
||||||
|
|
||||||
|
result.push({
|
||||||
|
name,
|
||||||
|
type: 'bench',
|
||||||
|
elapsed: user,
|
||||||
|
iterations: cycles,
|
||||||
|
ops: 1000 * cycles / user,
|
||||||
|
...bench,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
const IS_COMPARE = process.env.COMPARE
|
||||||
|
const filePath = IS_COMPARE
|
||||||
|
? './tmp/benchmark-comparison.json'
|
||||||
|
: './tmp/benchmark-baseline.json'
|
||||||
|
|
||||||
|
function generateReport(repo) {
|
||||||
|
repo
|
||||||
|
.run()
|
||||||
|
.then(report => {
|
||||||
|
const data = JSON.stringify(convertRepo(report))
|
||||||
|
writeFileSync(filePath, data)
|
||||||
|
return report
|
||||||
|
})
|
||||||
|
.then(report => {
|
||||||
|
if (IS_COMPARE) {
|
||||||
|
require('./compare')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { generateReport }
|
45
benchmark/helpers/h.js
Normal file
45
benchmark/helpers/h.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
|
const { createHyperscript } = require('slate-hyperscript')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a hyperscript.
|
||||||
|
*
|
||||||
|
* @type {Function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const h = createHyperscript({
|
||||||
|
blocks: {
|
||||||
|
line: 'line',
|
||||||
|
paragraph: 'paragraph',
|
||||||
|
quote: 'quote',
|
||||||
|
code: 'code',
|
||||||
|
list: 'list',
|
||||||
|
item: 'item',
|
||||||
|
image: {
|
||||||
|
type: 'image',
|
||||||
|
isVoid: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inlines: {
|
||||||
|
link: 'link',
|
||||||
|
hashtag: 'hashtag',
|
||||||
|
comment: 'comment',
|
||||||
|
emoji: {
|
||||||
|
type: 'emoji',
|
||||||
|
isVoid: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
marks: {
|
||||||
|
b: 'bold',
|
||||||
|
i: 'italic',
|
||||||
|
u: 'underline',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export.
|
||||||
|
*
|
||||||
|
* @type {Function}
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = h
|
20
benchmark/index.js
Normal file
20
benchmark/index.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
const { repo } = require('slate-dev-benchmark')
|
||||||
|
const { resolve } = require('path')
|
||||||
|
const { readdirSync } = require('fs')
|
||||||
|
const { generateReport } = require('./generate-report')
|
||||||
|
const { include } = require('./config')
|
||||||
|
|
||||||
|
const categoryDir = resolve(__dirname)
|
||||||
|
|
||||||
|
const categories = readdirSync(categoryDir).filter(
|
||||||
|
c => c[0] != '.' && c.match(/^slate/)
|
||||||
|
)
|
||||||
|
|
||||||
|
categories.forEach(dir => {
|
||||||
|
if (include && include[dir]) {
|
||||||
|
const { run } = require(`./${dir}`)
|
||||||
|
run(include[dir])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
generateReport(repo)
|
@@ -0,0 +1,58 @@
|
|||||||
|
/** @jsx h */
|
||||||
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
|
const Html = require('slate-html-serializer').default
|
||||||
|
const { JSDOM } = require('jsdom') // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
|
const html = new Html({
|
||||||
|
parseHtml: JSDOM.fragment,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
deserialize(el, next) {
|
||||||
|
switch (el.tagName.toLowerCase()) {
|
||||||
|
case 'blockquote':
|
||||||
|
return {
|
||||||
|
object: 'block',
|
||||||
|
type: 'quote',
|
||||||
|
nodes: next(el.childNodes),
|
||||||
|
}
|
||||||
|
case 'p': {
|
||||||
|
return {
|
||||||
|
object: 'block',
|
||||||
|
type: 'paragraph',
|
||||||
|
nodes: next(el.childNodes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'strong': {
|
||||||
|
return {
|
||||||
|
object: 'mark',
|
||||||
|
type: 'bold',
|
||||||
|
nodes: next(el.childNodes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'em': {
|
||||||
|
return {
|
||||||
|
object: 'mark',
|
||||||
|
type: 'italic',
|
||||||
|
nodes: next(el.childNodes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports.default = function(string) {
|
||||||
|
html.deserialize(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.input = `
|
||||||
|
<blockquote>
|
||||||
|
<p>
|
||||||
|
This is editable <strong>rich</strong> text, <em>much</em> better than a textarea!
|
||||||
|
</p>
|
||||||
|
</blockquote>
|
||||||
|
`
|
||||||
|
.trim()
|
||||||
|
.repeat(10)
|
@@ -1,10 +1,10 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import Html from '../..'
|
const Html = require('slate-html-serializer').default
|
||||||
import React from 'react'
|
const React = require('react')
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
import { JSDOM } from 'jsdom' // eslint-disable-line import/no-extraneous-dependencies
|
const { JSDOM } = require('jsdom') // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
const html = new Html({
|
const html = new Html({
|
||||||
parseHtml: JSDOM.fragment,
|
parseHtml: JSDOM.fragment,
|
||||||
@@ -34,11 +34,11 @@ const html = new Html({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function(state) {
|
module.exports.default = function(state) {
|
||||||
html.serialize(state)
|
html.serialize(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = (
|
module.exports.input = (
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
37
benchmark/slate-html-serializer/index.js
Normal file
37
benchmark/slate-html-serializer/index.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
const { readdirSync } = require('fs')
|
||||||
|
const { basename, extname, resolve } = require('path')
|
||||||
|
const { resetMemoization } = require('slate')
|
||||||
|
const { Suite, Bench } = require('slate-dev-benchmark')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmarks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports.run = function(include) {
|
||||||
|
const categoryDir = resolve(__dirname)
|
||||||
|
const categories = readdirSync(categoryDir).filter(
|
||||||
|
c => c[0] != '.' && c != 'index.js'
|
||||||
|
)
|
||||||
|
|
||||||
|
categories.forEach(category => {
|
||||||
|
const suite = new Suite(category, { minTries: 100, minTime: 1000 })
|
||||||
|
const benchmarkDir = resolve(categoryDir, category)
|
||||||
|
const benchmarks = readdirSync(benchmarkDir)
|
||||||
|
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
|
||||||
|
.map(b => basename(b, extname(b)))
|
||||||
|
|
||||||
|
benchmarks.forEach(benchmark => {
|
||||||
|
if (include && !benchmark.match(include)) return
|
||||||
|
const bench = new Bench(suite, benchmark)
|
||||||
|
const dir = resolve(benchmarkDir, benchmark)
|
||||||
|
const module = require(dir)
|
||||||
|
const fn = module.default
|
||||||
|
bench.input(() => module.input)
|
||||||
|
|
||||||
|
bench.run(input => {
|
||||||
|
fn(input)
|
||||||
|
resetMemoization()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
40
benchmark/slate-plain-serializer/index.js
Normal file
40
benchmark/slate-plain-serializer/index.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
const { basename, extname, resolve } = require('path')
|
||||||
|
const { readdirSync } = require('fs')
|
||||||
|
const { resetMemoization } = require('slate')
|
||||||
|
const { Suite, Bench } = require('slate-dev-benchmark')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmarks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports.run = function(include) {
|
||||||
|
const categoryDir = resolve(__dirname)
|
||||||
|
const categories = readdirSync(categoryDir).filter(
|
||||||
|
c => c[0] != '.' && c != 'index.js'
|
||||||
|
)
|
||||||
|
|
||||||
|
categories.forEach(category => {
|
||||||
|
const suite = new Suite(category, {
|
||||||
|
minTries: 100,
|
||||||
|
minTime: 1000,
|
||||||
|
})
|
||||||
|
const benchmarkDir = resolve(categoryDir, category)
|
||||||
|
const benchmarks = readdirSync(benchmarkDir)
|
||||||
|
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
|
||||||
|
.map(b => basename(b, extname(b)))
|
||||||
|
|
||||||
|
benchmarks.forEach(benchmark => {
|
||||||
|
if (include && !benchmark.match(include)) return
|
||||||
|
const bench = new Bench(suite, benchmark)
|
||||||
|
const dir = resolve(benchmarkDir, benchmark)
|
||||||
|
const module = require(dir)
|
||||||
|
const fn = module.default
|
||||||
|
bench.input(() => module.input)
|
||||||
|
|
||||||
|
bench.run(input => {
|
||||||
|
fn(input)
|
||||||
|
resetMemoization()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
@@ -1,14 +1,16 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import Plain from '../..'
|
const Plain = require('slate-plain-serializer').default
|
||||||
|
|
||||||
export default function(string) {
|
const input = `
|
||||||
Plain.deserialize(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = `
|
|
||||||
This is editable plain text, just like a text area.
|
This is editable plain text, just like a text area.
|
||||||
`
|
`
|
||||||
.trim()
|
.trim()
|
||||||
.repeat(10)
|
.repeat(10)
|
||||||
|
|
||||||
|
module.exports.input = input
|
||||||
|
|
||||||
|
module.exports.default = function(string) {
|
||||||
|
Plain.deserialize(string)
|
||||||
|
}
|
@@ -1,14 +1,14 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import Plain from '../..'
|
const Plain = require('slate-plain-serializer').default
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(state) {
|
module.exports.default = function(state) {
|
||||||
Plain.serialize(state)
|
Plain.serialize(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = (
|
module.exports.input = (
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
40
benchmark/slate-react/index.js
Normal file
40
benchmark/slate-react/index.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
const { basename, extname, resolve } = require('path')
|
||||||
|
const { readdirSync } = require('fs')
|
||||||
|
const { resetMemoization } = require('slate')
|
||||||
|
const { Suite, Bench } = require('slate-dev-benchmark')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmarks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports.run = function(include) {
|
||||||
|
const categoryDir = resolve(__dirname)
|
||||||
|
const categories = readdirSync(categoryDir).filter(
|
||||||
|
c => c[0] != '.' && c != 'index.js'
|
||||||
|
)
|
||||||
|
|
||||||
|
categories.forEach(category => {
|
||||||
|
const suite = new Suite(category, {
|
||||||
|
minTries: 100,
|
||||||
|
minTime: 1000,
|
||||||
|
})
|
||||||
|
const benchmarkDir = resolve(categoryDir, category)
|
||||||
|
const benchmarks = readdirSync(benchmarkDir)
|
||||||
|
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
|
||||||
|
.map(b => basename(b, extname(b)))
|
||||||
|
|
||||||
|
benchmarks.forEach(benchmark => {
|
||||||
|
if (include && !benchmark.match(include)) return
|
||||||
|
const bench = new Bench(suite, benchmark)
|
||||||
|
const dir = resolve(benchmarkDir, benchmark)
|
||||||
|
const module = require(dir)
|
||||||
|
const fn = module.default
|
||||||
|
bench.input(() => module.input)
|
||||||
|
|
||||||
|
bench.run(input => {
|
||||||
|
fn(input)
|
||||||
|
resetMemoization()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
46
benchmark/slate-react/rendering/decoration.js
Normal file
46
benchmark/slate-react/rendering/decoration.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/** @jsx h */
|
||||||
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
|
const React = require('react')
|
||||||
|
const ReactDOM = require('react-dom/server')
|
||||||
|
const h = require('../../helpers/h')
|
||||||
|
const { Editor } = require('slate-react')
|
||||||
|
|
||||||
|
module.exports.default = function(value) {
|
||||||
|
const el = React.createElement(Editor, { value })
|
||||||
|
ReactDOM.renderToStaticMarkup(el)
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = (
|
||||||
|
<value>
|
||||||
|
<document>
|
||||||
|
{Array.from(Array(10)).map(() => (
|
||||||
|
<quote>
|
||||||
|
<paragraph>
|
||||||
|
<paragraph>
|
||||||
|
This is editable <b>rich</b> text, <i>much</i> better than a
|
||||||
|
textarea!
|
||||||
|
</paragraph>
|
||||||
|
</paragraph>
|
||||||
|
</quote>
|
||||||
|
))}
|
||||||
|
</document>
|
||||||
|
</value>
|
||||||
|
)
|
||||||
|
|
||||||
|
const texts = value.document.getTexts()
|
||||||
|
const decorations = texts.flatMap((t, index) => {
|
||||||
|
if (index % 4 !== 0) return []
|
||||||
|
if (t.length === 0) return []
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
anchorKey: t.key,
|
||||||
|
anchorOffset: 0,
|
||||||
|
focusKey: t.key,
|
||||||
|
focusOffset: 1,
|
||||||
|
marks: [{ type: 'underline' }],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports.input = value.change().setValue({ decorations }).value
|
@@ -1,17 +1,17 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import React from 'react'
|
const React = require('react')
|
||||||
import ReactDOM from 'react-dom/server'
|
const ReactDOM = require('react-dom/server')
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
import { Editor } from '../..'
|
const { Editor } = require('slate-react')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
const el = React.createElement(Editor, { value })
|
const el = React.createElement(Editor, { value })
|
||||||
ReactDOM.renderToStaticMarkup(el)
|
ReactDOM.renderToStaticMarkup(el)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = (
|
module.exports.input = (
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
@@ -1,18 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(change) {
|
module.exports.default = function(change) {
|
||||||
change.deleteBackward()
|
change.deleteBackward()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const change = value.change()
|
|
||||||
return change
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map((v, i) => (
|
{Array.from(Array(10)).map((v, i) => (
|
||||||
@@ -29,3 +24,7 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
module.exports.input = () => {
|
||||||
|
return value.change()
|
||||||
|
}
|
@@ -1,18 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(change) {
|
module.exports.default = function(change) {
|
||||||
change.deleteForward()
|
change.deleteForward()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const change = value.change()
|
|
||||||
return change
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map((v, i) => (
|
{Array.from(Array(10)).map((v, i) => (
|
||||||
@@ -29,3 +24,7 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
module.exports.input = () => {
|
||||||
|
return value.change()
|
||||||
|
}
|
32
benchmark/slate/changes/insert-node-by-key.js
Normal file
32
benchmark/slate/changes/insert-node-by-key.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/** @jsx h */
|
||||||
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
|
module.exports.default = function({ change, block }) {
|
||||||
|
change.insertNodeByKey(block.key, 0, <paragraph>Hello world</paragraph>)
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = (
|
||||||
|
<value>
|
||||||
|
<document>
|
||||||
|
{Array.from(Array(10)).map((v, i) => (
|
||||||
|
<quote>
|
||||||
|
<paragraph>
|
||||||
|
<paragraph>
|
||||||
|
This is editable <b>rich</b> text, <i>much</i> better than a
|
||||||
|
textarea!
|
||||||
|
{i == 0 ? <cursor /> : ''}
|
||||||
|
</paragraph>
|
||||||
|
</paragraph>
|
||||||
|
</quote>
|
||||||
|
))}
|
||||||
|
</document>
|
||||||
|
</value>
|
||||||
|
)
|
||||||
|
const block = value.document.getBlocks().last()
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
const change = value.change()
|
||||||
|
return { change, block }
|
||||||
|
}
|
@@ -1,26 +1,15 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
import { resetMemoization } from '../..'
|
|
||||||
|
|
||||||
export default function({ change, keys }) {
|
module.exports.default = function({ change, keys }) {
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
change.insertTextByKey(key, 0, 'a')
|
change.insertTextByKey(key, 0, 'a')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const change = value.change()
|
|
||||||
const keys = value.document
|
|
||||||
.getTexts()
|
|
||||||
.toArray()
|
|
||||||
.map(t => t.key)
|
|
||||||
resetMemoization()
|
|
||||||
return { change, keys }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map((v, i) => (
|
{Array.from(Array(10)).map((v, i) => (
|
||||||
@@ -37,3 +26,12 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
const keys = value.document
|
||||||
|
.getTexts()
|
||||||
|
.toArray()
|
||||||
|
.map(t => t.key)
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
const change = value.change()
|
||||||
|
return { change, keys }
|
||||||
|
}
|
@@ -1,21 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
import { resetMemoization } from '../..'
|
|
||||||
|
|
||||||
export default function({ change, text }) {
|
module.exports.default = function({ change, text }) {
|
||||||
change.insertTextByKey(text.key, 0, 'a')
|
change.insertTextByKey(text.key, 0, 'a')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const change = value.change()
|
|
||||||
const text = value.document.getLastText()
|
|
||||||
resetMemoization()
|
|
||||||
return { change, text }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map((v, i) => (
|
{Array.from(Array(10)).map((v, i) => (
|
||||||
@@ -32,3 +24,9 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
const text = value.document.getLastText()
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
const change = value.change()
|
||||||
|
return { change, text }
|
||||||
|
}
|
@@ -1,18 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(change) {
|
module.exports.default = function(change) {
|
||||||
change.insertText('a')
|
change.insertText('a')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const change = value.change()
|
|
||||||
return change
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map((v, i) => (
|
{Array.from(Array(10)).map((v, i) => (
|
||||||
@@ -29,3 +24,7 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value.change()
|
||||||
|
}
|
@@ -1,17 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(change) {
|
module.exports.default = function(change) {
|
||||||
change.normalize()
|
change.normalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
return value.change()
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map((v, i) => (
|
{Array.from(Array(10)).map((v, i) => (
|
||||||
@@ -28,3 +24,7 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value.change()
|
||||||
|
}
|
32
benchmark/slate/changes/remove-node-by-key.js
Normal file
32
benchmark/slate/changes/remove-node-by-key.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/** @jsx h */
|
||||||
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
|
module.exports.default = function({ change, text }) {
|
||||||
|
change.removeNodeByKey(text.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = (
|
||||||
|
<value>
|
||||||
|
<document>
|
||||||
|
{Array.from(Array(10)).map((v, i) => (
|
||||||
|
<quote>
|
||||||
|
<paragraph>
|
||||||
|
<paragraph>
|
||||||
|
This is editable <b>rich</b> text, <i>much</i> better than a
|
||||||
|
textarea!
|
||||||
|
{i == 0 ? <cursor /> : ''}
|
||||||
|
</paragraph>
|
||||||
|
</paragraph>
|
||||||
|
</quote>
|
||||||
|
))}
|
||||||
|
</document>
|
||||||
|
</value>
|
||||||
|
)
|
||||||
|
const text = value.document.getLastText()
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
const change = value.change()
|
||||||
|
return { change, text }
|
||||||
|
}
|
@@ -1,18 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(change) {
|
module.exports.default = function(change) {
|
||||||
change.splitBlock()
|
change.splitBlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const change = value.change()
|
|
||||||
return change
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map((v, i) => (
|
{Array.from(Array(10)).map((v, i) => (
|
||||||
@@ -29,3 +24,7 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value.change()
|
||||||
|
}
|
37
benchmark/slate/index.js
Normal file
37
benchmark/slate/index.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
const { readdirSync } = require('fs')
|
||||||
|
const { basename, extname, resolve } = require('path')
|
||||||
|
const { resetMemoization } = require('slate')
|
||||||
|
const { Suite, Bench } = require('slate-dev-benchmark')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmarks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports.run = function(include) {
|
||||||
|
const categoryDir = resolve(__dirname)
|
||||||
|
const categories = readdirSync(categoryDir).filter(
|
||||||
|
c => c[0] != '.' && c != 'index.js'
|
||||||
|
)
|
||||||
|
|
||||||
|
categories.forEach(category => {
|
||||||
|
const suite = new Suite(category, { minTries: 100, minTime: 1000 })
|
||||||
|
const benchmarkDir = resolve(categoryDir, category)
|
||||||
|
const benchmarks = readdirSync(benchmarkDir)
|
||||||
|
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
|
||||||
|
.map(b => basename(b, extname(b)))
|
||||||
|
|
||||||
|
benchmarks.forEach(benchmark => {
|
||||||
|
if (include && !benchmark.match(include)) return
|
||||||
|
const bench = new Bench(suite, benchmark)
|
||||||
|
const dir = resolve(benchmarkDir, benchmark)
|
||||||
|
const module = require(dir)
|
||||||
|
const fn = module.default
|
||||||
|
bench.input(module.input)
|
||||||
|
|
||||||
|
bench.run(input => {
|
||||||
|
fn(input)
|
||||||
|
resetMemoization()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
@@ -1,12 +1,12 @@
|
|||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import { Value } from '../..'
|
const { Value } = require('slate')
|
||||||
|
|
||||||
export default function(json) {
|
module.exports.default = function(json) {
|
||||||
Value.fromJSON(json)
|
Value.fromJSON(json)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = {
|
const input = {
|
||||||
document: {
|
document: {
|
||||||
nodes: Array.from(Array(100)).map(() => ({
|
nodes: Array.from(Array(100)).map(() => ({
|
||||||
type: 'list',
|
type: 'list',
|
||||||
@@ -64,3 +64,7 @@ export const input = {
|
|||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return input
|
||||||
|
}
|
@@ -1,12 +1,12 @@
|
|||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import { Value } from '../..'
|
const { Value } = require('slate')
|
||||||
|
|
||||||
export default function(json) {
|
module.exports.default = function(json) {
|
||||||
Value.fromJSON(json)
|
Value.fromJSON(json)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = {
|
const input = {
|
||||||
document: {
|
document: {
|
||||||
nodes: Array.from(Array(10)).map(() => ({
|
nodes: Array.from(Array(10)).map(() => ({
|
||||||
object: 'block',
|
object: 'block',
|
||||||
@@ -44,3 +44,7 @@ export const input = {
|
|||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return input
|
||||||
|
}
|
@@ -1,17 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
value.document.getCharactersAtRange(value.selection)
|
value.document.getActiveMarksAtRange(value.selection)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
return value.change().selectAll().value
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -27,3 +23,9 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
.change()
|
||||||
|
.selectAll().value
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value
|
||||||
|
}
|
30
benchmark/slate/models/get-ancestors.js
Normal file
30
benchmark/slate/models/get-ancestors.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/** @jsx h */
|
||||||
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
|
module.exports.default = function({ value, text }) {
|
||||||
|
value.document.getAncestors(text.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = (
|
||||||
|
<value>
|
||||||
|
<document>
|
||||||
|
{Array.from(Array(10)).map(() => (
|
||||||
|
<quote>
|
||||||
|
<paragraph>
|
||||||
|
<paragraph>
|
||||||
|
This is editable <b>rich</b> text, <i>much</i> better than a
|
||||||
|
textarea!
|
||||||
|
</paragraph>
|
||||||
|
</paragraph>
|
||||||
|
</quote>
|
||||||
|
))}
|
||||||
|
</document>
|
||||||
|
</value>
|
||||||
|
)
|
||||||
|
const text = value.document.getLastText()
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return { value, text }
|
||||||
|
}
|
@@ -1,17 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
value.document.getBlocksAtRange(value.selection)
|
value.document.getBlocksAtRange(value.selection)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
return value.change().selectAll().value
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -27,3 +23,9 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
.change()
|
||||||
|
.selectAll().value
|
||||||
|
|
||||||
|
module.exports.input = () => {
|
||||||
|
return value
|
||||||
|
}
|
@@ -1,13 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
value.document.getBlocks()
|
value.document.getBlocks()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = (
|
const value = (
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -23,3 +23,7 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value
|
||||||
|
}
|
@@ -1,20 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
import { resetMemoization } from '../..'
|
|
||||||
|
|
||||||
export default function(text) {
|
module.exports.default = function({ value, first, last }) {
|
||||||
text.getLeaves()
|
value.document.getCommonAncestor(first.key, last.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const text = value.document.getFirstText()
|
|
||||||
resetMemoization()
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -30,3 +23,10 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const first = value.document.getFirstText()
|
||||||
|
const last = value.document.getLastText()
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return { value, first, last }
|
||||||
|
}
|
30
benchmark/slate/models/get-furthest-ancestor.js
Normal file
30
benchmark/slate/models/get-furthest-ancestor.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/** @jsx h */
|
||||||
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
|
module.exports.default = function({ value, text }) {
|
||||||
|
value.document.getFurthestAncestor(text.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = (
|
||||||
|
<value>
|
||||||
|
<document>
|
||||||
|
{Array.from(Array(10)).map(() => (
|
||||||
|
<quote>
|
||||||
|
<paragraph>
|
||||||
|
<paragraph>
|
||||||
|
This is editable <b>rich</b> text, <i>much</i> better than a
|
||||||
|
textarea!
|
||||||
|
</paragraph>
|
||||||
|
</paragraph>
|
||||||
|
</quote>
|
||||||
|
))}
|
||||||
|
</document>
|
||||||
|
</value>
|
||||||
|
)
|
||||||
|
const text = value.document.getLastText()
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return { value, text }
|
||||||
|
}
|
@@ -1,17 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
value.document.getInlinesAtRange(value.selection)
|
value.document.getInlinesAtRange(value.selection)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
return value.change().selectAll().value
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -27,3 +23,9 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
.change()
|
||||||
|
.selectAll().value
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value
|
||||||
|
}
|
@@ -1,13 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
value.document.getInlines()
|
value.document.getInlines()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = (
|
const value = (
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -23,3 +23,7 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value
|
||||||
|
}
|
@@ -1,13 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(text) {
|
||||||
value.document.getCharacters()
|
text.getLeaves()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = (
|
const value = (
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -23,3 +23,8 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
const text = value.document.getFirstText()
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return text
|
||||||
|
}
|
@@ -1,17 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
value.document.getMarksAtRange(value.selection)
|
value.document.getMarksAtRange(value.selection)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
return value.change().selectAll().value
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -27,3 +23,9 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
.change()
|
||||||
|
.selectAll().value
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value
|
||||||
|
}
|
@@ -1,13 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
value.document.getMarks()
|
value.document.getMarks()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = (
|
const value = (
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -23,3 +23,7 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value
|
||||||
|
}
|
30
benchmark/slate/models/get-parent.js
Normal file
30
benchmark/slate/models/get-parent.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/** @jsx h */
|
||||||
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
|
module.exports.default = function({ value, text }) {
|
||||||
|
value.document.getParent(text.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = (
|
||||||
|
<value>
|
||||||
|
<document>
|
||||||
|
{Array.from(Array(10)).map(() => (
|
||||||
|
<quote>
|
||||||
|
<paragraph>
|
||||||
|
<paragraph>
|
||||||
|
This is editable <b>rich</b> text, <i>much</i> better than a
|
||||||
|
textarea!
|
||||||
|
</paragraph>
|
||||||
|
</paragraph>
|
||||||
|
</quote>
|
||||||
|
))}
|
||||||
|
</document>
|
||||||
|
</value>
|
||||||
|
)
|
||||||
|
const text = value.document.getLastText()
|
||||||
|
|
||||||
|
module.exports.input = () => {
|
||||||
|
return { value, text }
|
||||||
|
}
|
@@ -1,20 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
import { resetMemoization } from '../..'
|
|
||||||
|
|
||||||
export default function({ value, text }) {
|
module.exports.default = function({ value, text }) {
|
||||||
value.document.getPath(text.key)
|
value.document.getPath(text.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const text = value.document.getLastText()
|
|
||||||
resetMemoization()
|
|
||||||
return { value, text }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -30,3 +23,8 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
const text = value.document.getLastText()
|
||||||
|
|
||||||
|
module.exports.input = () => {
|
||||||
|
return { value, text }
|
||||||
|
}
|
@@ -1,17 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
value.document.getTextsAtRange(value.selection)
|
value.document.getTextsAtRange(value.selection)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
return value.change().selectAll().value
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -27,3 +23,9 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
.change()
|
||||||
|
.selectAll().value
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value
|
||||||
|
}
|
@@ -1,13 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
value.document.getTexts()
|
value.document.getTexts()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = (
|
const value = (
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -23,3 +23,7 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value
|
||||||
|
}
|
30
benchmark/slate/models/getDescendant.js
Normal file
30
benchmark/slate/models/getDescendant.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/** @jsx h */
|
||||||
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
|
module.exports.default = function({ value, text }) {
|
||||||
|
value.document.getDescendant(text.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = (
|
||||||
|
<value>
|
||||||
|
<document>
|
||||||
|
{Array.from(Array(10)).map(() => (
|
||||||
|
<quote>
|
||||||
|
<paragraph>
|
||||||
|
<paragraph>
|
||||||
|
This is editable <b>rich</b> text, <i>much</i> better than a
|
||||||
|
textarea!
|
||||||
|
</paragraph>
|
||||||
|
</paragraph>
|
||||||
|
</quote>
|
||||||
|
))}
|
||||||
|
</document>
|
||||||
|
</value>
|
||||||
|
)
|
||||||
|
const text = value.document.getLastText()
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return { value, text }
|
||||||
|
}
|
@@ -1,25 +1,15 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
import { resetMemoization } from '../..'
|
|
||||||
|
|
||||||
export default function({ value, keys }) {
|
module.exports.default = function({ value, keys }) {
|
||||||
keys.forEach(key => {
|
keys.forEach(key => {
|
||||||
value.document.hasNode(key)
|
value.document.hasNode(key)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const keys = value.document
|
|
||||||
.getTexts()
|
|
||||||
.toArray()
|
|
||||||
.map(t => t.key)
|
|
||||||
resetMemoization()
|
|
||||||
return { value, keys }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -35,3 +25,11 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
const keys = value.document
|
||||||
|
.getTexts()
|
||||||
|
.toArray()
|
||||||
|
.map(t => t.key)
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return { value, keys }
|
||||||
|
}
|
@@ -1,20 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
import { resetMemoization } from '../..'
|
|
||||||
|
|
||||||
export default function({ value, text }) {
|
module.exports.default = function({ value, text }) {
|
||||||
value.document.hasNode(text.key)
|
value.document.hasNode(text.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const text = value.document.getLastText()
|
|
||||||
resetMemoization()
|
|
||||||
return { value, text }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -30,3 +23,8 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
const text = value.document.getLastText()
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return { value, text }
|
||||||
|
}
|
@@ -1,13 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
|
|
||||||
export default function(value) {
|
module.exports.default = function(value) {
|
||||||
value.toJSON()
|
value.toJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const input = (
|
const value = (
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -23,3 +23,7 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return value
|
||||||
|
}
|
@@ -1,23 +1,13 @@
|
|||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
|
|
||||||
import h from '../../test/helpers/h'
|
const h = require('../../helpers/h')
|
||||||
import { resetMemoization } from '../..'
|
|
||||||
|
|
||||||
export default function({ value, next }) {
|
module.exports.default = function({ value, next }) {
|
||||||
value.document.updateNode(next)
|
value.document.updateNode(next)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function before(value) {
|
const value = (
|
||||||
const texts = value.document.getTexts()
|
|
||||||
const { size } = texts
|
|
||||||
const text = texts.get(Math.round(size / 2))
|
|
||||||
const next = text.insertText(0, 'some text')
|
|
||||||
resetMemoization()
|
|
||||||
return { value, next }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = (
|
|
||||||
<value>
|
<value>
|
||||||
<document>
|
<document>
|
||||||
{Array.from(Array(10)).map(() => (
|
{Array.from(Array(10)).map(() => (
|
||||||
@@ -33,3 +23,12 @@ export const input = (
|
|||||||
</document>
|
</document>
|
||||||
</value>
|
</value>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const texts = value.document.getTexts()
|
||||||
|
const { size } = texts
|
||||||
|
const text = texts.get(Math.round(size / 2))
|
||||||
|
const next = text.insertText(0, 'some text')
|
||||||
|
|
||||||
|
module.exports.input = function() {
|
||||||
|
return { value, next }
|
||||||
|
}
|
12
package.json
12
package.json
@@ -16,17 +16,20 @@
|
|||||||
"babel-preset-stage-0": "^6.24.1",
|
"babel-preset-stage-0": "^6.24.1",
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"chalk": "^1.1.3",
|
"chalk": "^1.1.3",
|
||||||
|
"commander": "^2.15.1",
|
||||||
"copy-webpack-plugin": "^4.4.1",
|
"copy-webpack-plugin": "^4.4.1",
|
||||||
"cross-env": "^5.1.3",
|
"cross-env": "^5.1.3",
|
||||||
"css-loader": "^0.28.9",
|
"css-loader": "^0.28.9",
|
||||||
"emotion": "^9.2.4",
|
"emotion": "^9.2.4",
|
||||||
"eslint": "^4.19.1",
|
"eslint": "^4.19.1",
|
||||||
|
"emojis": "^1.0.10",
|
||||||
"eslint-config-prettier": "^2.9.0",
|
"eslint-config-prettier": "^2.9.0",
|
||||||
"eslint-plugin-import": "^2.8.0",
|
"eslint-plugin-import": "^2.8.0",
|
||||||
"eslint-plugin-prettier": "^2.5.0",
|
"eslint-plugin-prettier": "^2.5.0",
|
||||||
"eslint-plugin-react": "^7.6.0",
|
"eslint-plugin-react": "^7.6.0",
|
||||||
"extract-text-webpack-plugin": "^3.0.2",
|
"extract-text-webpack-plugin": "^3.0.2",
|
||||||
"faker": "^3.1.0",
|
"faker": "^3.1.0",
|
||||||
|
"figures": "^2.0.0",
|
||||||
"fs-promise": "^1.0.0",
|
"fs-promise": "^1.0.0",
|
||||||
"gh-pages": "^0.11.0",
|
"gh-pages": "^0.11.0",
|
||||||
"html-webpack-plugin": "^2.30.1",
|
"html-webpack-plugin": "^2.30.1",
|
||||||
@@ -62,6 +65,7 @@
|
|||||||
"rollup-plugin-sourcemaps": "^0.4.2",
|
"rollup-plugin-sourcemaps": "^0.4.2",
|
||||||
"rollup-plugin-uglify": "^3.0.0",
|
"rollup-plugin-uglify": "^3.0.0",
|
||||||
"slate-collapse-on-escape": "^0.6.0",
|
"slate-collapse-on-escape": "^0.6.0",
|
||||||
|
"slate-dev-benchmark": "*",
|
||||||
"slate-soft-break": "^0.6.0",
|
"slate-soft-break": "^0.6.0",
|
||||||
"source-map-loader": "^0.2.3",
|
"source-map-loader": "^0.2.3",
|
||||||
"source-map-support": "^0.4.0",
|
"source-map-support": "^0.4.0",
|
||||||
@@ -79,13 +83,15 @@
|
|||||||
"slate-schema-violations": "*"
|
"slate-schema-violations": "*"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"benchmark": "mkdir -p ./tmp && cross-env BABEL_ENV=test babel-node ./node_modules/.bin/_matcha --reporter ./support/benchmark/reporter ./packages/*/benchmark/index.js > ./tmp/benchmark-comparison.json && cross-env BABEL_ENV=test babel-node ./support/benchmark/compare",
|
"benchmark": "cross-env COMPARE=compare node --expose-gc ./tmp/benchmark/index.js",
|
||||||
"benchmark:save": "mkdir -p ./tmp && cross-env BABEL_ENV=test babel-node ./node_modules/.bin/_matcha --reporter ./support/benchmark/reporter ./packages/*/benchmark/index.js > ./tmp/benchmark-baseline.json",
|
"benchmark:save": " yarn benchmark:prepare && node --expose-gc ./tmp/benchmark/index.js",
|
||||||
|
"benchmark:prepare": "mkdir -p ./tmp && cross-env BABEL_ENV=benchmark babel benchmark --out-dir tmp/benchmark/",
|
||||||
|
"bootstrap": "lerna bootstrap && yarn build",
|
||||||
"build": "rollup --config ./support/rollup/config.js",
|
"build": "rollup --config ./support/rollup/config.js",
|
||||||
"build:production": "cross-env NODE_ENV=production rollup --config ./support/rollup/config.js && cross-env NODE_ENV=production webpack --config support/webpack/config.js",
|
"build:production": "cross-env NODE_ENV=production rollup --config ./support/rollup/config.js && cross-env NODE_ENV=production webpack --config support/webpack/config.js",
|
||||||
"clean": "lerna run clean && rm -rf ./node_modules ./dist ./build",
|
"clean": "lerna run clean && rm -rf ./node_modules ./dist ./build",
|
||||||
"gh-pages": "gh-pages --dist ./build",
|
"gh-pages": "gh-pages --dist ./build",
|
||||||
"lint": "eslint packages/*/src packages/*/test examples/*/*.js examples/dev/*/*.js && prettier --list-different '**/*.{js,jsx,md,json,css}'",
|
"lint": "eslint benchmark packages/*/src packages/*/test examples/*/*.js examples/dev/*/*.js && prettier --list-different '**/*.{js,jsx,md,json,css}'",
|
||||||
"open": "open http://localhost:8080",
|
"open": "open http://localhost:8080",
|
||||||
"prettier": "prettier --write '**/*.{js,jsx,md,json,css}'",
|
"prettier": "prettier --write '**/*.{js,jsx,md,json,css}'",
|
||||||
"release": "yarn build:production && yarn test && yarn lint && lerna publish && yarn gh-pages",
|
"release": "yarn build:production && yarn test && yarn lint && lerna publish && yarn gh-pages",
|
||||||
|
1
packages/slate-dev-benchmark/Readme.md
Normal file
1
packages/slate-dev-benchmark/Readme.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
This package contains 'Suite' and 'Bench' that Slate uses to compare computation efficiency under nodeJS.
|
15
packages/slate-dev-benchmark/package.json
Normal file
15
packages/slate-dev-benchmark/package.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "slate-dev-benchmark",
|
||||||
|
"description": "A simple, development-only benchmark for Slate",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "git://github.com/ianstormtaylor/slate.git",
|
||||||
|
"main": "src/index.js",
|
||||||
|
"devDependencies": {
|
||||||
|
"mocha": "^2.5.3"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rm -rf ./dist ./lib ./node_modules"
|
||||||
|
},
|
||||||
|
"keywords": ["slate"]
|
||||||
|
}
|
227
packages/slate-dev-benchmark/src/Bench.js
Normal file
227
packages/slate-dev-benchmark/src/Bench.js
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
/* global Promise */
|
||||||
|
const { BenchType } = require('./types')
|
||||||
|
const { makeOptions } = require('./makeOptions')
|
||||||
|
const { Timer } = require('./Timer')
|
||||||
|
const { logger } = require('./logger')
|
||||||
|
|
||||||
|
const errorReport = {
|
||||||
|
cycles: NaN,
|
||||||
|
user: NaN,
|
||||||
|
system: NaN,
|
||||||
|
all: NaN,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a task and calculate the time consuming of tasks
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Bench {
|
||||||
|
/**
|
||||||
|
* Construct a bench and register it to a Suite
|
||||||
|
* @param {Suite} suite
|
||||||
|
* @param {string} name
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(suite, name, options = {}) {
|
||||||
|
this.name = name
|
||||||
|
this.options = makeOptions({ ...suite.options, ...options })
|
||||||
|
this.isFinished = false
|
||||||
|
this.inputer = () => undefined
|
||||||
|
this.runner = () => {}
|
||||||
|
this.report = { ...errorReport }
|
||||||
|
suite.addBench(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a Bench?
|
||||||
|
* @param {any} obj
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
isBench(obj) {
|
||||||
|
return obj && obj[BenchType]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the method to generate (different} inputs for each run
|
||||||
|
* @param {Array|Function|Scalar} inputer
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
input(inputer) {
|
||||||
|
if (Array.isArray(inputer)) {
|
||||||
|
this.inputer = index => inputer[index % inputer.length]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof inputer === 'function') {
|
||||||
|
this.inputer = inputer
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.inputer = () => inputer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the task runner
|
||||||
|
* @param {Function} runner
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
run(runner) {
|
||||||
|
this.runner = runner
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to run tasks in `times`, if the time consuming excedes the max-time, then stop;
|
||||||
|
* After run, generate report and return
|
||||||
|
* If initial is the initial index to run the task, for continueing a task in adaptive mode
|
||||||
|
* @param {number} times
|
||||||
|
* @param {number} initial
|
||||||
|
*/
|
||||||
|
|
||||||
|
async compose(times, initial) {
|
||||||
|
times = Math.floor(times)
|
||||||
|
const isAsync = this.options.async
|
||||||
|
const { runner, inputer } = this
|
||||||
|
|
||||||
|
const { maxTime } = this.options
|
||||||
|
let seq = Number.isFinite(this.options.maxTries) ? 1 : NaN
|
||||||
|
let nextCheckIndex = seq
|
||||||
|
const hrStart = process.hrtime()
|
||||||
|
|
||||||
|
if (global.gc) {
|
||||||
|
global.gc()
|
||||||
|
}
|
||||||
|
|
||||||
|
const report = { user: 0, system: 0, all: 0, hr: 0, cycles: 0 }
|
||||||
|
|
||||||
|
for (
|
||||||
|
let initialIndex = initial;
|
||||||
|
initialIndex < times;
|
||||||
|
initialIndex += this.options.allocationTries
|
||||||
|
) {
|
||||||
|
const tries = Math.min(times - initialIndex, this.options.allocationTries)
|
||||||
|
const thisTryReport = await runBundleTasks.call(this, tries, initialIndex)
|
||||||
|
|
||||||
|
if (global.gc) {
|
||||||
|
global.gc()
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key in report) {
|
||||||
|
report[key] += thisTryReport[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return report
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a bundle of tasks;
|
||||||
|
* the Bench estimate the time consuming of every `tries` tasks, then explictly run gc, and caculate the time consuming of next bundle tasks
|
||||||
|
* @param {number} tries
|
||||||
|
* @param {number} initialIndex
|
||||||
|
* @return {Promise< Object , *>}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function runBundleTasks(tries, initialIndex) {
|
||||||
|
const inputs = Array.from({ length: tries }).map(index =>
|
||||||
|
inputer(index + initialIndex)
|
||||||
|
)
|
||||||
|
const timer = new Timer()
|
||||||
|
timer.start()
|
||||||
|
return runFrom(0).then(cycles => {
|
||||||
|
timer.end()
|
||||||
|
const { elapsed } = timer
|
||||||
|
return { ...elapsed, cycles }
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a single task run; If the task is end, return a Promise with the index when the task ends
|
||||||
|
* @param {number} index
|
||||||
|
* @return {Promise<number, *>}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function runFrom(index) {
|
||||||
|
if (index === tries) return Promise.resolve(tries)
|
||||||
|
|
||||||
|
if (index === nextCheckIndex) {
|
||||||
|
const hrEnd = process.hrtime(hrStart)
|
||||||
|
const elapsed = hrEnd[0] * 1e3 + hrEnd[1] / 1e6
|
||||||
|
|
||||||
|
if (elapsed > maxTime) {
|
||||||
|
return Promise.resolve(index)
|
||||||
|
} else {
|
||||||
|
if (elapsed < maxTime / 20) {
|
||||||
|
seq *= 2
|
||||||
|
}
|
||||||
|
|
||||||
|
nextCheckIndex = seq + nextCheckIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isAsync) {
|
||||||
|
const inputVar = inputs[index]
|
||||||
|
runner(inputVar)
|
||||||
|
return runFrom(index + 1)
|
||||||
|
} else {
|
||||||
|
return Promise.resolve(runner(inputs[index])).then(() =>
|
||||||
|
runFrom(index + 1)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Run the bench
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
makeRun() {
|
||||||
|
if (this.isFinished) return true
|
||||||
|
logger(this)
|
||||||
|
const { options } = this
|
||||||
|
const { minTries, maxTime, maxTries } = options
|
||||||
|
|
||||||
|
let { minTime } = options
|
||||||
|
if (minTime > maxTime) minTime = maxTime
|
||||||
|
|
||||||
|
return this.compose(minTries, 0)
|
||||||
|
.then(report => {
|
||||||
|
if (this.options.mode === 'static') return report
|
||||||
|
const { all } = report
|
||||||
|
if (all > minTime) return report
|
||||||
|
const times = (minTime / all - 1) * minTries
|
||||||
|
return this.compose(Math.min(times, maxTries), minTries).then(
|
||||||
|
newReport => {
|
||||||
|
return mergeResults(report, newReport)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.then(report => {
|
||||||
|
this.report = report
|
||||||
|
this.isFinished = true
|
||||||
|
logger(this)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bench.prototype[BenchType] = true
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Merge two different report
|
||||||
|
* @param {Object} res1
|
||||||
|
* @param {Object} res2
|
||||||
|
*/
|
||||||
|
|
||||||
|
function mergeResults(res1, res2) {
|
||||||
|
const result = {}
|
||||||
|
|
||||||
|
for (const key in res1) {
|
||||||
|
result[key] = res1[key] + res2[key]
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { Bench }
|
73
packages/slate-dev-benchmark/src/Repository.js
Normal file
73
packages/slate-dev-benchmark/src/Repository.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/* global Promise */
|
||||||
|
const { RepositoryType } = require('./types')
|
||||||
|
const { logger } = require('./logger')
|
||||||
|
const { compose } = require('./compose')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository Class for holding Suite
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Repository {
|
||||||
|
/**
|
||||||
|
* Construct a Repository with a name
|
||||||
|
* @param {string} name
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(name = 'default') {
|
||||||
|
this.name = name
|
||||||
|
this.suites = []
|
||||||
|
this.report = {}
|
||||||
|
this.isFinished = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether {obj} is repository
|
||||||
|
* @param {any} obj
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
isRepository(obj) {
|
||||||
|
return obj && obj[RepositoryType]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a suite to the repository
|
||||||
|
* @param {Suite} suite
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
addSuite(suite) {
|
||||||
|
this.isFinished = false
|
||||||
|
this.suites.push(suite)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run all suites (and all benches under suites) and generate a report
|
||||||
|
* @return {Promise<Object, *>}
|
||||||
|
*/
|
||||||
|
|
||||||
|
run() {
|
||||||
|
if (this.isFinished) return Promise.resolve(this.report)
|
||||||
|
logger(this)
|
||||||
|
return compose(this.suites).then(() => {
|
||||||
|
this.isFinished = true
|
||||||
|
const report = {}
|
||||||
|
|
||||||
|
for (const suite of this.suites) {
|
||||||
|
report[suite.name] = suite.report
|
||||||
|
}
|
||||||
|
|
||||||
|
this.report = report
|
||||||
|
return report
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Repository.prototype[RepositoryType] = true
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, all suites are registers to the following {repo}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const repo = new Repository()
|
||||||
|
|
||||||
|
module.exports = { Repository, repo }
|
85
packages/slate-dev-benchmark/src/Suite.js
Normal file
85
packages/slate-dev-benchmark/src/Suite.js
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/* global Promise */
|
||||||
|
const { repo } = require('./Repository.js')
|
||||||
|
const { SuiteType } = require('./types')
|
||||||
|
const { logger } = require('./logger')
|
||||||
|
const { compose } = require('./compose')
|
||||||
|
const { makeOptions } = require('./makeOptions')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suite is for holding Benches
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Suite {
|
||||||
|
/**
|
||||||
|
* Construct a Suite and regiester it to repository
|
||||||
|
* @param {string} name
|
||||||
|
* @param {Object} options
|
||||||
|
* @property {void|Repository} repository
|
||||||
|
* @property {any} ...rest
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(name, options = {}) {
|
||||||
|
const { repository = repo } = options
|
||||||
|
|
||||||
|
if (repository[name]) {
|
||||||
|
throw Error(`The suite name ${name} has benn occupied in repository`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof name !== 'string') {
|
||||||
|
throw Error(`The suite name must be a string`)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.name = name
|
||||||
|
this.options = makeOptions(options)
|
||||||
|
this.isFinished = false
|
||||||
|
this.benches = []
|
||||||
|
this.report = {}
|
||||||
|
repository.addSuite(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether it is a Suite
|
||||||
|
* @param {any} obj
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
isSuite(obj) {
|
||||||
|
return obj && obj[SuiteType]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an bench to the repository
|
||||||
|
* @param {Bench} bench
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
addBench(bench) {
|
||||||
|
this.isFinished = false
|
||||||
|
this.benches.push(bench)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run all benches, and generate report for consumed time
|
||||||
|
* @return {Promise<Object, *>
|
||||||
|
*/
|
||||||
|
|
||||||
|
makeRun() {
|
||||||
|
if (this.isFinished) return Promise.resolve(this.report)
|
||||||
|
logger(this)
|
||||||
|
return compose(this.benches).then(() => {
|
||||||
|
this.isFinished = true
|
||||||
|
const report = {}
|
||||||
|
|
||||||
|
for (const bench of this.benches) {
|
||||||
|
report[bench.name] = bench.report
|
||||||
|
}
|
||||||
|
|
||||||
|
this.report = report
|
||||||
|
return report
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Suite.prototype[SuiteType] = true
|
||||||
|
|
||||||
|
module.exports = { Suite }
|
66
packages/slate-dev-benchmark/src/Timer.js
Normal file
66
packages/slate-dev-benchmark/src/Timer.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
const { TimerType } = require('./types')
|
||||||
|
|
||||||
|
class Timer {
|
||||||
|
constructor() {
|
||||||
|
this.cpuStartTime = {}
|
||||||
|
this.hrStartTime = null
|
||||||
|
this.isStopped = false
|
||||||
|
this.elapsed = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether it is a Timer
|
||||||
|
* @param {any} obj
|
||||||
|
*/
|
||||||
|
|
||||||
|
isTimer(obj) {
|
||||||
|
return obj && obj[TimerType]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the timer
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.isStopped = false
|
||||||
|
this.cpuStartTime = process.cpuUsage()
|
||||||
|
this.hrStartTime = process.hrtime()
|
||||||
|
this.elapsed = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the timer and store restore in this.elapsed
|
||||||
|
* @return {Object}
|
||||||
|
*/
|
||||||
|
|
||||||
|
end() {
|
||||||
|
if (this.isStopped) return this.elapsed
|
||||||
|
const cpuElapsed = process.cpuUsage(this.cpuStartTime)
|
||||||
|
const hrElapsed = process.hrtime(this.hrStartTime)
|
||||||
|
const { user, system } = cpuElapsed
|
||||||
|
const hr = hrElapsed[0] * 1000 + hrElapsed[1] / 1e6
|
||||||
|
|
||||||
|
/**
|
||||||
|
* user: cpu time consumed in user space
|
||||||
|
* system: cpu time consumed in system space
|
||||||
|
* all: user+system
|
||||||
|
* hr: real world time
|
||||||
|
* (unit): ms
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.elapsed = {
|
||||||
|
user: user / 1000,
|
||||||
|
system: system / 1000,
|
||||||
|
all: (user + system) / 1000,
|
||||||
|
hr,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isStopped = true
|
||||||
|
return this.elapsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer.prototype[TimerType] = true
|
||||||
|
|
||||||
|
module.exports = { Timer }
|
22
packages/slate-dev-benchmark/src/compose.js
Normal file
22
packages/slate-dev-benchmark/src/compose.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/* global Promise */
|
||||||
|
const { errorLog } = require('./logger')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run all benches/suites with Promise; Ensure an error would not block the whole process
|
||||||
|
* @param {Array<Suite>|Array<Bench>}
|
||||||
|
* @param {string} name; where to call the run method
|
||||||
|
*/
|
||||||
|
|
||||||
|
function compose(list, name = 'makeRun') {
|
||||||
|
return dispatch(0)
|
||||||
|
|
||||||
|
function dispatch(index) {
|
||||||
|
if (index === list.length) return Promise.resolve(true)
|
||||||
|
const node = list[index]
|
||||||
|
return new Promise(resolve => resolve(node[name]()))
|
||||||
|
.catch(err => errorLog(err))
|
||||||
|
.then(() => dispatch(index + 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { compose }
|
5
packages/slate-dev-benchmark/src/index.js
Normal file
5
packages/slate-dev-benchmark/src/index.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
const { Repository, repo } = require('./Repository')
|
||||||
|
const { Suite } = require('./Suite')
|
||||||
|
const { Bench } = require('./Bench')
|
||||||
|
|
||||||
|
module.exports = { Repository, Suite, Bench, repo }
|
74
packages/slate-dev-benchmark/src/logger.js
Normal file
74
packages/slate-dev-benchmark/src/logger.js
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IS in test
|
||||||
|
*/
|
||||||
|
|
||||||
|
const IS_TEST =
|
||||||
|
typeof process !== 'undefined' &&
|
||||||
|
process.env &&
|
||||||
|
process.env.BABEL_ENV === 'test'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a `message`
|
||||||
|
*
|
||||||
|
* @param {String} message
|
||||||
|
* @param {Any} ...args
|
||||||
|
* @retrun {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function log(message, ...args) {
|
||||||
|
if (IS_TEST) return
|
||||||
|
|
||||||
|
return console.log(message, ...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Log a error `message`
|
||||||
|
*/
|
||||||
|
|
||||||
|
function errorLog(message, ...args) {
|
||||||
|
console.error(message, ...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logging benchmark result
|
||||||
|
*/
|
||||||
|
|
||||||
|
function logger(obj) {
|
||||||
|
const prefix = ' '
|
||||||
|
|
||||||
|
if (obj.isRepository) {
|
||||||
|
return log(`Repository ${obj.name} is running`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.isSuite) {
|
||||||
|
return log(`${prefix}- Suite ${obj.name} is running`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.isBench) {
|
||||||
|
if (!obj.isFinished) {
|
||||||
|
return log(`${prefix + prefix}- Bench ${obj.name} is running`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { report } = obj
|
||||||
|
const { cycles } = report
|
||||||
|
|
||||||
|
const header = {
|
||||||
|
user: 'user:',
|
||||||
|
hr: 'real:',
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key of ['user', 'hr']) {
|
||||||
|
log(
|
||||||
|
`${prefix + prefix + prefix}${header[key]} * ${cycles} cycles: ${
|
||||||
|
report[key]
|
||||||
|
} ms; ( ${cycles * 1000 / report[key]} ops/sec)`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return log(`${prefix + prefix + prefix}cycles: ${cycles}`)
|
||||||
|
}
|
||||||
|
return log(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { logger, errorLog, log }
|
40
packages/slate-dev-benchmark/src/makeOptions.js
Normal file
40
packages/slate-dev-benchmark/src/makeOptions.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
const defaultOptions = {
|
||||||
|
minTime: 1000,
|
||||||
|
maxTime: 2000,
|
||||||
|
minTries: 100,
|
||||||
|
maxTries: Infinity,
|
||||||
|
allocationTries: 1000,
|
||||||
|
async: false,
|
||||||
|
mode: 'adaptive',
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge two options for configuring a bench run
|
||||||
|
* @param {Object} options
|
||||||
|
* @returns {Object}
|
||||||
|
* @property {number} minTime
|
||||||
|
* @property {number} maxTime
|
||||||
|
* @property {number} minTries
|
||||||
|
* @property {number} maxTries
|
||||||
|
* @property {number} allocationTries
|
||||||
|
* @property {boolean} async
|
||||||
|
* @property {"static"|"adaptive"} mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
function makeOptions(options) {
|
||||||
|
const result = { ...defaultOptions, ...options }
|
||||||
|
|
||||||
|
for (const key in defaultOptions) {
|
||||||
|
const shallType = typeof defaultOptions[key]
|
||||||
|
const inputType = typeof result[key]
|
||||||
|
|
||||||
|
if (shallType !== inputType) {
|
||||||
|
throw TypeError(
|
||||||
|
`Wrong Input in Config Suite, options[${key}] should be ${shallType}, but the input type is ${inputType}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { makeOptions }
|
11
packages/slate-dev-benchmark/src/types.js
Normal file
11
packages/slate-dev-benchmark/src/types.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
const RepositoryType = '@@__SLATE_REPOSITORY__@@'
|
||||||
|
const SuiteType = '@@__SLATE_SUITE__@@'
|
||||||
|
const BenchType = '@@__SLATE_BENCH__@@'
|
||||||
|
const TimerType = '@@__SLATE_BENCH_TIMER_@@'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
RepositoryType,
|
||||||
|
SuiteType,
|
||||||
|
BenchType,
|
||||||
|
TimerType,
|
||||||
|
}
|
12
packages/slate-dev-benchmark/test/index.js
Normal file
12
packages/slate-dev-benchmark/test/index.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Dependencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests.
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('slate-dev-benchmark', () => {
|
||||||
|
require('./tries/')
|
||||||
|
require('./time/')
|
||||||
|
})
|
22
packages/slate-dev-benchmark/test/time/index.js
Normal file
22
packages/slate-dev-benchmark/test/time/index.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { repo, Suite } from '../..'
|
||||||
|
import fs from 'fs'
|
||||||
|
import { resolve } from 'path'
|
||||||
|
|
||||||
|
describe('time', async () => {
|
||||||
|
const suite = new Suite('tries')
|
||||||
|
const testDir = resolve(__dirname)
|
||||||
|
const files = fs
|
||||||
|
.readdirSync(testDir)
|
||||||
|
.filter(x => x[0] !== '.' && x !== 'index.js')
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const module = require(`./${file}`)
|
||||||
|
|
||||||
|
it(module.experiment, () => {
|
||||||
|
module.default(suite)
|
||||||
|
const { expected } = module
|
||||||
|
repo.isFinished = false
|
||||||
|
return repo.run().then(() => expected())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
31
packages/slate-dev-benchmark/test/time/max-time-async.js
Normal file
31
packages/slate-dev-benchmark/test/time/max-time-async.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/* global Promise */
|
||||||
|
import { Bench } from '../..'
|
||||||
|
import assert from 'assert'
|
||||||
|
|
||||||
|
export const experiment = 'max-time-async'
|
||||||
|
|
||||||
|
let index = 0
|
||||||
|
|
||||||
|
// A wider range than sync, becuase Promise intialization, babel-node takes time
|
||||||
|
export function expected() {
|
||||||
|
assert(
|
||||||
|
index > 5 && index < 12,
|
||||||
|
`index should be 10, but is actually ${index}`
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function(suite) {
|
||||||
|
const bench = new Bench(suite, experiment, {
|
||||||
|
mode: 'adaptive',
|
||||||
|
minTries: 100,
|
||||||
|
maxTries: 200,
|
||||||
|
minTime: 1,
|
||||||
|
maxTime: 100,
|
||||||
|
async: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
bench.run(
|
||||||
|
() => new Promise(resolve => setTimeout(() => resolve(index++), 10))
|
||||||
|
)
|
||||||
|
}
|
@@ -0,0 +1,31 @@
|
|||||||
|
import { Bench } from '../..'
|
||||||
|
import { syncSleep } from '../utils/sleep'
|
||||||
|
import assert from 'assert'
|
||||||
|
|
||||||
|
export const experiment = 'max-time'
|
||||||
|
|
||||||
|
let index = 0
|
||||||
|
|
||||||
|
export function expected() {
|
||||||
|
assert(
|
||||||
|
index > 85 && index < 115,
|
||||||
|
`index should be around 100, but is actually ${index}`
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function(suite) {
|
||||||
|
const bench = new Bench(suite, experiment, {
|
||||||
|
mode: 'adaptive',
|
||||||
|
minTries: 1000,
|
||||||
|
maxTries: 2000,
|
||||||
|
minTime: 1,
|
||||||
|
maxTime: 1000,
|
||||||
|
async: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
bench.run(() => {
|
||||||
|
syncSleep(10)
|
||||||
|
index++
|
||||||
|
})
|
||||||
|
}
|
28
packages/slate-dev-benchmark/test/time/max-time.js
Normal file
28
packages/slate-dev-benchmark/test/time/max-time.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { Bench } from '../..'
|
||||||
|
import { syncSleep } from '../utils/sleep'
|
||||||
|
import assert from 'assert'
|
||||||
|
|
||||||
|
export const experiment = 'max-time'
|
||||||
|
|
||||||
|
let index = 0
|
||||||
|
|
||||||
|
export function expected() {
|
||||||
|
assert(index === 10, `index should be 10, but is actually ${index}`)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function(suite) {
|
||||||
|
const bench = new Bench(suite, experiment, {
|
||||||
|
mode: 'adaptive',
|
||||||
|
minTries: 100,
|
||||||
|
maxTries: 200,
|
||||||
|
minTime: 1,
|
||||||
|
maxTime: 100,
|
||||||
|
async: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
bench.run(() => {
|
||||||
|
syncSleep(10)
|
||||||
|
index++
|
||||||
|
})
|
||||||
|
}
|
25
packages/slate-dev-benchmark/test/tries/index.js
Normal file
25
packages/slate-dev-benchmark/test/tries/index.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import assert from 'assert'
|
||||||
|
import { repo, Suite } from '../..'
|
||||||
|
import fs from 'fs'
|
||||||
|
import { resolve } from 'path'
|
||||||
|
|
||||||
|
describe('tries', async () => {
|
||||||
|
const suite = new Suite('tries')
|
||||||
|
const testDir = resolve(__dirname)
|
||||||
|
const files = fs
|
||||||
|
.readdirSync(testDir)
|
||||||
|
.filter(x => x[0] !== '.' && x !== 'index.js')
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const module = require(`./${file}`)
|
||||||
|
|
||||||
|
it(module.experiment, () => {
|
||||||
|
module.default(suite)
|
||||||
|
const { actual, expected } = module
|
||||||
|
repo.isFinished = false
|
||||||
|
return repo.run().then(() => {
|
||||||
|
assert.deepEqual(actual, expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
19
packages/slate-dev-benchmark/test/tries/max-tries.js
Normal file
19
packages/slate-dev-benchmark/test/tries/max-tries.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { Bench } from '../..'
|
||||||
|
|
||||||
|
export const experiment = 'max-tries adaptive mode'
|
||||||
|
export const actual = { index: 0 }
|
||||||
|
export const expected = { index: 200 }
|
||||||
|
|
||||||
|
export default function(suite) {
|
||||||
|
const bench = new Bench(suite, experiment, {
|
||||||
|
mode: 'adaptive',
|
||||||
|
minTries: 100,
|
||||||
|
maxTries: 200,
|
||||||
|
minTime: 100,
|
||||||
|
maxTime: Infinity,
|
||||||
|
})
|
||||||
|
|
||||||
|
bench.run(() => {
|
||||||
|
actual.index++
|
||||||
|
})
|
||||||
|
}
|
18
packages/slate-dev-benchmark/test/tries/min-tries.js
Normal file
18
packages/slate-dev-benchmark/test/tries/min-tries.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Bench } from '../..'
|
||||||
|
|
||||||
|
export const experiment = 'min-tries static mode'
|
||||||
|
export const actual = { index: 0 }
|
||||||
|
export const expected = { index: 100 }
|
||||||
|
|
||||||
|
export default function(suite) {
|
||||||
|
const bench = new Bench(suite, experiment, {
|
||||||
|
mode: 'static',
|
||||||
|
minTries: 100,
|
||||||
|
maxTries: 200,
|
||||||
|
minTime: 100,
|
||||||
|
})
|
||||||
|
|
||||||
|
bench.run(() => {
|
||||||
|
actual.index++
|
||||||
|
})
|
||||||
|
}
|
10
packages/slate-dev-benchmark/test/utils/sleep.js
Normal file
10
packages/slate-dev-benchmark/test/utils/sleep.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
function syncSleep(ms) {
|
||||||
|
const start = process.hrtime()
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const end = process.hrtime(start)
|
||||||
|
if (end[0] * 1000 + end[1] / 1e6 > ms) return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { syncSleep }
|
@@ -1,48 +0,0 @@
|
|||||||
/** @jsx h */
|
|
||||||
/* eslint-disable react/jsx-key */
|
|
||||||
|
|
||||||
import Html from '../..'
|
|
||||||
import React from 'react'
|
|
||||||
import { JSDOM } from 'jsdom' // eslint-disable-line import/no-extraneous-dependencies
|
|
||||||
|
|
||||||
const html = new Html({
|
|
||||||
parseHtml: JSDOM.fragment,
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
serialize(obj, children) {
|
|
||||||
switch (obj.object) {
|
|
||||||
case 'block': {
|
|
||||||
switch (obj.type) {
|
|
||||||
case 'paragraph':
|
|
||||||
return React.createElement('p', {}, children)
|
|
||||||
case 'quote':
|
|
||||||
return React.createElement('blockquote', {}, children)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 'mark': {
|
|
||||||
switch (obj.type) {
|
|
||||||
case 'bold':
|
|
||||||
return React.createElement('strong', {}, children)
|
|
||||||
case 'italic':
|
|
||||||
return React.createElement('em', {}, children)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
export default function(string) {
|
|
||||||
html.deserialize(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const input = `
|
|
||||||
<blockquote>
|
|
||||||
<p>
|
|
||||||
This is editable <strong>rich</strong> text, <em>much</em> better than a textarea!
|
|
||||||
</p>
|
|
||||||
</blockquote>
|
|
||||||
`
|
|
||||||
.trim()
|
|
||||||
.repeat(10)
|
|
@@ -1,46 +0,0 @@
|
|||||||
/* global suite, set, bench */
|
|
||||||
|
|
||||||
import fs from 'fs'
|
|
||||||
import { basename, extname, resolve } from 'path'
|
|
||||||
import { resetMemoization } from 'slate'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Benchmarks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const categoryDir = resolve(__dirname)
|
|
||||||
const categories = fs
|
|
||||||
.readdirSync(categoryDir)
|
|
||||||
.filter(c => c[0] != '.' && c != 'index.js')
|
|
||||||
|
|
||||||
categories.forEach(category => {
|
|
||||||
suite(category, () => {
|
|
||||||
set('iterations', 50)
|
|
||||||
set('mintime', 1000)
|
|
||||||
|
|
||||||
if (category == 'models') {
|
|
||||||
after(() => {
|
|
||||||
resetMemoization()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const benchmarkDir = resolve(categoryDir, category)
|
|
||||||
const benchmarks = fs
|
|
||||||
.readdirSync(benchmarkDir)
|
|
||||||
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
|
|
||||||
.map(b => basename(b, extname(b)))
|
|
||||||
|
|
||||||
benchmarks.forEach(benchmark => {
|
|
||||||
const dir = resolve(benchmarkDir, benchmark)
|
|
||||||
const module = require(dir)
|
|
||||||
const fn = module.default
|
|
||||||
let { input, before, after } = module
|
|
||||||
if (before) input = before(input)
|
|
||||||
|
|
||||||
bench(benchmark, () => {
|
|
||||||
fn(input)
|
|
||||||
if (after) after()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
@@ -1,46 +0,0 @@
|
|||||||
/* global suite, set, bench */
|
|
||||||
|
|
||||||
import fs from 'fs'
|
|
||||||
import { basename, extname, resolve } from 'path'
|
|
||||||
import { resetMemoization } from 'slate'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Benchmarks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const categoryDir = resolve(__dirname)
|
|
||||||
const categories = fs
|
|
||||||
.readdirSync(categoryDir)
|
|
||||||
.filter(c => c[0] != '.' && c != 'index.js')
|
|
||||||
|
|
||||||
categories.forEach(category => {
|
|
||||||
suite(category, () => {
|
|
||||||
set('iterations', 50)
|
|
||||||
set('mintime', 1000)
|
|
||||||
|
|
||||||
if (category == 'models') {
|
|
||||||
after(() => {
|
|
||||||
resetMemoization()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const benchmarkDir = resolve(categoryDir, category)
|
|
||||||
const benchmarks = fs
|
|
||||||
.readdirSync(benchmarkDir)
|
|
||||||
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
|
|
||||||
.map(b => basename(b, extname(b)))
|
|
||||||
|
|
||||||
benchmarks.forEach(benchmark => {
|
|
||||||
const dir = resolve(benchmarkDir, benchmark)
|
|
||||||
const module = require(dir)
|
|
||||||
const fn = module.default
|
|
||||||
let { input, before, after } = module
|
|
||||||
if (before) input = before(input)
|
|
||||||
|
|
||||||
bench(benchmark, () => {
|
|
||||||
fn(input)
|
|
||||||
if (after) after()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
@@ -1,39 +0,0 @@
|
|||||||
/* global suite, set, bench */
|
|
||||||
|
|
||||||
import fs from 'fs'
|
|
||||||
import { basename, extname, resolve } from 'path'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Benchmarks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const categoryDir = resolve(__dirname)
|
|
||||||
const categories = fs
|
|
||||||
.readdirSync(categoryDir)
|
|
||||||
.filter(c => c[0] != '.' && c != 'index.js')
|
|
||||||
|
|
||||||
categories.forEach(category => {
|
|
||||||
suite(category, () => {
|
|
||||||
set('iterations', 50)
|
|
||||||
set('mintime', 1000)
|
|
||||||
|
|
||||||
const benchmarkDir = resolve(categoryDir, category)
|
|
||||||
const benchmarks = fs
|
|
||||||
.readdirSync(benchmarkDir)
|
|
||||||
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
|
|
||||||
.map(b => basename(b, extname(b)))
|
|
||||||
|
|
||||||
benchmarks.forEach(benchmark => {
|
|
||||||
const dir = resolve(benchmarkDir, benchmark)
|
|
||||||
const module = require(dir)
|
|
||||||
const fn = module.default
|
|
||||||
let { input, before, after } = module
|
|
||||||
if (before) input = before(input)
|
|
||||||
|
|
||||||
bench(benchmark, () => {
|
|
||||||
fn(input)
|
|
||||||
if (after) after()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
@@ -1,46 +0,0 @@
|
|||||||
/* global suite, set, bench */
|
|
||||||
|
|
||||||
import fs from 'fs'
|
|
||||||
import { basename, extname, resolve } from 'path'
|
|
||||||
import { resetMemoization } from '..'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Benchmarks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const categoryDir = resolve(__dirname)
|
|
||||||
const categories = fs
|
|
||||||
.readdirSync(categoryDir)
|
|
||||||
.filter(c => c[0] != '.' && c != 'index.js')
|
|
||||||
|
|
||||||
categories.forEach(category => {
|
|
||||||
suite(category, () => {
|
|
||||||
set('iterations', 100)
|
|
||||||
set('mintime', 1000)
|
|
||||||
|
|
||||||
if (category == 'models') {
|
|
||||||
after(() => {
|
|
||||||
resetMemoization()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const benchmarkDir = resolve(categoryDir, category)
|
|
||||||
const benchmarks = fs
|
|
||||||
.readdirSync(benchmarkDir)
|
|
||||||
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
|
|
||||||
.map(b => basename(b, extname(b)))
|
|
||||||
|
|
||||||
benchmarks.forEach(benchmark => {
|
|
||||||
const dir = resolve(benchmarkDir, benchmark)
|
|
||||||
const module = require(dir)
|
|
||||||
const fn = module.default
|
|
||||||
let { input, before, after } = module
|
|
||||||
if (before) input = before(input)
|
|
||||||
|
|
||||||
bench(benchmark, () => {
|
|
||||||
fn(input)
|
|
||||||
if (after) after()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
@@ -1,14 +1,24 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
|
import figures from 'figures'
|
||||||
|
import emojis from 'emojis'
|
||||||
import baseline from '../../tmp/benchmark-baseline'
|
import baseline from '../../tmp/benchmark-baseline'
|
||||||
import comparison from '../../tmp/benchmark-comparison'
|
import comparison from '../../tmp/benchmark-comparison'
|
||||||
|
import { existsSync } from 'fs'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants.
|
* Constants.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const THRESHOLD = 0.333
|
let THRESHOLD = 0.333
|
||||||
|
const configPath = '../../tmp/benchmark-config.js'
|
||||||
|
if (existsSync(configPath)) {
|
||||||
|
const alternative = require(configPath).THRESHOLD
|
||||||
|
if (typeof alternative === 'number' && alternative > 0) {
|
||||||
|
THRESHOLD = alternative
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print.
|
* Print.
|
||||||
@@ -21,27 +31,72 @@ baseline.forEach((suite, i) => {
|
|||||||
console.log(` ${suite.name}`)
|
console.log(` ${suite.name}`)
|
||||||
|
|
||||||
suite.benchmarks.forEach((base, j) => {
|
suite.benchmarks.forEach((base, j) => {
|
||||||
const comp = comparison[i].benchmarks[j]
|
const compared = { user: {}, hr: {} }
|
||||||
if (!comp) return
|
|
||||||
|
|
||||||
const b = base.iterations / base.elapsed * 1000
|
for (const key of Object.keys(compared)) {
|
||||||
const c = comp.iterations / comp.elapsed * 1000
|
const comp = comparison[i].benchmarks[j]
|
||||||
const threshold = b * THRESHOLD
|
if (!comp) return
|
||||||
const slower = b - c > threshold
|
const b = base.iterations / base[key] * 1000
|
||||||
const faster = b - c < 0 - threshold
|
const c = comp.iterations / comp[key] * 1000
|
||||||
const percent = Math.round(Math.abs(b - c) / b * 100)
|
const balancePercent =
|
||||||
|
b > c ? Math.round(Math.abs(b - c) / c * 100) : (c - b) / b * 100
|
||||||
|
|
||||||
let output = `${b.toFixed(2)} → ${c.toFixed(2)} ops/sec`
|
const output = `${b.toFixed(2)} -> ${c.toFixed(2)} ops/sec`
|
||||||
if (slower) output = chalk.red(`${output} (${percent}% slower)`)
|
compared[key].baseOutput = output
|
||||||
else if (faster) output = chalk.green(`${output} (${percent}% faster)`)
|
compared[key].percentOutput = `${balancePercent.toFixed(2)}% ${
|
||||||
else output = chalk.gray(output)
|
c > b ? 'faster' : 'slower'
|
||||||
|
}`
|
||||||
|
compared[key].percentValue = balancePercent
|
||||||
|
compared[key].b = b
|
||||||
|
compared[key].c = c
|
||||||
|
compared[key].isFaster = c > b
|
||||||
|
if (balancePercent > 1000) {
|
||||||
|
compared[key].percentOutput += emojis.unicode(' :scream: ')
|
||||||
|
} else if (balancePercent > 100) {
|
||||||
|
if (c > b) {
|
||||||
|
compared[key].percentOutput += emojis.unicode(' :raised_hands: ')
|
||||||
|
} else {
|
||||||
|
compared[key].percentOutput += emojis.unicode(' :worried: ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (percent > 1000) output += ' 😱'
|
const { user, hr } = compared
|
||||||
else if (faster && percent > 100) output += ' 🙌'
|
|
||||||
else if (slower && percent > 100) output += ' 😟'
|
|
||||||
|
|
||||||
console.log(` ${base.title}`)
|
if (
|
||||||
console.log(` ${output}`)
|
user.percentValue < THRESHOLD * 100 &&
|
||||||
|
hr.percentValue < THRESHOLD * 100
|
||||||
|
) {
|
||||||
|
console.log(
|
||||||
|
chalk.grey(
|
||||||
|
` ${figures.tick} ${base.name}: ${user.baseOutput} (${
|
||||||
|
user.percentOutput
|
||||||
|
})`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.isFaster === hr.isFaster) {
|
||||||
|
if (user.isFaster) {
|
||||||
|
console.log(chalk.green(` ${figures.star} ${base.name}:`))
|
||||||
|
console.log(
|
||||||
|
` user: ${user.baseOutput} (${user.percentOutput})`
|
||||||
|
)
|
||||||
|
console.log(` real: ${hr.baseOutput} (${hr.percentOutput})`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log(chalk.red(` ${figures.cross} ${base.name}:`))
|
||||||
|
console.log(
|
||||||
|
` user: ${user.baseOutput} (${user.percentOutput})`
|
||||||
|
)
|
||||||
|
console.log(` real: ${hr.baseOutput} (${hr.percentOutput})`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.red(` ${figures.questionMarkPrefix} ${base.name}:`))
|
||||||
|
console.log(` user: ${user.baseOutput} (${user.percentOutput})`)
|
||||||
|
console.log(` real: ${hr.baseOutput} (${hr.percentOutput})`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -1,31 +0,0 @@
|
|||||||
const { stdout } = process
|
|
||||||
|
|
||||||
module.exports = function(runner, utils) {
|
|
||||||
let hasSuite = false
|
|
||||||
let hasBench = false
|
|
||||||
|
|
||||||
runner.on('start', () => {
|
|
||||||
stdout.write('[')
|
|
||||||
})
|
|
||||||
|
|
||||||
runner.on('end', () => {
|
|
||||||
stdout.write(']')
|
|
||||||
})
|
|
||||||
|
|
||||||
runner.on('suite start', suite => {
|
|
||||||
if (hasSuite) stdout.write(',')
|
|
||||||
stdout.write(`{"name":"${suite.title}","benchmarks":[`)
|
|
||||||
hasSuite = true
|
|
||||||
})
|
|
||||||
|
|
||||||
runner.on('suite end', suite => {
|
|
||||||
hasBench = false
|
|
||||||
stdout.write(']}')
|
|
||||||
})
|
|
||||||
|
|
||||||
runner.on('bench end', bench => {
|
|
||||||
if (hasBench) stdout.write(',')
|
|
||||||
stdout.write(JSON.stringify(bench))
|
|
||||||
hasBench = true
|
|
||||||
})
|
|
||||||
}
|
|
@@ -11,6 +11,7 @@ import slatePropTypes from '../../packages/slate-prop-types/package.json'
|
|||||||
import slateReact from '../../packages/slate-react/package.json'
|
import slateReact from '../../packages/slate-react/package.json'
|
||||||
import slateSchemaViolations from '../../packages/slate-schema-violations/package.json'
|
import slateSchemaViolations from '../../packages/slate-schema-violations/package.json'
|
||||||
import slateSimulator from '../../packages/slate-simulator/package.json'
|
import slateSimulator from '../../packages/slate-simulator/package.json'
|
||||||
|
// Do not import slateDevBenchmark here. The benchmark shall be a pure nodeJS program and can be run without babel-node
|
||||||
|
|
||||||
const configurations = [
|
const configurations = [
|
||||||
...factory(slate),
|
...factory(slate),
|
||||||
|
@@ -1926,6 +1926,10 @@ commander@2.9.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
graceful-readlink ">= 1.0.0"
|
graceful-readlink ">= 1.0.0"
|
||||||
|
|
||||||
|
commander@^2.15.1:
|
||||||
|
version "2.16.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50"
|
||||||
|
|
||||||
commander@~2.13.0:
|
commander@~2.13.0:
|
||||||
version "2.13.0"
|
version "2.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
|
||||||
@@ -2796,6 +2800,10 @@ emojis-list@^2.0.0:
|
|||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
|
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
|
||||||
|
|
||||||
|
emojis@^1.0.10:
|
||||||
|
version "1.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/emojis/-/emojis-1.0.10.tgz#2558133df0dff13313c99531647f693d7adb57da"
|
||||||
|
|
||||||
emotion@^9.2.4:
|
emotion@^9.2.4:
|
||||||
version "9.2.4"
|
version "9.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/emotion/-/emotion-9.2.4.tgz#0139e7cc154b2845f4b9afaa996dd4de13bb90e3"
|
resolved "https://registry.yarnpkg.com/emotion/-/emotion-9.2.4.tgz#0139e7cc154b2845f4b9afaa996dd4de13bb90e3"
|
||||||
|
Reference in New Issue
Block a user