playground 2

This commit is contained in:
Jonatan Nilsson 2024-10-23 01:07:35 +00:00
parent 474e6ae7ca
commit 1ed5b49aee
4 changed files with 176 additions and 15 deletions

View file

@ -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)
} }

View file

@ -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`)
}

View file

@ -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();

View file

@ -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)