• Stars
    star
    2,569
  • Rank 17,131 (Top 0.4 %)
  • Language
    C++
  • License
    MIT License
  • Created almost 2 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

High-performance TypeScript compiler

TypeRunner

High-performance TypeScript compiler.

Goals

  • Parser
  • Type checking (as CLI and as library)
  • Language Server
  • Interactive type debugging
  • Type information in other languages
  • (optional) transpiling to JavaScript
  • (optional) RTTI in JavaScript
  • (optional) type profiler

Additionally, making TypeScript type checking as fast as possible and providing a native library for other languages so they can use TypeScript type information without the need for a JavaScript engine enables all sorts of use cases like JSON-Schema replacement, ORM DSL, encoding information (like Protocol Buffers schema) and more.

Non-goals

  • Drop-in replacement for the official TypeScript compiler
  • Runtime

Being a drop-in replacement for the entire official TypeScript compiler (tsc) would require copying design limitations, bugs, and legacy decisions of tsc. Because of TypeScript's 10-year history there are many features that are unnecessary today but kept for compatibility. We focus on a stricter subset of TypeScript, which means TypeRunner won't support some features such as JSDoc and several compiler options.

Status

The source code in the initial version is really only a proof of concept. It consists of roughly 30k LoC and shows very promising results. The approach is to use a TypeScript-to-bytecode compiler and then to run the bytecode in a custom virtual machine. The data show that this approach can lead to a hundred- to several-thousand-fold improvement in speed.

TypeRunner Debugger

Once the project gets funding through the community, development will continue.

Performance

TypeRunner cold means the file was seen for the first time and has to be compiled to bytecode first. TypeRunner warm means the bytecode could be directly executed because it was cached. Usually only a few files change between compilations. For example, if you have a project with 100 files and edit one and rerun type checking, only the changed file has the slower cold timing.

The tsc numbers below are after 10 iterations (the JavaScript engine V8 JIT optimises it early already), which leads to the most conservative comparisons. Running a single iteration is 10x slower, and a cold tsc start is even slower because of the initial bootstrap delay of several hundred milliseconds. Therefore you can safely assume that tsc is slower than what the numbers shown below.

Note that compilation has not yet been optimised (for example, it still uses a slow memory allocator, the optimisation of which can result in another tenfold improvement).

Basic variables

const v1: string = "abc";
const v2: number = 123;
TypeScript tsc:  0.8ms
TypeRunner cold: 0.004688500ms (170x faster)
TypeRunner warm: 0.000079584ms (10,052x faster)

Generic function

function doIt<T extends number>(v: T) {
}
const a = doIt<number>;
a(23);
TypeScript tsc:  1.4ms
TypeRunner cold: 0.014966250ms (93x faster)
TypeRunner warm: 0.000181875ms (7,697x faster)

Object literal type

type Person = {name: string, age: number}

const a: Person = {name: 'Peter', age: 52};
const b: Person = {name: 'Peter', age: '52'};
TypeScript tsc:  1.5ms
TypeRunner cold: 0.009106375ms (164x faster)
TypeRunner warm: 0.000836959ms (1,795x faster)

Complex type

type StringToNum<T extends string, A extends 0[] = []> = `${A['length']}` extends T ? A['length'] : StringToNum<T, [...A, 0]>;
const var1: StringToNum<'999'> = 999;
TypeScript tsc:  350.2ms
TypeRunner cold:   0.862534792ms (406x faster)
TypeRunner warm:   0.839308334ms (417x faster)

FAQ

Why?

TypeScript has one of the most versatile type systems, but the official tooling is very slow and the types are not usable in other languages. We want to make it fast and bring type computation accessible to all languages.

We believe that TypeScript can be much faster. Many workarounds exist to mitigate slow type checking. Some "TypeScript runtimes" even entirely disable type checking (and thus the key selling point of TypeScript) by default and rely on suboptimal editor-only type checking (which is still slow). We think it is possible to build a TypeScript compiler that is so fast that you can run TypeScript files directly with all its type checking features enabled and still have almost instant compile time.

We also believe that TypeScript is more than just a linter. It is a language that is so powerful and can be used for much more. Imagine writing a schema such as the following and be able to validate data against it in any language: JavaScript, C++, C, Rust, or Go.

export interface User {
    id: number & PrimaryKey;
    name: string & MinLength<3>;
    password: string;
}
export type ReadUser = Omit<User, 'password'>
export type CreateUser = Omit<User, 'id'>;

With TypeRunner this will be possible and thus has the potential to replace JSON schema with a much more powerful way of defining schemas. It doesn't stop with JSON schema however: ORM, GraphQL, gRPC, Protocol Buffers, and many more technologies that rely on schema information could rely on the powerful TypeScript type system to increase usability and efficiency dramatically. This brings isomorphic TypeScript to a whole new level.

