Last active
June 28, 2023 13:32
-
-
Save mizchi/25619126dac28223998e5dbc6603f05c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
# Benchmark for typescript compiler API - parse/print/transform | |
CAUTION: JIT is not taken into account | |
I use https://github.com/mizchi/svelte2tsx-component/blob/main/src/core.mts | |
--- | |
code-size 43377chars 5336nodes | |
Run 100 times | |
(createSourceFile) | |
parse: 193.245ms | |
(visit all nodes) | |
full-traverse: 17.935ms | |
(noop transformer) | |
noop-transformer: 30.529ms | |
(visit many identifiers 2221/5336 41%) | |
full-transformer: 122.425ms | |
(printer.printFile(sourceFile)) | |
print-file: 199.499ms | |
(ts-clone-node) | |
clone-node: 1.049s | |
Conclusion: | |
1 parse ≒ 1.2 printFile | |
1 * parse ≒ 10 * full-traverse | |
1 * parse ≒ 0.33 * (transformed-nodes/all-nodes) | |
1 * full-traverse ≒ 0.5 * one-transform | |
1 * clone-node ≒ 6 * parse | |
*/ | |
// npx tsm bench.ts | |
import ts from "typescript"; | |
// @ts-ignore | |
import fs from "node:fs"; | |
import { cloneNode } from "ts-clone-node"; | |
const __dirname = new URL(".", import.meta.url).pathname; | |
const code = fs.readFileSync(__dirname + "/src/core.mts", "utf8"); | |
const sourceFile = ts.createSourceFile("test.ts", code, ts.ScriptTarget.ESNext); | |
let nodeCount = 0; | |
const visit = (node: ts.Node) => { | |
nodeCount++; | |
ts.forEachChild(node, visit); | |
}; | |
visit(sourceFile); | |
console.log("code-size", code.length + "chars", nodeCount + "nodes"); | |
console.time("parse"); | |
for (let i = 0; i < 100; i++) { | |
ts.createSourceFile("test.ts", code, ts.ScriptTarget.ESNext); | |
} | |
console.timeEnd("parse"); | |
// create once | |
console.time("full-traverse"); | |
for (let i = 0; i < 100; i++) { | |
const visit = (node: ts.Node) => { | |
ts.forEachChild(node, visit); | |
}; | |
ts.forEachChild(sourceFile, visit); | |
} | |
console.timeEnd("full-traverse"); | |
// no transforme | |
const transformer: ts.TransformerFactory<any> = (context: ts.TransformationContext) => (root) => { | |
const visit = (node: ts.Node): ts.Node => { | |
return ts.visitEachChild(node, visit, context); | |
}; | |
return ts.visitNode(root, visit); | |
}; | |
console.time("noop-transformer"); | |
for (let i = 0; i < 100; i++) { | |
ts.transform(sourceFile, [transformer]); | |
} | |
console.timeEnd("noop-transformer"); | |
// let mutableNodeCount = 0; | |
const transformer2: ts.TransformerFactory<any> = (context: ts.TransformationContext) => (root) => { | |
const visit = (node: ts.Node): ts.Node => { | |
if (ts.isIdentifier(node)) { | |
// mutableNodeCount++; | |
// const random = Math.random().toString(36).substring(7); | |
const newName = node.text + "_new"; | |
return context.factory.createIdentifier(newName); | |
} | |
return ts.visitEachChild(node, visit, context); | |
}; | |
return ts.visitNode(root, visit); | |
}; | |
// ts.transform(sourceFile, [transformer2]); | |
// console.log("transformed-node-count", mutableNodeCount); | |
// let mutableNodeCount = 0; | |
const transformer3: ts.TransformerFactory<any> = (context: ts.TransformationContext) => (root) => { | |
const visit = (node: ts.Node): ts.Node => { | |
if (ts.isIdentifier(node) && node.text === "isLastNode") { | |
return context.factory.createIdentifier("xxx"); | |
} | |
return ts.visitEachChild(node, visit, context); | |
}; | |
return ts.visitNode(root, visit); | |
}; | |
// ts.transform(sourceFile, [transformer2]); | |
// console.log("transformed-node-count", mutableNodeCount); | |
console.time("full-transformer"); | |
for (let i = 0; i < 100; i++) { | |
ts.transform(sourceFile, [transformer2]); | |
} | |
console.timeEnd("full-transformer"); | |
console.time("one-transformer"); | |
for (let i = 0; i < 100; i++) { | |
ts.transform(sourceFile, [transformer3]); | |
} | |
console.timeEnd("one-transformer"); | |
const printer = ts.createPrinter(); | |
console.time("print-file"); | |
for (let i = 0; i < 100; i++) { | |
printer.printFile(sourceFile); | |
} | |
console.timeEnd("print-file"); | |
console.time("clone-node"); | |
for (let i = 0; i < 100; i++) { | |
cloneNode(sourceFile); | |
} | |
console.timeEnd("clone-node"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment