playground 2
This commit is contained in:
parent
474e6ae7ca
commit
1ed5b49aee
4 changed files with 176 additions and 15 deletions
|
@ -55,7 +55,7 @@ function IfTreeBranch(branches, indent = 0) {
|
||||||
|
|
||||||
for (let i = 0; i < branches.length; i++) {
|
for (let i = 0; i < branches.length; i++) {
|
||||||
let branch = branches[i]
|
let branch = branches[i]
|
||||||
output += `${i > 0 ? 'else ': ''}if (str.charCodeAt(${indent}) === ${branch.char.charCodeAt(0)}) {`
|
output += `${i > 0 ? 'else ': ''}if (str.charCodeAt(${indent}) === ${branch.char.charCodeAt(0)}) { // ${branch.char}`
|
||||||
|
|
||||||
if (branch.path) {
|
if (branch.path) {
|
||||||
output += '\n' + indentation + ` if (str.length === ${branch.path.length}) {`
|
output += '\n' + indentation + ` if (str.length === ${branch.path.length}) {`
|
||||||
|
@ -78,5 +78,39 @@ function IfTreeBranch(branches, indent = 0) {
|
||||||
export function compileTreeIntoIfs(tree) {
|
export function compileTreeIntoIfs(tree) {
|
||||||
let output = IfTreeBranch(tree)
|
let output = IfTreeBranch(tree)
|
||||||
output += '\nreturn null'
|
output += '\nreturn null'
|
||||||
return new Function(output)
|
return new Function('str', output)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function IfTreeBranchBuffer(branches, indent = 0) {
|
||||||
|
let output = ''
|
||||||
|
let indentation = ''.padStart(indent * 2)
|
||||||
|
|
||||||
|
for (let i = 0; i < branches.length; i++) {
|
||||||
|
let branch = branches[i]
|
||||||
|
output += `${i > 0 ? 'else ': ''}if (uint[${indent}] === ${branch.char.charCodeAt(0)}) { // ${branch.char}`
|
||||||
|
|
||||||
|
if (branch.path) {
|
||||||
|
output += '\n' + indentation + ` if (uint.length === ${branch.path.length}) {`
|
||||||
|
output += '\n' + indentation + ` return "${branch.path}"`
|
||||||
|
output += '\n' + indentation + ` }`
|
||||||
|
}
|
||||||
|
if (branch.children.length) {
|
||||||
|
if (branch.path) {
|
||||||
|
output += ' else '
|
||||||
|
} else {
|
||||||
|
output += '\n' + indentation + ' '
|
||||||
|
}
|
||||||
|
output += IfTreeBranchBuffer(branch.children, indent + 1)
|
||||||
|
}
|
||||||
|
output += '\n' + indentation + '} '
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
export function compileTreeIntoIfsWithBuffer(tree) {
|
||||||
|
let output = `var uint = Buffer.from(str)\n`
|
||||||
|
output += IfTreeBranchBuffer(tree)
|
||||||
|
output += '\nreturn null'
|
||||||
|
return new Function('str', output)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,3 +6,28 @@ export function printTree(children, indent = 0) {
|
||||||
printTree(child.children, indent + 1)
|
printTree(child.children, indent + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function printCurrentStatus(fn) {
|
||||||
|
let opt = %GetOptimizationStatus(fn)
|
||||||
|
console.log(`${opt.toString(2).padStart(17, '0').split('').join(' ')}`)
|
||||||
|
}
|
||||||
|
export function printStatusHelperText() {
|
||||||
|
console.log(`┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬
|
||||||
|
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─╸ is function
|
||||||
|
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └───╸ is never optimized
|
||||||
|
│ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────╸ is always optimized
|
||||||
|
│ │ │ │ │ │ │ │ │ │ │ │ │ └───────╸ is maybe deoptimized
|
||||||
|
│ │ │ │ │ │ │ │ │ │ │ │ └─────────╸ is optimized
|
||||||
|
│ │ │ │ │ │ │ │ │ │ │ └───────────╸ is optimized by TurboFan
|
||||||
|
│ │ │ │ │ │ │ │ │ │ └─────────────╸ is interpreted
|
||||||
|
│ │ │ │ │ │ │ │ │ └───────────────╸ is marked for optimization
|
||||||
|
│ │ │ │ │ │ │ │ └─────────────────╸ is marked for concurrent optimization
|
||||||
|
│ │ │ │ │ │ │ └───────────────────╸ is optimizing concurrently
|
||||||
|
│ │ │ │ │ │ └─────────────────────╸ is executing
|
||||||
|
│ │ │ │ │ └───────────────────────╸ topmost frame is turbo fanned
|
||||||
|
│ │ │ │ └─────────────────────────╸ lite mode
|
||||||
|
│ │ │ └───────────────────────────╸ marked for deoptimization
|
||||||
|
│ │ └─────────────────────────────╸ baseline
|
||||||
|
│ └───────────────────────────────╸ topmost frame is interpreted
|
||||||
|
└─────────────────────────────────╸ topmost frame is baseline`)
|
||||||
|
}
|
|
@ -1,19 +1,121 @@
|
||||||
import { buildTree, compileTreeIntoIfs } from "./compiler/compiler.mjs"
|
import { buildTree, compileTreeIntoIfs, compileTreeIntoIfsWithBuffer } from "./compiler/compiler.mjs"
|
||||||
|
import { summary, run, bench } from 'mitata';
|
||||||
|
import { printCurrentStatus, printStatusHelperText } from "./compiler/utils.mjs";
|
||||||
|
import { FlaskaRouter } from "../flaska.mjs";
|
||||||
|
|
||||||
|
// Warmup (de-optimize `bench()` calls)
|
||||||
|
bench('noop', () => { });
|
||||||
|
bench('noop2', () => { });
|
||||||
|
|
||||||
let paths = [
|
let paths = [
|
||||||
'test1',
|
'/fsdafasfa',
|
||||||
'test',
|
'/ymreklhmse',
|
||||||
'test3',
|
'/h34nmlaeknmgl',
|
||||||
'test5',
|
'/asdgsdagas',
|
||||||
'something',
|
'/ahaewhweaaa',
|
||||||
'sometimes',
|
'/adshashaea',
|
||||||
'else',
|
'/sdafasfsadfasdfas',
|
||||||
'goes',
|
//'/gdfsfgsfdsgsdrgsregsergsregersgserersgsergersg',
|
||||||
'here',
|
//'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
'too',
|
|
||||||
]
|
]
|
||||||
|
let pathsBla = [
|
||||||
|
'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
|
'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
|
'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
|
'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
|
'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
|
'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
|
'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
|
'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
|
'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
|
'/test5afdlkasdflksad flsakdf lsakf asdlkfa lsdkfasdlkdfalklk',
|
||||||
|
]
|
||||||
|
let pathsBuffer = paths.map(x => new Uint8Array(Buffer.from(x)))
|
||||||
|
|
||||||
let tree = buildTree(paths)
|
let tree = buildTree(paths)
|
||||||
|
let noop = function() { }
|
||||||
|
|
||||||
const ifTree = compileTreeIntoIfs(tree)
|
const ifTree = compileTreeIntoIfs(tree)
|
||||||
console.log(ifTree.toString())
|
// console.log(ifTree.toString())
|
||||||
|
const ifTreeBuffer = compileTreeIntoIfsWithBuffer(tree)
|
||||||
|
// console.log(ifTreeBuffer.toString())
|
||||||
|
const flaskaRouter = new FlaskaRouter()
|
||||||
|
for (let path of paths) {
|
||||||
|
flaskaRouter.addRoute(path, noop)
|
||||||
|
}
|
||||||
|
|
||||||
|
const m = new Map(paths.map(x => [x, x]))
|
||||||
|
function mapFlat(str) {
|
||||||
|
return m.get(str) ?? null
|
||||||
|
}
|
||||||
|
|
||||||
|
function toBuffer(str) {
|
||||||
|
return Buffer.from(str)
|
||||||
|
}
|
||||||
|
function toUint(str) {
|
||||||
|
return new Uint8Array(Buffer.from(str))
|
||||||
|
}
|
||||||
|
function toManualArray(str) {
|
||||||
|
let length = str.length
|
||||||
|
let out = new Array(length)
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
out[i] = str.charCodeAt(i)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
function allocBufferUnsafe(str) {
|
||||||
|
return Buffer.allocUnsafe(str.length)
|
||||||
|
}
|
||||||
|
function allocBufferSafe(str) {
|
||||||
|
return Buffer.alloc(str.length)
|
||||||
|
}
|
||||||
|
function allocUint8(str) {
|
||||||
|
return new Uint8Array(str.length)
|
||||||
|
}
|
||||||
|
function toManualArraySplitMap(str) {
|
||||||
|
return str.split('').map(x => x.charCodeAt(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
let func1 = [mapFlat, toBuffer, toUint, toManualArray, toManualArraySplitMap, allocBufferUnsafe, allocBufferSafe, allocUint8, ifTree];
|
||||||
|
for (var i = 0; i < 100000; i++) {
|
||||||
|
for (let fun of func1) {
|
||||||
|
paths.map(fun)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < 100000; i++) {
|
||||||
|
for (let path of paths) {
|
||||||
|
flaskaRouter.match(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let fun of func1) {
|
||||||
|
printCurrentStatus(fun);
|
||||||
|
}
|
||||||
|
printCurrentStatus(flaskaRouter.match)
|
||||||
|
printStatusHelperText()
|
||||||
|
|
||||||
|
summary(() => {
|
||||||
|
bench('if tree', function() {
|
||||||
|
return paths.map(ifTree)
|
||||||
|
})
|
||||||
|
bench('if tree buffer edition', function() {
|
||||||
|
return paths.map(ifTreeBuffer)
|
||||||
|
});
|
||||||
|
bench('flaskarouter', function() {
|
||||||
|
return paths.map(flaskaRouter.match.bind(flaskaRouter))
|
||||||
|
});
|
||||||
|
/*bench('map edition', function() {
|
||||||
|
return paths.map(mapFlat)
|
||||||
|
});
|
||||||
|
bench('if tree pre buffer edition', function() {
|
||||||
|
return pathsBuffer.map(ifTreeBuffer)
|
||||||
|
});
|
||||||
|
bench('toBuffer', () => pathsBla.map(toBuffer));
|
||||||
|
bench('toUint', () => pathsBla.map(toUint));
|
||||||
|
bench('toManualArraySplitMap', () => pathsBla.map(toManualArraySplitMap))
|
||||||
|
bench('toManualArray', () => pathsBla.map(toManualArray))*/
|
||||||
|
bench('allocBufferUnsafe', () => pathsBla.map(allocBufferUnsafe))
|
||||||
|
bench('allocBufferSafe', () => pathsBla.map(allocBufferSafe))
|
||||||
|
bench('allocUint8', () => pathsBla.map(allocUint8))
|
||||||
|
})
|
||||||
|
|
||||||
|
run();
|
|
@ -431,7 +431,7 @@ export class FlaskaRouter {
|
||||||
let isFullParam = false
|
let isFullParam = false
|
||||||
let branch = this.root
|
let branch = this.root
|
||||||
|
|
||||||
if (route.indexOf(':') < 0) {
|
if (route.indexOf(':') < 0 && false) {
|
||||||
let name = route
|
let name = route
|
||||||
if (name.length > 1 && name[name.length - 1] === '/') {
|
if (name.length > 1 && name[name.length - 1] === '/') {
|
||||||
name = name.slice(0, -1)
|
name = name.slice(0, -1)
|
||||||
|
|
Loading…
Reference in a new issue