google / google/closure-compiler
Exponential perf degradation during substituteGenerics (NTI)
- Dominant language
- JavaScript
- Stars
- 7.7k
- Forks
- 1.2k
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 6
Description
Our moderately sized codebase uses extensive use of the [externs attached](https://github.com/google/closure-compiler/files/1421907/externs.js.txt). Over time, as we've build out these externs, and the corresponding code that uses them, we've seen an exponential degradation in performance, to the point where it's taking literally hours and gigabytes of memory to complete checks-only compilation.
Here's an example stacktrace after pausing in Eclipse once it's taken far too long already:
```
ImmutableMap.copyOf(Map) line: 333
FunctionType.normalized(JSTypes, List, List, JSType, JSType, JSType, JSType, Map, TypeParameters, boolean, boolean) line: 232
FunctionTypeBuilder.buildFunction() line: 191
FunctionType.substituteNominalGenerics(Map) line: 1287
FunctionType.substituteGenerics(Map) line: 1296
ObjectType.substituteGenerics(Map) line: 1587
JSType$ObjsType(JSType).substituteGenerics(Map) line: 698
Property.substituteGenerics(Map) line: 220
ObjectType.substituteGenerics(Map) line: 1584
JSType$NullableObjsType(JSType).substituteGenerics(Map) line: 698
Property.substituteGenerics(Map) line: 218
ObjectType.substituteGenerics(Map) line: 1584
JSType$ObjsType(JSType).substituteGenerics(Map) line: 698
Property.substituteGenerics(Map) line: 220
ObjectType.substituteGenerics(Map) line: 1584
JSType$ObjsType(JSType).substituteGenerics(Map) line: 698
FunctionType.substituteNominalGenerics(Map) line: 1268
FunctionType.substituteGenerics(Map) line: 1296
ObjectType.substituteGenerics(Map) line: 1587
JSType$UnionType(JSType).substituteGenerics(Map) line: 698
Property.substituteGenerics(Map) line: 218
ObjectType.substituteGenerics(Map) line: 1584
JSType$UnionType(JSType).substituteGenerics(Map) line: 698
Property.substituteGenerics(Map) line: 218
ObjectType.substituteGenerics(Map) line: 1584
JSType$UnionType(JSType).substituteGenerics(Map) line: 698
Property.substituteGenerics(Map) line: 218
ObjectType.substituteGenerics(Map) line: 1584
JSType$UnionType(JSType).substituteGenerics(Map) line: 698
Property.substituteGenerics(Map) line: 218
ObjectType.substituteGenerics(Map) line: 1584
JSType$ObjsType(JSType).substituteGenerics(Map) line: 698
Property.substituteGenerics(Map) line: 218
ObjectType.substituteGenerics(Map) line: 1584
JSType$NullableObjsType(JSType).substituteGenerics(Map) line: 698
FunctionType.substituteNominalGenerics(Map) line: 1276
FunctionType.substituteGenerics(Map) line: 1296
ObjectType.substituteGenerics(Map) line: 1587
JSType$ObjsType(JSType).substituteGenerics(Map) line: 698
Property.substituteGenerics(Map) line: 218
NominalType.getProp(String, RawNominalType$PropAccess) line: 414
RawNominalType.getPropFromClass(String, RawNominalType$PropAccess) line: 429
RawNominalType.getProp(String, RawNominalType$PropAccess) line: 458
RawNominalType.getInstancePropDeclaredType(String) line: 478
NominalType.getPropDeclaredType(String) line: 427
GlobalTypeInfoCollector.checkSuperProperty(RawNominalType, NominalType, String, Multimap, Multimap) line: 655
GlobalTypeInfoCollector.checkAndFreezeNominalType(RawNominalType) line: 532
GlobalTypeInfoCollector.process(Node, Node) line: 378
PhaseOptimizer$NamedPass.process(Node, Node) line: 304
PhaseOptimizer.process(Node, Node) line: 230
```
The problem appears to be due to some combination of the usages of:
1. `|undefined` to allow properties to be optional
2. `Array<...>` generic types
3. The depth of the tree of types being defined in the externs
Performance is improved by breaking up the structure of these externs type trees through changing various arrays to `Array<*>` and putting in casts at point of use.
I've created a very simple [example in the debugger](https://closure-compiler-debugger.appspot.com/#input0%3D%250A%252F**%2520%2540abstract%2520*%252F%250Aclass%2520X%2520%257B%250A%250A%2520%2520%252F**%250A%2520%2520%2520*%2520%2540return%2520%257B%253FHighcharts.Options%257D%250A%2520%2520%2520*%2520%2540abstract%250A%2520%2520%2520*%252F%250A%2520%2520getOptions()%2520%257B%257D%250A%250A%257D%250A%250Aclass%2520Y%2520extends%2520X%2520%257B%250A%2520%2520%252F**%2520%2540override%2520*%252F%250A%2520%2520getOptions()%2520%257B%250A%2520%2520%2520%2520return%2520%257B%250A%2520%2520%2520%2520%2520%2520chart%253A%2520%257B%2520animation%253A%2520true%2520%257D%252C%250A%2520%2520%2520%2520%2520%2520title%253A%2520null%252C%250A%2520%2520%2520%2520%2520%2520subtitle%253A%2520null%250A%2520%2520%2520%2520%257D%253B%250A%2520%2520%257D%250A%257D%250A%26input1%26conformanceConfig%26externs%3D%252F**%2520%2540constructor%2520*%252F%250Avar%2520Element%2520%253D%2520function()%2520%257B%257D%253B%2520%252F%252F%2520not%2520sure%2520why%2520debugger%2520doesn't%2520know%2520about%2520this%250A%250A%250Avar%2520Highcharts%2520%253D%2520%257B%257D%253B%250A%250A%252F**%250A%2520*%2520%2540param%2520%257BHighcharts.HighchartsOptions%257D%2520globalOptions%250A%2520*%252F%250AHighcharts.setOptions%2520%253D%2520function(globalOptions)%2520%257B%257D%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520global%253A%2520(Highcharts.GlobalOptions%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.HighchartsOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520useUTC%253A%2520(boolean%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.GlobalOptions%253B%250A%250A%252F**%250A%2520*%2520%2540constructor%250A%2520*%252F%250AHighcharts.SVGRenderer%2520%253D%2520function()%2520%257B%257D%253B%250A%250A%250A%252F**%250A%2520*%2520%2540type%2520%257BObject%253Cstring%252C%2520function(number%252C%2520number%252C%2520number%252C%2520number)%253AArray%253C(string%257Cnumber)%253E%253E%257D%250A%2520*%252F%250AHighcharts.SVGRenderer.prototype.symbols%253B%250A%250AHighcharts.seriesTypes%2520%253D%2520%257B%250A%2520%2520%2520%2520wordcloud%253A%2520Highcharts.WordcloudType%250A%257D%253B%250A%250A%252F**%250A%2520*%2520%2540type%2520%257B%257B%250A%2520*%2520%2520placementStrategy%253A%2520*%252C%250A%2520*%2520%2520deriveFontSize%253A%2520function()%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.WordcloudType%253B%250A%250A%252F**%250A%2520*%2520%2540param%2520%257BElement%257D%2520element%250A%2520*%2520%2540param%2520%257BHighcharts.Options%257D%2520options%250A%2520*%2520%2540return%2520%257BHighcharts.Chart%257D%250A%2520*%252F%250AHighcharts.chart%2520%253D%2520function(element%252C%2520options)%2520%257B%257D%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520%2520%2520%2520%2520chart%253A%2520(Highcharts.ChartOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520credits%253A%2520(Highcharts.CreditsOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520legend%253A%2520(Highcharts.LegendOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520pane%253A%2520(Highcharts.PaneOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520plotOptions%253A%2520(Highcharts.PlotOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520series%253A%2520(Highcharts.SeriesOptions%257CArray%253CHighcharts.SeriesOptions%253E%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520subtitle%253A%2520(%253Fstring%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520title%253A%2520(%253Fstring%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520tooltip%253A%2520(Highcharts.TooltipOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520xAxis%253A%2520(Highcharts.AxisOptions%257CArray%253CHighcharts.AxisOptions%253E%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520yAxis%253A%2520(Highcharts.AxisOptions%257CArray%253CHighcharts.AxisOptions%253E%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520zAxis%253A%2520(Highcharts.AxisOptions%257CArray%253CHighcharts.AxisOptions%253E%257Cundefined)%252C%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.Options%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520animation%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520type%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520events%253A%2520(Highcharts.EventsOptions%257Cundefined)%252C%250A%2520*%2520%2520alignTicks%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520zoomType%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520inverted%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520polar%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520options3d%253A%2520(Highcharts.Options3D%257Cundefined)%252C%250A%2520*%2520%2520margin%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520spacingBottom%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520spacingTop%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520spacingLeft%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520spacingRight%253A%2520(number%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.ChartOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520enabled%253A%2520(boolean%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.CreditsOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520enabled%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520itemStyle%253A%2520(*%257Cundefined)%252C%250A%2520*%2520%2520margin%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520padding%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520itemDistance%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520symbolPadding%253A%2520(number%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.LegendOptions%253B%250A%250A%252F**%250A%2520*%2520%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520%2520%2520%2520%2520center%253A%2520(Array%253Cstring%253E%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520size%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520startAngle%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520endAngle%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520background%253A%2520(%257BinnerRadius%253A%2520(string%257Cundefined)%252C%2520outerRadius%253A%2520(string%257Cundefined)%252C%2520shape%253A%2520(string%257Cundefined)%257D%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.PaneOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520area%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520areaspline%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520bar%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520column%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520line%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520spline%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520pie%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520funnel%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520pyramid%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520scatter%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520series%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520solidgauge%253A%2520(Highcharts.SeriesOptions%257Cundefined)%252C%250A%2520*%2520%2520wordcloud%253A%2520(Highcharts.SeriesOptions%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.PlotOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520%2520%2520%2520%2520name%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520id%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520color%253A%2520(string%257CHighcharts.GradientColourOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520animation%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520type%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520xAxis%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520yAxis%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520marker%253A%2520(Highcharts.MarkerOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520turboThreshold%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520dataLabels%253A%2520(Highcharts.DataLabelsOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520tooltip%253A%2520(Highcharts.TooltipOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520events%253A%2520(Highcharts.EventsOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520borderColor%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520borderWidth%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520levels%253A%2520(Array%253CHighcharts.SeriesLevelOptions%253E%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520fillOpacity%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520zIndex%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520lineWidth%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520dial%253A%2520(%257BbackgroundColor%253A%2520(string%257Cundefined)%257D%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520size%253A%2520(number%257Cstring%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520innerSize%253A%2520(number%257Cstring%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520startAngle%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520endAngle%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520center%253A%2520(Array%253Cstring%257Cnull%253E%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520enableMouseTracking%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520showInLegend%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520stacking%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520connectNulls%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520trackByArea%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520neckWidth%253A%2520(number%257Cstring%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520neckHeight%253A%2520(number%257Cstring%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520pointPlacement%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520pointWidth%253A%2520(number%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520maxPointWidth%253A%2520(number%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520pointPadding%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520groupPadding%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520data%253A%2520(Array%253C*%253E%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520placementStrategy%253A%2520(string%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.SeriesOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520enabled%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520headerFormat%253A%2520(string%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520pointFormat%253A%2520(string%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520crosshairs%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520shared%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520formatter%253A%2520(function(this%253A%2520Highcharts.Event)%257Cundefined)%252C%250A%2520*%2520%2520pointFormatter%253A%2520(function(this%253A%2520Highcharts.Point)%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.TooltipOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520%2520%2520%2520%2520visible%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520gridLineColor%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520gridLineWidth%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520gridLineInterpolation%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520min%253A%2520(number%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520max%253A%2520(number%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520softMin%253A%2520(number%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520softMax%253A%2520(number%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520title%253A%2520(%257Benabled%253A%2520(boolean%257Cundefined)%252C%2520text%253A%2520(string%257Cnull%257Cundefined)%252C%2520y%253A%2520(number%257Cundefined)%257D%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520categories%253A%2520(Array%253Cstring%253E%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520labels%253A%2520(Highcharts.AxisLabelOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520stackLabels%253A%2520(Highcharts.AxisLabelOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520tickmarkPlacement%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520tickPositioner%253A%2520(function(this%253A%2520Highcharts.Axis)%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520lineWidth%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520type%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520minorTickInterval%253A%2520(%253Fnumber%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520tickAmount%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520opposite%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520scrollbar%253A%2520(Highcharts.AxisScrollbarOptions%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.AxisOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520enabled%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520align%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520reserveSpace%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520x%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520y%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520style%253A%2520(*%257Cundefined)%252C%250A%2520*%2520%2520min%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520max%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520formatter%253A%2520(function(this%253A%2520Highcharts.AxisLabelFormatterEvent)%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.AxisLabelOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520enabled%253A%2520(boolean%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.AxisScrollbarOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520enabled%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520connectorColor%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520allowOverlap%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520align%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520verticalAlign%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520format%253A%2520(string%257Cnull%257Cundefined)%252C%250A%2520*%2520%2520formatter%253A%2520(function(this%253A%2520Highcharts.Event)%257Cundefined)%252C%250A%2520*%2520%2520style%253A%2520(*%257Cundefined)%252C%250A%2520*%2520%2520borderWidth%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520useHTML%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520inside%253A%2520(boolean%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.DataLabelsOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520click%253A%2520(function(Highcharts.Event)%257Cundefined)%252C%250A%2520*%2520%2520selection%253A%2520(function(Highcharts.Event)%257Cundefined)%252C%250A%2520*%2520%2520redraw%253A%2520(function(Highcharts.Event)%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.EventsOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520%2520%2520%2520%2520enabled%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520states%253A%2520(Highcharts.MarkerStateOptions%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520radius%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520lineColor%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520lineWidth%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520%2520%2520%2520%2520symbol%253A%2520(string%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.MarkerOptions%253B%250A%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520select%253A%2520(*%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.MarkerStateOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520alpha%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520beta%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520depth%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520enabled%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520fitToPlot%253A%2520(boolean%257Cundefined)%252C%250A%2520*%2520%2520frame%253A%2520(%257Bbottom%253A%2520(Highcharts.FrameOptions%257Cundefined)%252C%2520back%253A%2520(Highcharts.FrameOptions%257Cundefined)%252C%2520side%253A%2520(Highcharts.FrameOptions%257Cundefined)%257D%257Cundefined)%252C%250A%2520*%2520%2520viewDistance%253A%2520(number%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.Options3D%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520size%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520color%253A%2520(string%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.FrameOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520level%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520layoutAlgorithm%253A%2520(string%257Cundefined)%252C%250A%2520*%2520%2520borderWidth%253A%2520(number%257Cundefined)%252C%250A%2520*%2520%2520dataLabels%253A%2520(Highcharts.DataLabelsOptions%257Cundefined)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.SeriesLevelOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520linearGradient%253A%2520(%257Bx1%253A%2520number%252C%2520x2%253A%2520number%252C%2520y1%253A%2520number%252C%2520y2%253A%2520number%257D)%252C%250A%2520*%2520%2520stops%253A%2520(Array%253CArray%253Cnumber%257Cstring%253E%253E)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.GradientColourOptions%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520toPixels%253A%2520function(number)%253Anumber%252C%250A%2520*%2520%2520toValue%253A%2520function(number)%253Anumber%252C%250A%2520*%2520%2520getExtremes%253A%2520function()%253A(Highcharts.AxisExtremes)%252C%250A%2520*%2520%2520categories%253A%2520Array%253C*%253E%252C%250A%2520*%2520%2520width%253A%2520number%252C%250A%2520*%2520%2520height%253A%2520number%252C%250A%2520*%2520%2520min%253A%2520number%252C%250A%2520*%2520%2520max%253A%2520number%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.Axis%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520min%253A%2520number%252C%250A%2520*%2520%2520max%253A%2520number%252C%250A%2520*%2520%2520dataMin%253A%2520number%252C%250A%2520*%2520%2520dataMax%253A%2520number%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.AxisExtremes%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520destroy%253A%2520function()%252C%250A%2520*%2520%2520reflow%253A%2520function()%252C%250A%2520*%2520%2520renderer%253A%2520Highcharts.Renderer%252C%250A%2520*%2520%2520get%253A%2520function(string)%253A(Highcharts.Point)%252C%250A%2520*%2520%2520getSelectedPoints%253A%2520function()%253AArray%253CHighcharts.Point%253E%252C%250A%2520*%2520%2520xAxis%253A%2520Array%253CHighcharts.Axis%253E%252C%250A%2520*%2520%2520yAxis%253A%2520Array%253CHighcharts.Axis%253E%252C%250A%2520*%2520%2520series%253A%2520Array%253CHighcharts.Series%253E%252C%250A%2520*%2520%2520plotBox%253A%2520%257Bx%253A%2520number%252C%2520y%253A%2520number%252C%2520width%253A%2520number%252C%2520height%253A%2520number%257D%252C%250A%2520*%2520%2520options%253A%2520Highcharts.Options%252C%250A%2520*%2520%2520redraw%253A%2520function(boolean)%252C%250A%2520*%2520%2520plotLeft%253A%2520number%252C%250A%2520*%2520%2520plotTop%253A%2520number%252C%250A%2520*%2520%2520plotWidth%253A%2520number%252C%250A%2520*%2520%2520plotHeight%253A%2520number%252C%250A%2520*%2520%2520update%253A%2520function(Highcharts.Options)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.Chart%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520add%253A%2520function()%252C%250A%2520*%2520%2520attr%253A%2520function(%253F)%252C%250A%2520*%2520%2520show%253A%2520function()%252C%250A%2520*%2520%2520hide%253A%2520function()%252C%250A%2520*%2520%2520toFront%253A%2520function()%252C%250A%2520*%2520%2520translateX%253A%2520number%252C%250A%2520*%2520%2520translateY%253A%2520number%252C%250A%2520*%2520%2520padding%253A%2520number%252C%250A%2520*%2520%2520width%253A%2520number%252C%250A%2520*%2520%2520height%253A%2520number%252C%250A%2520*%2520%2520translate%253A%2520function(number%252C%2520number)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.Element%253B%250A%250A%252F**%250A%2520*%2520NOTE%253A%2520data%2520and%2520points%2520are%2520deliberately%2520untyped.%250A%2520*%2520They%2520should%2520be%2520Highcharts.Point%250A%2520*%2520but%2520this%2520introduces%2520a%2520massive%2520(4x)%2520degradation%2520in%2520NTI%2520compilation%2520time%250A%2520*%2520presumably%2520because%2520of%2520some%2520recursive%2520code%2520in%2520CC%2520which%2520is%2520visiting%2520the%2520above%2520structures%250A%2520*%2520to%2520handle%2520generics%2520(Array%253C...%253E)%2520and%2520this%2520object%2520appears%2520in%2520many%2520possible%2520different%250A%2520*%2520tree%2520structures.%250A%2520*%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520index%253A%2520number%252C%250A%2520*%2520%2520data%253A%2520Array%253C*%253E%252C%250A%2520*%2520%2520points%253A%2520Array%253C*%253E%252C%250A%2520*%2520%2520name%253A%2520string%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.Series%253B%250A%250A%252F**%250A%2520*%2520Custom%2520properties%253A%250A%2520*%250A%2520*%2520element%253A%2520Custom%2520property%2520for%2520element%2520plots.%2520The%2520ElementModel%2520representing%2520this%2520point.%250A%2520**%250A%2520*%2520measure%253A%2520Custom%2520property%2520for%2520element%2520plots.%2520The%2520alternative%2520Measure%2520to%2520use%2520to%2520obtain%2520the%2520element%2520value.%250A%2520*%2520By%2520default%2520we%2520use%2520the%2520primary%2520measure.%2520In%2520some%2520cases%2520we%2520want%2520to%2520use%2520an%2520alternative%2520measure%2520(eg.%2520in%2520the%2520bar%252Fline%250A%2520*%2520chart%2520we%2520want%2520to%2520use%2520either%2520the%2520%2522barMeasure%2522%2520or%2520%2522lineMeasure%2522).%250A%2520*%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520select%253A%2520function(boolean%253D%252Cboolean%253D)%252C%250A%2520*%2520%2520index%253A%2520number%252C%250A%2520*%2520%2520dataLabel%253A%2520(%253FHighcharts.Element)%252C%250A%2520*%2520%2520connector%253A%2520(%253FHighcharts.Element)%252C%250A%2520*%2520%2520series%253A%2520Highcharts.Series%252C%250A%2520*%2520%2520point%253A%2520%257Bx%253A%2520number%252C%2520y%253A%2520number%252C%2520low%253A%2520number%252C%2520high%253A%2520number%252C%2520element%253A%2520*%257D%252C%250A%2520*%2520%2520element%253A%2520*%252C%250A%2520*%2520%2520measure%253A%2520*%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.Point%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520rect%253A%2520(function(number%252C%2520number%252C%2520number%252C%2520number%252C%2520number)%253AHighcharts.Element)%252C%250A%2520*%2520%2520button%253A%2520(function(string%252C%2520number%252C%2520number%252C%2520function())%253AHighcharts.Element)%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.Renderer%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520series%253A%2520Highcharts.Series%252C%250A%2520*%2520%2520point%253A%2520Highcharts.Point%252C%250A%2520*%2520%2520points%253A%2520Array%253C*%253E%252C%250A%2520*%2520%2520xAxis%253A%2520Array%253C*%253E%252C%250A%2520*%2520%2520yAxis%253A%2520Array%253C*%253E%252C%250A%2520*%2520%2520x%253A%2520number%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.Event%253B%250A%250A%252F**%250A%2520*%2520%2540typedef%2520%257B%257B%250A%2520*%2520%2520value%253A%2520number%252C%250A%2520*%2520%2520isFirst%253A%2520boolean%252C%250A%2520*%2520%2520isLast%253A%2520boolean%252C%250A%2520*%2520%2520total%253A%2520number%252C%250A%2520*%2520%2520x%253A%2520number%250A%2520*%2520%257D%257D%250A%2520*%252F%250AHighcharts.AxisLabelFormatterEvent%253B%250A%250A%250A%26refasterjs-template%26includeDefaultExterns%3Dtrue%26CHECK_SYMBOLS%3Dtrue%26MISSING_PROPERTIES%3Dtrue%26TRANSPILE%3Dtrue%26CHECK_TYPES%3Dtrue%26CHECK_TYPES_NEW_INFERENCE%3Dtrue%26CLOSURE_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue), but it doesn't show any obvious performance problems. Probably it needs a larger real-world codebase, which I can't submit.
Externs in full, attached: [externs.js.txt](https://github.com/google/closure-compiler/files/1421907/externs.js.txt)
Contributor guide
Assessment
This issue has not been assessed yet.