Why doesn't Microsoft implement it like this?

Microsoft has had the goal to create wide adoption of TypeScript. That means to find product-market fit and improve UX, iteration speed is key to success. Writing high-performance code usually impacts these goals negatively.

Also, implementing features to make adoption easier and dogfooding are important strategies to make sure the product you're building will actually be adopted and solves real problems. However, since the TypeScript team doesn't have unlimited resources, this means that they have to focus on what brings growth. Performance is not something that brings much growth, especially if you take into consideration that the market expands every four years or so by 100%, which means that most developers are beginners and have priorities other than performance.

Strategically speaking it makes sense for Microsoft to develop TypeScript the way they do it, at least for the moment.

Why not a drop-in replacement for tsc?

TypeScript offers a lot of functionality. Many things are targeted at a smooth transition from JavaScript to TypeScript by allowing not-so-strict syntax and alternative type declaration syntax like JSDoc. Although these features have a big impact on new TypeScript users they are not so much used in projects where TypeScript is used more strictly. TypeScript comes also with a fairly big variety of transpilers/transformers to generate JavaScript for all the different versions of of ECMAScript standards. While we think that although these features have a big value for new users and adoption, we want to focus more on the enterprise side of things where performance often translates directly to money.

What is currently supported?

Only very basic type expressions are currently supported: primitives, variable declaration, (generic) function declaration, some type functions like type aliases, (distributive) conditional types, template literals, array/tuples, index access, union, rest, and a few other things. They are implemented in a very rough way just enough to proof that the language in its core can be implemented in a fast way.

When will it be released?

Currently, the development of TypeRunner is almost stalled and was more an experiment/proof of concept. To actually make this a reality, funding is necessary. In the coming weeks, we will set up a kickstarter/funding project, which makes it possible for the community that is interested in high-speed TypeScript to make this a reality.

Why C++ and not Rust?

Because I know C++ much better than Rust. The market of good C++ developers is much bigger. TypeScript code also maps surprisingly well to C++, so porting the scanner, parser, and AST structure is actually rather easy, which allows back-porting features from TypeScript tsc to TypeRunner much easier. I also find Rust ugly.

Why not port TypeScript?

Porting TypeScript alone to a faster language won't yield much performance difference since the V8 JIT optimises TypeScript compiler already, and the current slowdown comes mainly from architectural decisions made to work well in a JavaScript runtime (where optimisation strategies are very limited). To get a much faster compiler you have to do both: use a fast compiling language and use an architecture that utilizes all performance advantages of that language.

That being said, in the current stage the actual TypeScript scanner/parser code is ported from the TypeScript compiler to make back-porting easier. It's also at the moment the most complicated and slowest code (with over 20k LoC), which will be improved in the future.

What can I do to support this project?

Follow me on Twitter and fund it once the funding campaign is published: twitter.com/MarcJSchmidt

How does it work/Why is it so fast?

It is fast because it does the heavy-lifting only once per file and the type computation/comparison is optimised in a custom virtual machine.

The compiler consists of 3 stages: parsing to AST, compiling to bytecode, and executing the bytecode in a virtual machine. The first two stages are the most expensive and have to be done for each file once. The resulting bytecode can then be cached on disk.

The compiler has a simple data-flow analysis implemented to generate more efficient bytecode (like tail call/tail rest detection, and detecting usage of potential usage of super instructions). It also tries to precompute as much as possible. For example, all literal values will have in the bytecode header a precomputed 64-bit hash so that the virtual machine can compare literal types with a simple integer comparison and use it in hash-tables.

The stack based virtual machine tries to be lightweight and highly-performant as the most work happens here. It uses multiple memory pools with garbage collection, fix-sized type structure, tail call optimisation, and tuple re-use (tail rest optimisation). For list-structures, linked lists and hash tables (based on precomputed literal hash) are used to make lookups very fast.

The instruction set consists of currently 83 instructions: https://github.com/marcj/TypeRunner/blob/master/src/checker/instructions.h and will likely grow in the future.

Development

TypeRunner is written in modern C++ with cmake, doctest, imgui, tracy, fmt. To work on this project first clone the repository:

$ git clone [email protected]:marcj/TypeRunner.git
$ cd TypeRunner
$ git submodule update --init --recursive

To compile using Docker:

$ docker build -t typerunner -f Dockerfile .
$ docker run typerunner build/bench tests/objectLiterals1.ts

To compile natively make sure cmake and a C++ compiler is installed. We use LLVM toolchain per default. To build the project run the usual cmake command:

