New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf: Speed up getTargets
#15228
Merged
Merged
perf: Speed up getTargets
#15228
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import Benchmark from "benchmark"; | ||
import baseline from "@babel-baseline/helper-compilation-targets"; | ||
import current from "@babel/helper-compilation-targets"; | ||
import { report } from "../util.mjs"; | ||
|
||
const suite = new Benchmark.Suite("", { initCount: 0 }); | ||
function benchCases(implementation, name) { | ||
suite.add(name + "#getTargets last1", () => { | ||
implementation({ | ||
browsers: [ | ||
"last 1 chrome version", | ||
"last 1 firefox version", | ||
"last 1 safari version", | ||
"last 1 iOS version", | ||
"last 1 edge version", | ||
], | ||
}); | ||
}); | ||
suite.add(name + "#getTargets last100", () => { | ||
implementation({ | ||
browsers: [ | ||
"last 100 chrome version", | ||
"last 100 firefox version", | ||
"last 100 safari version", | ||
"last 100 iOS version", | ||
"last 100 edge version", | ||
], | ||
}); | ||
}); | ||
suite.add(name + "#getTargets chrome 49 ie 11", () => { | ||
implementation({ | ||
browsers: ["chrome 49", "ie 11"], | ||
}); | ||
}); | ||
} | ||
|
||
benchCases(baseline.default, "baseline"); | ||
benchCases(current.default, "current"); | ||
|
||
suite.on("cycle", report).run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import browserslist from "browserslist"; | ||
import { findSuggestion } from "@babel/helper-validator-option"; | ||
import browserModulesData from "@babel/compat-data/native-modules"; | ||
import LruCache from "lru-cache"; | ||
|
||
import { | ||
semverify, | ||
|
@@ -45,7 +46,7 @@ function validateTargetNames(targets: Targets): TargetsTuple { | |
} | ||
} | ||
|
||
return targets as any; | ||
return targets; | ||
} | ||
|
||
export function isBrowsersQueryValid(browsers: unknown): boolean { | ||
|
@@ -70,7 +71,7 @@ function getLowestVersions(browsers: Array<string>): Targets { | |
BrowserslistBrowserName, | ||
string, | ||
]; | ||
const target: Target = browserNameMap[browserName]; | ||
const target = browserNameMap[browserName]; | ||
|
||
if (!target) { | ||
return all; | ||
|
@@ -108,7 +109,7 @@ function getLowestVersions(browsers: Array<string>): Targets { | |
|
||
function outputDecimalWarning( | ||
decimalTargets: Array<{ target: string; value: number }>, | ||
): void { | ||
) { | ||
if (!decimalTargets.length) { | ||
return; | ||
} | ||
|
@@ -123,7 +124,7 @@ getting parsed as 6.1, which can lead to unexpected behavior. | |
`); | ||
} | ||
|
||
function semverifyTarget(target: keyof Targets, value: string) { | ||
function semverifyTarget(target: Target, value: string) { | ||
try { | ||
return semverify(value); | ||
} catch (error) { | ||
|
@@ -141,7 +142,7 @@ function nodeTargetParser(value: true | string) { | |
value === true || value === "current" | ||
? process.versions.node | ||
: semverifyTarget("node", value); | ||
return ["node" as const, parsed] as const; | ||
return ["node", parsed] as const; | ||
} | ||
|
||
function defaultTargetParser( | ||
|
@@ -158,7 +159,7 @@ function generateTargets(inputTargets: InputTargets): Targets { | |
const input = { ...inputTargets }; | ||
delete input.esmodules; | ||
delete input.browsers; | ||
return input as any as Targets; | ||
return input; | ||
} | ||
|
||
function resolveTargets(queries: Browsers, env?: string): Targets { | ||
|
@@ -169,6 +170,18 @@ function resolveTargets(queries: Browsers, env?: string): Targets { | |
return getLowestVersions(resolved); | ||
} | ||
|
||
const targetsCache = new LruCache(64); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We probably need less than 64, since the targets are usually the same for every file (I believe that 8 would be enough). However it doesn't really matter, since 64 small allocations already has a very small memory footprint. |
||
|
||
function resolveTargetsCached(queries: Browsers, env?: string): Targets { | ||
const cacheKey = typeof queries === "string" ? queries : queries.join() + env; | ||
let cached = targetsCache.get(cacheKey) as Targets | undefined; | ||
if (!cached) { | ||
cached = resolveTargets(queries, env); | ||
targetsCache.set(cacheKey, cached); | ||
} | ||
return { ...cached }; | ||
} | ||
|
||
type GetTargetsOption = { | ||
// This is not the path of the config file, but the path where start searching it from | ||
configPath?: string; | ||
|
@@ -181,7 +194,7 @@ type GetTargetsOption = { | |
}; | ||
|
||
export default function getTargets( | ||
inputTargets: InputTargets = {} as InputTargets, | ||
inputTargets: InputTargets = {}, | ||
options: GetTargetsOption = {}, | ||
): Targets { | ||
let { browsers, esmodules } = inputTargets; | ||
|
@@ -190,7 +203,7 @@ export default function getTargets( | |
validateBrowsers(browsers); | ||
|
||
const input = generateTargets(inputTargets); | ||
let targets: TargetsTuple = validateTargetNames(input); | ||
let targets = validateTargetNames(input); | ||
|
||
const shouldParseBrowsers = !!browsers; | ||
const hasTargets = shouldParseBrowsers || Object.keys(targets).length > 0; | ||
|
@@ -233,7 +246,10 @@ export default function getTargets( | |
// or an empty array (without any user config, use default config), | ||
// we don't need to call `resolveTargets` to execute the related methods of `browserslist` library. | ||
if (browsers?.length) { | ||
const queryBrowsers = resolveTargets(browsers, options.browserslistEnv); | ||
const queryBrowsers = resolveTargetsCached( | ||
browsers, | ||
options.browserslistEnv, | ||
); | ||
|
||
if (esmodules === "intersect") { | ||
for (const browser of Object.keys(queryBrowsers) as Target[]) { | ||
|
@@ -258,7 +274,7 @@ export default function getTargets( | |
} | ||
|
||
// Parse remaining targets | ||
const result: Targets = {} as Targets; | ||
const result: Targets = {}; | ||
const decimalWarnings = []; | ||
for (const target of Object.keys(targets).sort() as Target[]) { | ||
const value = targets[target]; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we update
lru-cache
to7.14.1
for Babel 8?