Reduce linear search on list traversing (#12302)

* perf: reduce linear search on list traversing

* fix: remove parent cache when replacing node
This commit is contained in:
Huáng Jùnliàng 2020-11-04 20:14:51 -05:00 committed by GitHub
parent 6cb6f9f5ea
commit 0641a15030
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 14 additions and 18 deletions

View File

@ -95,7 +95,7 @@ export default class TraversalContext {
this.queue = queue; this.queue = queue;
this.priorityQueue = []; this.priorityQueue = [];
const visited = []; const visited = new WeakSet();
let stop = false; let stop = false;
// visit the queue // visit the queue
@ -120,8 +120,9 @@ export default class TraversalContext {
} }
// ensure we don't visit the same node twice // ensure we don't visit the same node twice
if (visited.indexOf(path.node) >= 0) continue; const { node } = path;
visited.push(path.node); if (visited.has(node)) continue;
if (node) visited.add(node);
if (path.visit()) { if (path.visit()) {
stop = true; stop = true;

View File

@ -67,24 +67,16 @@ export default class NodePath {
const targetNode = container[key]; const targetNode = container[key];
const paths = pathCache.get(parent) || []; let paths = pathCache.get(parent);
if (!pathCache.has(parent)) { if (!paths) {
paths = new Map();
pathCache.set(parent, paths); pathCache.set(parent, paths);
} }
let path; let path = paths.get(targetNode);
for (let i = 0; i < paths.length; i++) {
const pathCheck = paths[i];
if (pathCheck.node === targetNode) {
path = pathCheck;
break;
}
}
if (!path) { if (!path) {
path = new NodePath(hub, parent); path = new NodePath(hub, parent);
paths.push(path); if (targetNode) paths.set(targetNode, path);
} }
path.setup(parentPath, container, listKey, key); path.setup(parentPath, container, listKey, key);

View File

@ -163,8 +163,7 @@ export function updateSiblingKeys(fromIndex, incrementBy) {
if (!this.parent) return; if (!this.parent) return;
const paths = pathCache.get(this.parent); const paths = pathCache.get(this.parent);
for (let i = 0; i < paths.length; i++) { for (const [, path] of paths) {
const path = paths[i];
if (path.key >= fromIndex) { if (path.key >= fromIndex) {
path.key += incrementBy; path.key += incrementBy;
} }

View File

@ -1,6 +1,7 @@
// This file contains methods responsible for removing a node. // This file contains methods responsible for removing a node.
import { hooks } from "./lib/removal-hooks"; import { hooks } from "./lib/removal-hooks";
import { path as pathCache } from "../cache";
import { REMOVED, SHOULD_SKIP } from "./index"; import { REMOVED, SHOULD_SKIP } from "./index";
export function remove() { export function remove() {
@ -44,6 +45,7 @@ export function _remove() {
export function _markRemoved() { export function _markRemoved() {
// this.shouldSkip = true; this.removed = true; // this.shouldSkip = true; this.removed = true;
this._traverseFlags |= SHOULD_SKIP | REMOVED; this._traverseFlags |= SHOULD_SKIP | REMOVED;
if (this.parent) pathCache.get(this.parent).delete(this.node);
this.node = null; this.node = null;
} }

View File

@ -3,6 +3,7 @@
import { codeFrameColumns } from "@babel/code-frame"; import { codeFrameColumns } from "@babel/code-frame";
import traverse from "../index"; import traverse from "../index";
import NodePath from "./index"; import NodePath from "./index";
import { path as pathCache } from "../cache";
import { parse } from "@babel/parser"; import { parse } from "@babel/parser";
import * as t from "@babel/types"; import * as t from "@babel/types";
@ -49,6 +50,7 @@ export function replaceWithMultiple(nodes: Array<Object>) {
nodes = this._verifyNodeList(nodes); nodes = this._verifyNodeList(nodes);
t.inheritLeadingComments(nodes[0], this.node); t.inheritLeadingComments(nodes[0], this.node);
t.inheritTrailingComments(nodes[nodes.length - 1], this.node); t.inheritTrailingComments(nodes[nodes.length - 1], this.node);
pathCache.get(this.parent).delete(this.node);
this.node = this.container[this.key] = null; this.node = this.container[this.key] = null;
const paths = this.insertAfter(nodes); const paths = this.insertAfter(nodes);