mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 06:02:11 +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.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
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.db.Database;
|
||||
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.PDOMNode;
|
||||
import org.eclipse.core.runtime.Assert;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
|
@ -90,8 +94,14 @@ public class IndexFileSet implements IIndexFileSet {
|
|||
PDOMFileSet pdomFileSet = (PDOMFileSet) fragmentFileSet;
|
||||
Database db = pdom.getDB();
|
||||
IRecordIterator nameIterator = pdom.getDeclarationsDefintitionsRecordIterator(binding);
|
||||
Set<Long> visited = null;
|
||||
long nameRecord;
|
||||
while ((nameRecord = nameIterator.next()) != 0) {
|
||||
if (visited != null && !visited.add(nameRecord)) {
|
||||
// Cycle detected!
|
||||
logInvalidNameChain(pdom, binding);
|
||||
return false;
|
||||
}
|
||||
long fileRecord = PDOMName.getFileRecord(db, nameRecord);
|
||||
if (pdomFileSet.containsFile(fileRecord)) {
|
||||
if (sDEBUG_INDEX_FILE_SET && iterationCount >= 200) {
|
||||
|
@ -103,12 +113,11 @@ public class IndexFileSet implements IIndexFileSet {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
if (sDEBUG_INDEX_FILE_SET && ++iterationCount % 1000 == 0) {
|
||||
System.out.println(
|
||||
String.format("IndexFileSet: %s (%s) not yet found after %d iterations", //$NON-NLS-1$
|
||||
String.join("::", binding.getQualifiedName()), //$NON-NLS-1$
|
||||
binding.getClass().getSimpleName(),
|
||||
iterationCount));
|
||||
if (iterationCount >= 1000 && visited == null) {
|
||||
// Iteration count is suspiciously high. Start keeping track of visited names
|
||||
// to be able to detect a cycle.
|
||||
visited = new HashSet<>();
|
||||
visited.add(nameRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,6 +135,40 @@ public class IndexFileSet implements IIndexFileSet {
|
|||
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() {
|
||||
return timingContainsDeclarationNanos;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue