Typescript: Feature request: inline function

Created on 12 Sep 2014  路  18Comments  路  Source: microsoft/TypeScript

such as : inline public int add(a, b): int { return a+b; }
It's very useful for performance

Out of Scope Suggestion

Most helpful comment

I'm totally with jlennox here: this is not just his case, but a common good programming practices case.

Sometimes we like to write tons of little helper functions (that need not incur the overhead of function calls when the code is run) and are just there for code clarity.

All 18 comments

JavaScript runtimes already automatically perform function inlining; there's no need for TypeScript to do this given the complexity of doing it correctly.

Inlining at the JS level vs the runtime level may not be wholly equal, however.

http://jsperf.com/do-add-inline-test

Chrome 43.0.2357.81:
6,391,069 vs 6,714,536

Internet Explorer 11.0.9600.17801
2,079,037 vs 17,248,948

Internet Explorer 8.0.7601.17514
57,947 vs 250,837

Firefox 38.0.1
13,654,068 vs 13,444,826

Runtime inling is slower in everything but firefox, and in the latest version of internet explorer it's 8.3x faster for the JS to be inlined!

Can you provide a counter example?

Even if this particular example were representative of the majority of examples the results don't really suggest doing our own optimization pass is correct. Clearly in this case inlining the code doesn't actually make us faster everywhere, a meaningful number of your customers now experience slower code (even if only marginally, other cases may be worse). Then the fact that Firefox demonstrates this performance characteristic suggests it's entirely possible for IE and Chrome to eventually do the same (for this or other code patterns), at which point our optimization phase is now making your performance slower everywhere (and you only know this for each microbenchmark you manually inspect), while costing us time, adding complexity to our codebase and making the emitted JS farther from the TS that you wrote. Further, any optimization pass of this nature that you might want to make could just be handled by an existing JS optimizing tool whose sole goal is optimizing performance, something we will never be as focused on as a tool like that or the JS runtimes themselves.

The JavaScript runtimes do an immense amount of work to optimize your code, some based on static analysis, some based on runtime patterns, or something else entirely. We're simply never going to spend the same amount of effort as them on these problems (nor do we have enough information to do what they do) and the best thing we can do for your performance is to emit idiomatic code so that as they improve we emit JS that benefits from that: https://wingolog.org/archives/2011/08/02/a-closer-look-at-crankshaft-v8s-optimizing-compiler

I should of said this before. I'm not for automatic inlining, but something closer to a macro statement.

Sadly, IE8 to IE11 will never become what version of IE ultimately does optimize this situation well. We'll be supporting those browsers for a very long time.

Thank you for the interesting link.

@jlennox see also https://github.com/Microsoft/TypeScript/issues/2721

For your case perhaps you could define a decorator called inline and a post processing task could do the work of replacing the places you've determined inlining to be advantageous.

I'm totally with jlennox here: this is not just his case, but a common good programming practices case.

Sometimes we like to write tons of little helper functions (that need not incur the overhead of function calls when the code is run) and are just there for code clarity.

This would be very useful for user defined type guards.

Yes I agree. I personally need this a lot

I think automatic inlining similar to Golang would be beneficial,
Even basic "getter" support (ie when you simply return 1 value from a function), would be a good start.

Just to reiterate: JS runtimes are extremely (extremely) good at this and you really shouldn't be worrying about this using logic acquired when writing C code.

For example, in the parser, we changed hundreds of instances from x = e; to x = f(); where f was just return e, all of which were in the hot path. We saw 0% change in runtime. 0%.

For any case where TS could determine that a function could be inlined, the JS runtime is already doing a better job of it.

@RyanCavanaugh I really doubt you saw a 0% change in runtime in Internet Explorer and I don't think you're accounting for cases where a website needs to perform fast on IE/Edge browsers due to client restraints.

Are you able to post a link to these benchmarks? Does it cover every browser or just the Chrome?

@RyanCavanaugh You can see in the result from my original test case that around Chrome 54 they either improved inlining or improved side effect free branch removal: https://jsperf.com/do-add-inline-test.

Which is great. However, I'm targeting IE8. Which now and forever has a 5x speed improvement possibility, and IE11 which has an 8x. Even in Chrome latest you can see there is some performance improvement.

I wouldn't presume that this would be decided automatically by the TypeScript compiler. Instead it would be like the C 'inline' keyword. Even C#/.NET supports something similar with MethodImplAttribute, and that's for a JIT, just like JavaScript.

Guys, what a compiler can do, should do. If it's complicated to implement let's keep it in the backlogs until there is time for it. We can't talk about the runtime because we don't know it, we can't presume that it will be always a browser ( or a browser's JS engine in the case of node.js for example ), it could be some new startup tech in 2022, who knows.

As a note here, I just got a significant speed increase by inlining a function called in a tight loop on node 8. So there is, imo, a reason to do this - apparently the JavaScript runtime isn't _always_ that optimal.

@RyanCavanaugh @danquirk I'd love to see this feature re-opened please 馃槃 The browser's ability to inline is not sufficient for a number of scenarios in the real world.

As a concrete example, I work on this product: https://www.invisionapp.com/studio One of the most critical parts of this app is a custom, WebGL-based renderer. The renderer is not currently written in TypeScript and one of the reasons it's difficult for us to justify a move to TypeScript is because of TypeScript's inability to inline specific functions. The current language it's written in supports this and it's critical for our perf scenarios.

I also believe we could make use of this in Aurelia to more liberally factor some of our complex functions to smaller functions. Inside a framework of this nature, perf is very critical.

In both the scenarios above, perf is a key competitive feature in the market and every decision is made within that context.

I realize this isn't a small feature and it's complicated, but I wanted to put another vote here based on two real, non-trivial projects that are well-known in the community.

Thanks for all the great work you all are doing!

Please for the love all that is holy allow us proper inlining and a preprocessor. As a game dever this is absolutely critical especially for javascript, for both code size and runtime efficiency reasons. But please don't make inline a "suggestion" but instead forced. Or at the least include support for __forceinline like what the visual c++ compiler uses. We need full control over our code and allowing us to do things like this is just a massive help. Your already gaining traction from the game dev community. Those of us who code our own engines need as much control as possible to squeeze out as much performance as possible. Laziness is not an option in this situation.

I tip my hat to the devs of this amazing software though it's already a massive improvement over the mess that is javascript.

This feature might be also useful for React, reference: https://flexport.engineering/ending-the-debate-on-inline-functions-in-react-8c03fabd144

Was this page helpful?
0 / 5 - 0 ratings

Related issues

blendsdk picture blendsdk  路  3Comments

manekinekko picture manekinekko  路  3Comments

seanzer picture seanzer  路  3Comments

uber5001 picture uber5001  路  3Comments

Antony-Jones picture Antony-Jones  路  3Comments