diff --git a/packages/slate-html-serializer/benchmark/html-serializer/deserialize.js b/packages/slate-html-serializer/benchmark/html-serializer/deserialize.js
new file mode 100644
index 000000000..094a77c4b
--- /dev/null
+++ b/packages/slate-html-serializer/benchmark/html-serializer/deserialize.js
@@ -0,0 +1,42 @@
+/** @jsx h */
+/* eslint-disable react/jsx-key */
+
+import Html from '../..'
+import React from 'react'
+import parse5 from 'parse5' // eslint-disable-line import/no-extraneous-dependencies
+
+const html = new Html({
+ parseHtml: parse5.parseFragment,
+ rules: [
+ {
+ serialize(obj, children) {
+ switch (obj.kind) {
+ 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 = `
+
+
+ This is editable rich text, much better than a textarea!
+
+
+`.trim().repeat(10)
diff --git a/packages/slate-html-serializer/benchmark/html-serializer/serialize.js b/packages/slate-html-serializer/benchmark/html-serializer/serialize.js
new file mode 100644
index 000000000..20d9bc66b
--- /dev/null
+++ b/packages/slate-html-serializer/benchmark/html-serializer/serialize.js
@@ -0,0 +1,49 @@
+/** @jsx h */
+/* eslint-disable react/jsx-key */
+
+import Html from '../..'
+import React from 'react'
+import h from '../../test/helpers/h'
+import parse5 from 'parse5' // eslint-disable-line import/no-extraneous-dependencies
+
+const html = new Html({
+ parseHtml: parse5.parseFragment,
+ rules: [
+ {
+ serialize(obj, children) {
+ switch (obj.kind) {
+ 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 (state) {
+ html.serialize(state)
+}
+
+export const input = (
+
+
+ {Array.from(Array(10)).map(() => (
+
+
+ This is editable rich text, much better than a textarea!
+
+
+ ))}
+
+
+)
diff --git a/packages/slate-html-serializer/benchmark/index.js b/packages/slate-html-serializer/benchmark/index.js
new file mode 100644
index 000000000..521d7c484
--- /dev/null
+++ b/packages/slate-html-serializer/benchmark/index.js
@@ -0,0 +1,41 @@
+/* global suite, set, bench */
+
+import fs from 'fs'
+import { basename, extname, resolve } from 'path'
+import { __clear } from '../../slate/lib/utils/memoize'
+
+/**
+ * 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', 2000)
+
+ if (category == 'models') {
+ after(() => {
+ __clear()
+ })
+ }
+
+ 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()
+ })
+ })
+ })
+})
diff --git a/packages/slate-plain-serializer/benchmark/index.js b/packages/slate-plain-serializer/benchmark/index.js
new file mode 100644
index 000000000..521d7c484
--- /dev/null
+++ b/packages/slate-plain-serializer/benchmark/index.js
@@ -0,0 +1,41 @@
+/* global suite, set, bench */
+
+import fs from 'fs'
+import { basename, extname, resolve } from 'path'
+import { __clear } from '../../slate/lib/utils/memoize'
+
+/**
+ * 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', 2000)
+
+ if (category == 'models') {
+ after(() => {
+ __clear()
+ })
+ }
+
+ 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()
+ })
+ })
+ })
+})
diff --git a/packages/slate-plain-serializer/benchmark/plain-serializer/deserialize.js b/packages/slate-plain-serializer/benchmark/plain-serializer/deserialize.js
new file mode 100644
index 000000000..956aaaf69
--- /dev/null
+++ b/packages/slate-plain-serializer/benchmark/plain-serializer/deserialize.js
@@ -0,0 +1,12 @@
+/** @jsx h */
+/* eslint-disable react/jsx-key */
+
+import Plain from '../..'
+
+export default function (string) {
+ Plain.deserialize(string)
+}
+
+export const input = `
+ This is editable plain text, just like a text area.
+`.trim().repeat(10)
diff --git a/packages/slate-plain-serializer/benchmark/plain-serializer/serialize.js b/packages/slate-plain-serializer/benchmark/plain-serializer/serialize.js
new file mode 100644
index 000000000..aa39d8e99
--- /dev/null
+++ b/packages/slate-plain-serializer/benchmark/plain-serializer/serialize.js
@@ -0,0 +1,25 @@
+/** @jsx h */
+/* eslint-disable react/jsx-key */
+
+import Plain from '../..'
+import h from '../../test/helpers/h'
+
+export default function (state) {
+ Plain.serialize(state)
+}
+
+export const input = (
+
+
+ {Array.from(Array(10)).map(() => (
+
+
+
+ This is editable rich text, much better than a textarea!
+
+
+
+ ))}
+
+
+)