Skip to content

Commit

Permalink
Clear Babel Cache and avoid unnecessary AST clone
Browse files Browse the repository at this point in the history
Summary:
Improves the memory pressure and runtime-performance by cleaning the babel-cache and avoiding to clone the AST in the transformer.

Clearing the babel cache is not strictly necessary because babel uses a `WeakMap` internally. However, we can help the GC since we know that the same AST nodes are no longer referenced (it's either a different file or the file gets reparsed, which results in new nodes).

Before:
https://pxl.cl/1s5nB

After:

https://pxl.cl/1s5nx

Results for building the `MarketplaceHome.entrypoint` on my on-demand using a local metronome package with `--reset-cache`

|        | Run 1  | Run 2  | Run 3  |
|--------|--------|--------|--------|
| Before | 1m 17s | 1m 18s | 1m 19s |
| After  | 1m 14s | 1m 14s | 1m 13s |

Reviewed By: cpojer

Differential Revision: D25175301

fbshipit-source-id: 459074916d1c150a1767d245358e155e81a2661c
  • Loading branch information
Micha Reiser authored and facebook-github-bot committed Dec 1, 2020
1 parent aceafc5 commit 279b295
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 14 deletions.
26 changes: 12 additions & 14 deletions packages/metro-transform-worker/src/index.js
Expand Up @@ -17,7 +17,6 @@ const assetTransformer = require('./utils/assetTransformer');
const babylon = require('@babel/parser');
const collectDependencies = require('metro/src/ModuleGraph/worker/collectDependencies');
const generateImportNames = require('metro/src/ModuleGraph/worker/generateImportNames');
const nullthrows = require('nullthrows');
const generate = require('@babel/generator').default;
const getCacheKey = require('metro-cache-key');
const getMinifier = require('./utils/getMinifier');
Expand Down Expand Up @@ -373,19 +372,18 @@ module.exports = {

plugins.push([inlinePlugin, opts]);

ast = nullthrows(
transformFromAstSync(ast, '', {
ast: true,
babelrc: false,
code: false,
configFile: false,
comments: false,
compact: false,
filename,
plugins,
sourceMaps: false,
}).ast,
);
transformFromAstSync(ast, '', {
ast: true,
babelrc: false,
code: false,
configFile: false,
comments: false,
compact: false,
filename,
plugins,
sourceMaps: false,
cloneInputAst: false,
});

let dependencyMapName = '';
let dependencies;
Expand Down
9 changes: 9 additions & 0 deletions packages/metro/src/DeltaBundler/Worker.js
Expand Up @@ -13,6 +13,7 @@
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const traverse = require('@babel/traverse').default;

import type {TransformResult} from './types.flow';
import type {LogEntry} from 'metro-core/src/Logger';
Expand Down Expand Up @@ -84,6 +85,14 @@ async function transform(
transformOptions,
);

// The babel cache caches scopes and pathes for already traversed AST nodes.
// Clearing the cache here since the nodes of the transformed file are no longer referenced.
// This isn't stritcly necessary since the cache uses a WeakMap. However, WeakMap only permit
// that unreferenced keys are collected but the values still hold references to the Scope and NodePaths.
// Manually clearing the cache allows the GC to collect the Scope and NodePaths without checking if there
// exist any other references to the keys.
traverse.cache.clear();

const transformFileEndLogEntry = getEndLogEntry(
transformFileStartLogEntry,
filename,
Expand Down

0 comments on commit 279b295

Please sign in to comment.