question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Performance depends on declaration order

See original GitHub issue

These lines compile successfully in any order (assuming the import stays first, of course). Unexpectedly, the compilation time varies substantially based on the order.

import * as CSS from 'csstype';
declare const width: string | number; declare const y: CSSObject; const x: CSSObject = { width, ...y };
type CSSProperties = CSS.PropertiesFallback<number | string>;
type CSSPropertiesWithMultiValues = { [K in keyof CSSProperties]: CSSProperties[K] | Array<Exclude<CSSProperties[K], undefined>> };
interface ArrayCSSInterpolation extends Array<CSSInterpolation> {}
type InterpolationPrimitive = null | undefined | boolean | number | string | CSSObject;
type CSSInterpolation = InterpolationPrimitive | ArrayCSSInterpolation;
interface CSSOthersObject { [propertiesName: string]: CSSInterpolation }
interface CSSObject extends CSSPropertiesWithMultiValues, CSSOthersObject {}

On my box, compilation time varies between 2 and 3 seconds, depending on the order - quite a range. It appears to depend primarily on whether const x: CSSObject = { width, ...y }; or interface CSSObject extends CSSPropertiesWithMultiValues, CSSOthersObject {} comes first (slower with the const first).

This difference dates back to at least TS 3.6.

Discovered while investigating #43422 and reduced from the same codebase (i.e. emotion).

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

5reactions
ahejlsbergcommented, Apr 8, 2021

I figured out what’s happening here. As we discussed, it is caused by the way we cache temporary results on a “maybe related” list during evaluation of nested relationships (those “maybe related” results aren’t recorded in the main cache until we reach depth zero and know that our assumptions were correct). The “maybe related” list is scanned linearly and in this particular example it grows very large–we accumulate 17,500 temporary results during evaluation of 80,000 nested relationships and eventually the linear scan time completely dominates.

When the declarations in the repro example are reversed, a number of the interesting relationships are evaluated as part of checking the interface declaration and therefore cached in the main relationship cache. Thus, when it comes time to evaluate a relationship involving the interface, we already have most of the results cached and they never end up on the “maybe related” list.

I’ve verified we can be fix the issue by adding a map of “maybe related” results, but I’m going to think on it a little bit before putting up a PR.

0reactions
amcaseycommented, Apr 2, 2021

Mostly for my own amusement, I made a graph representation of the should-precede relation. A -- N% --> B should be read as “A should precede B, otherwise compilation time will increase by N%”. Note that the effect of reversing multiple edges is not cumulative.

order gv

Methodology: Time compilation of each permutation of the lines. Compare the average time of the permutations with A preceding B to the average time of the permutations with B preceding A. One run per permutation seemed sufficient, since we’re taking averages of 8!/2 =~ 20K runs.

Disclaimer: This is mostly for fun, so I didn’t double check it very carefully. However, the arrow from the top node to the bottom node matches the description of this bug.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Is SQL CTE performance depends on declaration order?
My real code is very complex and huge, and I have some performance problems with it, and I am trying to localize them....
Read more >
Specific performance - Wikipedia
Specific performance is an equitable remedy in the law of contract, whereby a court issues an order requiring a party to perform a...
Read more >
FL-303 Declaration Regarding Notice and Service of Request ...
DECLARATION REGARDING NOTICE AND SERVICE OF REQUEST. FOR TEMPORARY EMERGENCY (EX PARTE) ORDERS. FOR COURT USE ONLY. PARTY WITHOUT ATTORNEY OR ATTORNEY.
Read more >
602-Oaths and Declarations
When the issue concerns the authority of the person administering the oath, proof of authority may be required. Depending on the jurisdiction, the...
Read more >
Write safe and efficient C# code
Any performance improvements are an added benefit. The readonly struct keywords clearly express your design intent. Declare readonly members for ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found