Can Golang‑Compiled TypeScript Outrun Node, Bun, and Deno? Benchmark Results Revealed
This article examines Microsoft’s new Golang‑based TypeScript compiler by benchmarking recursive Fibonacci, merge sort, and matrix multiplication across Golang, Node.js, Bun, and Deno, revealing that while Golang remains faster, Bun narrows the gap, and the promised ten‑fold speedup is not universally achieved.
TypeScript has long aimed to improve developer experience, but as projects grow, compilation time, editor responsiveness, and build speed become challenges. Microsoft announced that the TypeScript compiler and tools are being natively ported to Golang, promising a ten‑fold compilation speed increase and better memory efficiency.
Benchmark Setup
To compare performance, a simple benchmark suite was created that evaluates three CPU‑intensive tasks:
Fibonacci (recursive) – quick test of CPU performance.
Merge sort – sorting benchmark to measure algorithm efficiency.
Matrix multiplication – parallelizable task that benefits from concurrent execution.
The benchmarks were run in the following environments:
Golang (direct compile and execute)
Node.js (using --experimental-strip-types to support native TypeScript)
Bun (claimed to be the fastest JavaScript runtime)
Deno (Rust‑based, optimized for TypeScript)
Golang Example Code
<code>package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func fibonacci(n int) int {
if n <= 1 {
return n
}
return fibonacci(n-1) + fibonacci(n-2)
}
func mergeSort(arr []int) []int {
if len(arr) <= 1 {
return arr
}
mid := len(arr) / 2
left := mergeSort(arr[:mid])
right := mergeSort(arr[mid:])
return merge(left, right)
}
func merge(left, right []int) []int {
result := []int{}
i, j := 0, 0
for i < len(left) && j < len(right) {
if left[i] < right[j] {
result = append(result, left[i])
i++
} else {
result = append(result, right[j])
j++
}
}
result = append(result, left[i:]...)
result = append(result, right[j:]...)
return result
}
func multiplyMatrices(A, B [][]float64, result [][]float64, wg *sync.WaitGroup, start, end int) {
defer wg.Done()
for i := start; i < end; i++ {
for j := 0; j < len(B[0]); j++ {
for k := 0; k < len(A[0]); k++ {
result[i][j] += A[i][k] * B[k][j]
}
}
}
}
func parallelMultiplyMatrices(A, B [][]float64) [][]float64 {
size := len(A)
result := make([][]float64, size)
for i := range result {
result[i] = make([]float64, size)
}
var wg sync.WaitGroup
workers := 4
chunkSize := size / workers
for i := 0; i < workers; i++ {
start := i * chunkSize
end := (i + 1) * chunkSize
if i == workers-1 {
end = size
}
wg.Add(1)
go multiplyMatrices(A, B, result, &wg, start, end)
}
wg.Wait()
return result
}
func benchmark() {
fmt.Println("Starting benchmarks...")
fibNum := 45
startFib := time.Now()
fmt.Println("Fibonacci(", fibNum, "):", fibonacci(fibNum))
fmt.Println("Fibonacci Execution Time:", time.Since(startFib))
arraySize := 5000000
arr := make([]int, arraySize)
for i := range arr {
arr[i] = rand.Intn(1000000)
}
startSort := time.Now()
mergeSort(arr)
fmt.Println("Merge Sort Execution Time:", time.Since(startSort))
matrixSize := 1000
A := make([][]float64, matrixSize)
B := make([][]float64, matrixSize)
for i := range A {
A[i] = make([]float64, matrixSize)
B[i] = make([]float64, matrixSize)
for j := range A[i] {
A[i][j] = rand.Float64() * 10
B[i][j] = rand.Float64() * 10
}
}
startMatrix := time.Now()
parallelMultiplyMatrices(A, B)
fmt.Println("Matrix Multiplication Execution Time:", time.Since(startMatrix))
}
func main() {
benchmark()
}
</code>TypeScript Example Code
<code>import { Worker } from "node:worker_threads";
function fibonacci(n: number): number {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
function mergeSort(arr: number[]): number[] {
if (arr.length <= 1) return arr;
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, right);
}
function merge(left: number[], right: number[]): number[] {
const result: number[] = [];
let i = 0, j = 0;
while (i < left.length && j < right.length) {
result.push(left[i] < right[j] ? left[i++] : right[j++]);
}
return [...result, ...left.slice(i), ...right.slice(j)];
}
async function parallelMultiplyMatrices(A: number[][], B: number[][]): Promise<number[][]> {
const size = A.length;
const result = Array.from({ length: size }, () => Array(size).fill(0));
const numWorkers = 4;
const chunkSize = Math.ceil(size / numWorkers);
const workers: Worker[] = [];
for (let i = 0; i < numWorkers; i++) {
const worker = new Worker("./matrixWorker.js");
workers.push(worker);
}
await Promise.all(
workers.map((worker, i) => new Promise<void>((resolve) => {
const start = i * chunkSize;
const end = Math.min((i + 1) * chunkSize, size);
worker.postMessage({ A, B, start, end });
worker.on("message", (data) => {
const { result: partialResult, start, end } = data;
for (let i = start; i < end; i++) {
result[i] = partialResult[i];
}
worker.terminate();
resolve();
});
}))
);
return result;
}
function measureExecutionTime(label: string, fn: () => void) {
console.time(label);
fn();
console.timeEnd(label);
}
async function benchmark() {
console.log("Starting benchmarks...");
measureExecutionTime("Fibonacci Execution Time", () => {
console.log(`Fibonacci(45):`, fibonacci(45));
});
measureExecutionTime("Merge Sort Execution Time", () => {
const arraySize = 5000000;
const arr = Array.from({ length: arraySize }, () => Math.floor(Math.random() * 1_000_000));
mergeSort(arr);
});
const matrixSize = 1000;
const A = Array.from({ length: matrixSize }, () => Array.from({ length: matrixSize }, () => Math.random() * 10));
const B = Array.from({ length: matrixSize }, () => Array.from({ length: matrixSize }, () => Math.random() * 10));
console.time("Matrix Multiplication Execution Time");
await parallelMultiplyMatrices(A, B);
console.timeEnd("Matrix Multiplication Execution Time");
}
benchmark();
</code>matrixWorker.js Example Code
<code>import { parentPort } from "node:worker_threads";
parentPort.on("message", (data) => {
const { A, B, start, end } = data;
const size = A.length;
const result = Array.from({ length: size }, () => Array(size).fill(0));
for (let i = start; i < end; i++) {
for (let j = 0; j < size; j++) {
for (let k = 0; k < size; k++) {
result[i][j] += A[i][k] * B[k][j];
}
}
}
parentPort.postMessage({ result, start, end });
});
</code>Benchmark Results
Golang Execution Results
Fibonacci execution time: 6.016 seconds
Merge sort execution time: 1.761 seconds
Matrix multiplication execution time: 6.371 seconds
TypeScript Execution Results (Node.js)
Fibonacci execution time: 12.665 seconds
Merge sort execution time: 5.031 seconds
Matrix multiplication execution time: 7.648 seconds
TypeScript Execution Results (Bun)
Fibonacci execution time: 10.33 seconds
Merge sort execution time: 3.91 seconds
Matrix multiplication execution time: 5.51 seconds
TypeScript Execution Results (Deno)
Fibonacci execution time: 12.678 seconds
Merge sort execution time: 5.102 seconds
Matrix multiplication execution time: 9.443 seconds
Observations
Golang is significantly faster overall, but it does not achieve a universal ten‑fold speedup over TypeScript.
Bun delivers the best TypeScript performance, outperforming both Node.js and Deno in all tests.
Matrix multiplication shows the largest variance due to differing parallel execution models.
Conclusion
Although Golang remains faster, it does not consistently deliver the advertised ten‑fold improvement. The benchmarks demonstrate that TypeScript performance heavily depends on the runtime environment. With Bun’s support, the gap shrinks dramatically, making TypeScript a viable option even for CPU‑intensive tasks.
The key insight is that Golang is not a direct competitor to TypeScript but rather a complementary tool. The new TypeScript‑to‑Golang compiler aims to accelerate development, reduce build times, and improve memory efficiency, ultimately contributing to a more efficient JavaScript ecosystem.
Future work will continue to refine these benchmarks and track performance trends across runtimes. JavaScript developers can rest assured that TypeScript is getting faster, and the ecosystem is evolving to meet performance demands.
Code Mala Tang
Read source code together, write articles together, and enjoy spicy hot pot together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.