$ mkdir build
$ cd build
$ cmake -DCMAKE_CXX_COMPILER=clang++-14 -DCMAKE_C_COMPILER=clang-14 -DCMAKE_BUILD_TYPE=Release ..
$ make bench -j 8
$ ./bench ../tests/objectLiterals1.ts

Binaries are created in the build folder, which can now be executed.

More Repositories

1

css-element-queries

CSS Element-Queries aka Container Queries. High-speed element dimension/media queries in valid css.
JavaScript
4,270
star
2

jquery-selectBox

A jQuery plugin for replacing <select> elements.
JavaScript
548
star
3

angular2-localstorage

Angular 2+ decorator to save and restore variables/class properties to HTML5 LocalStorage automatically.
TypeScript
302
star
4

topsort.php

High-Performance Topological Sort / Dependency resolver in PHP
PHP
237
star
5

php-rest-service

Php-Rest-Service is a very simple and fast PHP class for server-side RESTful JSON APIs.
PHP
217
star
6

BetterQuitJobBundle

You should better quit your current job instead of searching a solution for *that* problem.
95
star
7

angular-es6-annotations

This little collection of annotations and registry functions allows you to register directives, controllers and filter with annotations at your angular module.
JavaScript
66
star
8

Pesto

Pesto is a high-performance GUI framework in C++ highly inspired by CSS and HTML, using Skia as rendering engine.
C++
64
star
9

angular-desktop-ui

Angular & Electron desktop UI framework. Angular components for native looking and behaving macOS desktop UI (Electron/Web)
TypeScript
51
star
10

pybridge

TypeScript library to access python functions in NodeJS, type-safe and easy to use.
TypeScript
44
star
11

typescript-react-dependency-injection

React + Vite + Deepkit's powerful dependency injection system
TypeScript
27
star
12

typedoc-plugin-lerna-packages

A plugin for Typedoc that groups all Lerna packages into own TS module
TypeScript
27
star
13

npm-local-development

Replacement for 'npm link' that actually works. Automatically overwrites installed packages with a locally available dev version.
JavaScript
24
star
14

glut.ts

The first reactive full-stack framework for Typescript specially tailored for admin interfaces and complex SPA.
TypeScript
23
star
15

bitcoin.ts

Typescript implementation of a Cryptocurrency inspired by the Bitcoin blockchain.
TypeScript
19
star
16

chrome-chatgpt-screenshot-extension

JavaScript
12
star
17

google-api-php-client

Google APIs Client Library for PHP
PHP
11
star
18

krycms-bundle-old

Don't use it. Don't Star it. Old project. New Project is https://github.com/jarves/jarves |
JavaScript
10
star
19

angular-typescript-decorators

Kinda hackish handy decorators for using Typescript with Angular v1.4+
TypeScript
9
star
20

katana-orm

Katana ORM, the new incredible sharp PHP ORM - maybe someday.
8
star
21

optimistic-locking-behavior

A behavior allowing you to use optimistic locking in Propel 2
PHP
5
star
22

twig-apply_filter-bundle

Symfony Bundle for Twig 'apply_filter' to call dynamic filters.
PHP
4
star
23

typescript-semantic-search

TypeScript
4
star
24

deepkit-bookstore

Example bookstore API with Deepkit API Console
TypeScript
3
star
25

angular-zoneless

Angular v16+ Zoneless implementation for SSR with Hydration
TypeScript
3
star
26

angular-unsub

Unsubscribes automatically your RXJS subscriptions when component is ngOnDestroy'ed
TypeScript
3
star
27

change-logger-behavior

Logs changes for defined columns in a extra logger table, for Propel2
PHP
3
star
28

glut-admin

The first real-time headless CMS/CMF with crud builder, based on Typescript/Angular. So efficient and fast it hurts.
TypeScript
2
star
29

mootools-sprintf

Mootools Javascript sprintf/printf function.
JavaScript
2
star
30

estdlib.ts

Engineer's strict stdlib for TypeScript.
TypeScript
2
star
31

mowla.js

A fast and super simple JavaScript Template Engine.
JavaScript
1
star
32

Propel2-old

PHP
1
star
33

shellfuncs

Some useful bash functions
Shell
1
star
34

deepkit-webpack

JavaScript
1
star
35

git-objects-sync

git push based on objects, instead of commits.
Python
1
star
36

angular-ivy-issue1

TypeScript
1
star
37

shut-the-lock

iOs Game "Shut the lock"
JavaScript
1
star
38

vscode-vertical-tabs

1
star
39

docker-macOS-container

An easy way to run commands in docker using macOS catalina as OS (via qemu) via ssh. Jenkins node possible
Shell
1
star
40

angular-desktop-ui-example

Angular v9 with angular-desktop-ui configured and ready to use
TypeScript
1
star