mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 14:12:10 +02:00
Bug 509898 - IndexFileSet.containsDeclaration is slow and is causing UI
freezes Added cycle detection to IndexFileSet.containsDeclaration. Change-Id: I48a596bd680bd4f764739b9170a98c907c41ae8c
This commit is contained in:
parent
5e793c9b43
commit
5462bac381
1 changed files with 49 additions and 6 deletions
|
@ -13,7 +13,9 @@ package org.eclipse.cdt.internal.core.index;
|
||||||
|
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
@ -25,7 +27,9 @@ import org.eclipse.cdt.internal.core.pdom.PDOM;
|
||||||
import org.eclipse.cdt.internal.core.pdom.PDOMFileSet;
|
import org.eclipse.cdt.internal.core.pdom.PDOMFileSet;
|
||||||
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
||||||
import org.eclipse.cdt.internal.core.pdom.dom.IRecordIterator;
|
import org.eclipse.cdt.internal.core.pdom.dom.IRecordIterator;
|
||||||
|
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
||||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
||||||
|
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
|
||||||
import org.eclipse.core.runtime.Assert;
|
import org.eclipse.core.runtime.Assert;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
|
@ -90,8 +94,14 @@ public class IndexFileSet implements IIndexFileSet {
|
||||||
PDOMFileSet pdomFileSet = (PDOMFileSet) fragmentFileSet;
|
PDOMFileSet pdomFileSet = (PDOMFileSet) fragmentFileSet;
|
||||||
Database db = pdom.getDB();
|
Database db = pdom.getDB();
|
||||||
IRecordIterator nameIterator = pdom.getDeclarationsDefintitionsRecordIterator(binding);
|
IRecordIterator nameIterator = pdom.getDeclarationsDefintitionsRecordIterator(binding);
|
||||||
|
Set<Long> visited = null;
|
||||||
long nameRecord;
|
long nameRecord;
|
||||||
while ((nameRecord = nameIterator.next()) != 0) {
|
while ((nameRecord = nameIterator.next()) != 0) {
|
||||||
|
if (visited != null && !visited.add(nameRecord)) {
|
||||||
|
// Cycle detected!
|
||||||
|
logInvalidNameChain(pdom, binding);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
long fileRecord = PDOMName.getFileRecord(db, nameRecord);
|
long fileRecord = PDOMName.getFileRecord(db, nameRecord);
|
||||||
if (pdomFileSet.containsFile(fileRecord)) {
|
if (pdomFileSet.containsFile(fileRecord)) {
|
||||||
if (sDEBUG_INDEX_FILE_SET && iterationCount >= 200) {
|
if (sDEBUG_INDEX_FILE_SET && iterationCount >= 200) {
|
||||||
|
@ -103,12 +113,11 @@ public class IndexFileSet implements IIndexFileSet {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (sDEBUG_INDEX_FILE_SET && ++iterationCount % 1000 == 0) {
|
if (iterationCount >= 1000 && visited == null) {
|
||||||
System.out.println(
|
// Iteration count is suspiciously high. Start keeping track of visited names
|
||||||
String.format("IndexFileSet: %s (%s) not yet found after %d iterations", //$NON-NLS-1$
|
// to be able to detect a cycle.
|
||||||
String.join("::", binding.getQualifiedName()), //$NON-NLS-1$
|
visited = new HashSet<>();
|
||||||
binding.getClass().getSimpleName(),
|
visited.add(nameRecord);
|
||||||
iterationCount));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,6 +135,40 @@ public class IndexFileSet implements IIndexFileSet {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void logInvalidNameChain(PDOM pdom, IIndexBinding binding) {
|
||||||
|
try {
|
||||||
|
PDOMBinding pdomBinding = (PDOMBinding) binding;
|
||||||
|
for (String listType : new String[] {"declarations", "definitions"}) { //$NON-NLS-1$//$NON-NLS-2$
|
||||||
|
StringBuilder nameChain = new StringBuilder();
|
||||||
|
Set<PDOMName> visited = new HashSet<>();
|
||||||
|
PDOMName first = listType.equals("declarations") ? pdomBinding.getFirstDeclaration() : pdomBinding.getFirstDefinition(); //$NON-NLS-1$
|
||||||
|
for (PDOMName name = first; name != null; name= name.getNextInBinding()) {
|
||||||
|
if (nameChain.length() != 0)
|
||||||
|
nameChain.append(", "); //$NON-NLS-1$
|
||||||
|
nameChain.append(name.getRecord());
|
||||||
|
PDOMBinding nameBinding = name.getBinding();
|
||||||
|
if (!nameBinding.equals(binding)) {
|
||||||
|
nameChain.append(String.format(" belongs to %s (%s) @%d", //$NON-NLS-1$
|
||||||
|
String.join("::", nameBinding.getQualifiedName()), //$NON-NLS-1$
|
||||||
|
nameBinding.getClass().getSimpleName(),
|
||||||
|
((PDOMNode) nameBinding).getRecord()));
|
||||||
|
}
|
||||||
|
if (!visited.add(name)) {
|
||||||
|
CCorePlugin.log(String.format("IndexFileSet: %s (%s) @%d - list of %s contains a cycle: ", //$NON-NLS-1$
|
||||||
|
String.join("::", binding.getQualifiedName()), //$NON-NLS-1$
|
||||||
|
binding.getClass().getSimpleName(),
|
||||||
|
pdomBinding.getRecord(),
|
||||||
|
listType,
|
||||||
|
nameChain.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
CCorePlugin.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public long getTimingContainsDeclarationNanos() {
|
public long getTimingContainsDeclarationNanos() {
|
||||||
return timingContainsDeclarationNanos;
|
return timingContainsDeclarationNanos;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue