mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 565553 - Improve performance of build command parsers with large number of files
Narrow down parsers based on option string Instead of trying to match all patterns one by one, we can check the start of the option string to be parsed and narrow down which pattern (parsers) should be used. Doing so is much less elegant code-wise as we are "unrolling" the beginning of the patterns by hand, but it gives a good speed up. Around 300ms saved with a test of LLVM code base (~50% of parseOption time) and much larger gains on much larger projects or course. Change-Id: I9e841e7233078d6e38ad08943d98966d0e3c661e Signed-off-by: Marc-Andre Laperle <malaperle@gmail.com>
This commit is contained in:
parent
379e300382
commit
08e8e57162
4 changed files with 185 additions and 15 deletions
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
|||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %pluginName
|
||||
Bundle-SymbolicName: org.eclipse.cdt.managedbuilder.core; singleton:=true
|
||||
Bundle-Version: 9.0.0.qualifier
|
||||
Bundle-Version: 9.1.0.qualifier
|
||||
Bundle-Activator: org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin
|
||||
Bundle-Vendor: %providerName
|
||||
Bundle-Localization: plugin
|
||||
|
|
|
@ -418,6 +418,20 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
|
|||
*/
|
||||
protected abstract AbstractOptionParser[] getOptionParsers();
|
||||
|
||||
/**
|
||||
* @return array of option parsers defining how to parse a string to
|
||||
* {@link ICLanguageSettingEntry}.
|
||||
* See {@link AbstractOptionParser} and its specific extenders.
|
||||
*
|
||||
* @param optionToParse the option string to be parsed.
|
||||
* This can be used as a hint in order to return a subset of parsers, for better performance.
|
||||
*
|
||||
* @since 9.1
|
||||
*/
|
||||
protected AbstractOptionParser[] getOptionParsers(String optionToParse) {
|
||||
return getOptionParsers();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} when the provider tries to resolve relative or remote paths
|
||||
* to the existing paths in the workspace or local file-system using certain heuristics.
|
||||
|
@ -499,8 +513,8 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
|
|||
|
||||
List<String> options = parseOptions(line);
|
||||
if (options != null) {
|
||||
AbstractOptionParser[] optionParsers = getOptionParsers();
|
||||
for (String option : options) {
|
||||
AbstractOptionParser[] optionParsers = getOptionParsers(option);
|
||||
for (AbstractOptionParser optionParser : optionParsers) {
|
||||
try {
|
||||
if (optionParser.parseOption(option)) {
|
||||
|
|
|
@ -13,6 +13,11 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.managedbuilder.language.settings.providers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.core.errorparsers.RegexErrorPattern;
|
||||
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditableProvider;
|
||||
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
|
||||
|
@ -32,34 +37,124 @@ import org.eclipse.cdt.core.settings.model.ICSettingEntry;
|
|||
*/
|
||||
public class GCCBuildCommandParser extends AbstractBuildCommandParser implements ILanguageSettingsEditableProvider {
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] optionParsers = {
|
||||
static final AbstractOptionParser[] includeOptionParsers = {
|
||||
new IncludePathOptionParser("-I\\s*(?<quote>[\"'])(.*)\\k<quote>", "$2"),
|
||||
new IncludePathOptionParser("-I\\s*([^\\s\"']*)", "$1"),
|
||||
new IncludePathOptionParser("-I\\s*([^\\s\"']*)", "$1"), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] systemIncludeOptionParsers = {
|
||||
new IncludePathOptionParser("-isystem\\s*(?<quote>[\"'])(.*)\\k<quote>", "$2"),
|
||||
new IncludePathOptionParser("-isystem\\s*([^\\s\"']*)", "$1"),
|
||||
new IncludePathOptionParser("-isystem\\s*([^\\s\"']*)", "$1"), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] frameworkOptionParsers = {
|
||||
new IncludePathOptionParser("-(F|(iframework))\\s*(?<quote>[\"'])(.*)\\k<quote>", "$4",
|
||||
ICSettingEntry.FRAMEWORKS_MAC),
|
||||
new IncludePathOptionParser("-(F|(iframework))\\s*([^\\s\"']*)", "$3", ICSettingEntry.FRAMEWORKS_MAC),
|
||||
new IncludePathOptionParser("-(F|(iframework))\\s*([^\\s\"']*)", "$3", ICSettingEntry.FRAMEWORKS_MAC), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] forceIncludeOptionParsers = {
|
||||
new IncludeFileOptionParser("-include\\s*(?<quote>[\"'])(.*)\\k<quote>", "$2"),
|
||||
new IncludeFileOptionParser("-include\\s*([^\\s\"']*)", "$1"),
|
||||
new IncludeFileOptionParser("-include\\s*([^\\s\"']*)", "$1"), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] defineOptionParsers = {
|
||||
new MacroOptionParser("-D\\s*(?<quote>[\"'])([^=]*)(=(.*))?\\k<quote>", "$2", "$4"),
|
||||
new MacroOptionParser("-D\\s*([^\\s=\"']*)=(\"\\\\(\")(.*?)\\\\\"\")", "$1", "$3$4$3"),
|
||||
new MacroOptionParser("-D\\s*([^\\s=\"']*)=(?<quote>\\\\([\"']))(.*?)\\k<quote>", "$1", "$3$4$3"),
|
||||
new MacroOptionParser("-D\\s*([^\\s=\"']*)=(?<quote>[\"'])(.*?)\\k<quote>", "$1", "$3"),
|
||||
new MacroOptionParser("-D\\s*([^\\s=\"']*)=([^\\s\"']*)?", "$1", "$2"),
|
||||
new MacroOptionParser("-D\\s*([^\\s=\"']*)", "$1", "1"),
|
||||
new MacroOptionParser("-U\\s*([^\\s=\"']*)", "$1", ICSettingEntry.UNDEFINED),
|
||||
new MacroOptionParser("-D\\s*([^\\s=\"']*)", "$1", "1"), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] undefineOptionParsers = {
|
||||
new MacroOptionParser("-U\\s*([^\\s=\"']*)", "$1", ICSettingEntry.UNDEFINED), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] macrosOptionParsers = {
|
||||
new MacroFileOptionParser("-imacros\\s*(?<quote>[\"'])(.*)\\k<quote>", "$2"),
|
||||
new MacroFileOptionParser("-imacros\\s*([^\\s\"']*)", "$1"),
|
||||
new MacroFileOptionParser("-imacros\\s*([^\\s\"']*)", "$1"), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] libraryOptionParsers = {
|
||||
new LibraryPathOptionParser("-L\\s*(?<quote>[\"'])(.*)\\k<quote>", "$2"),
|
||||
new LibraryPathOptionParser("-L\\s*([^\\s\"']*)", "$1"),
|
||||
new LibraryFileOptionParser("-l\\s*([^\\s\"']*)", "lib$1.a"), };
|
||||
|
||||
static final AbstractOptionParser[] emptyParsers = new AbstractOptionParser[0];
|
||||
|
||||
static final AbstractOptionParser[] optionParsers;
|
||||
static {
|
||||
List<AbstractOptionParser> parsers = new ArrayList<>(Arrays.asList(includeOptionParsers));
|
||||
Collections.addAll(parsers, systemIncludeOptionParsers);
|
||||
Collections.addAll(parsers, frameworkOptionParsers);
|
||||
Collections.addAll(parsers, forceIncludeOptionParsers);
|
||||
Collections.addAll(parsers, defineOptionParsers);
|
||||
Collections.addAll(parsers, undefineOptionParsers);
|
||||
Collections.addAll(parsers, macrosOptionParsers);
|
||||
Collections.addAll(parsers, libraryOptionParsers);
|
||||
|
||||
optionParsers = parsers.toArray(new AbstractOptionParser[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractOptionParser[] getOptionParsers() {
|
||||
return optionParsers;
|
||||
}
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
@Override
|
||||
protected AbstractOptionParser[] getOptionParsers(String optionToParse) {
|
||||
if (optionToParse.length() <= 1) {
|
||||
return emptyParsers;
|
||||
}
|
||||
|
||||
// Skip -, we know it's there with the OPTIONS_PATTERN
|
||||
String optionName = optionToParse.substring(1);
|
||||
|
||||
if (optionName.startsWith("I")) {
|
||||
return includeOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("D")) {
|
||||
return defineOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("l") || optionName.startsWith("L")) {
|
||||
return libraryOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("i")) {
|
||||
if (optionName.startsWith("include")) {
|
||||
return forceIncludeOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("isystem")) {
|
||||
return systemIncludeOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("imacros")) {
|
||||
return macrosOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("iframework")) {
|
||||
return frameworkOptionParsers;
|
||||
}
|
||||
|
||||
return emptyParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("F")) {
|
||||
return frameworkOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("U")) {
|
||||
return undefineOptionParsers;
|
||||
}
|
||||
|
||||
return emptyParsers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GCCBuildCommandParser cloneShallow() throws CloneNotSupportedException {
|
||||
return (GCCBuildCommandParser) super.cloneShallow();
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
package org.eclipse.cdt.msw.build.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -93,12 +95,22 @@ public class MSVCBuildCommandParser extends AbstractBuildCommandParser implement
|
|||
}
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] optionParsers = { new MSVCIncludePathOptionParser("(-|/)I\\s*\"(.*)\"", "$2"),
|
||||
new MSVCIncludePathOptionParser("(-|/)I\\s*([^\\s\"]*)", "$2"),
|
||||
static final AbstractOptionParser[] includeOptionParsers = {
|
||||
new MSVCIncludePathOptionParser("(-|/)I\\s*\"(.*)\"", "$2"),
|
||||
new MSVCIncludePathOptionParser("(-|/)I\\s*([^\\s\"]*)", "$2"), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] forceIncludeOptionParsers = {
|
||||
new MSVCForceIncludePathOptionParser("(-|/)FI\\s*\"(.*)\"", "$2"),
|
||||
new MSVCForceIncludePathOptionParser("(-|/)FI\\s*([^\\s\"]*)", "$2"),
|
||||
new MSVCForceIncludePathOptionParser("(-|/)FI\\s*([^\\s\"]*)", "$2"), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] msvcIncludeOptionParsers = {
|
||||
new ClangCLMSVCSystemPathOptionParser("(-|/)imsvc\\s*\"(.*)\"", "$2"),
|
||||
new ClangCLMSVCSystemPathOptionParser("(-|/)imsvc\\s*([^\\s\"]*)", "$2"),
|
||||
new ClangCLMSVCSystemPathOptionParser("(-|/)imsvc\\s*([^\\s\"]*)", "$2"), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] defineOptionParsers = {
|
||||
// /D "FOO=bar"
|
||||
new MSVCMacroOptionParser("(-|/)D\\s*\"([^=]+)=(.*)\"", "$2", "$3"),
|
||||
// /D FOO="bar"
|
||||
|
@ -108,12 +120,28 @@ public class MSVCBuildCommandParser extends AbstractBuildCommandParser implement
|
|||
// /D FOO
|
||||
new MSVCMacroOptionParser("(-|/)D\\s*([^\\s=\"]+)", "$2", "1"),
|
||||
// /D"FOO"
|
||||
new MSVCMacroOptionParser("(-|/)D\\s*\"([^\\s=\"]+)\"", "$2", "1"),
|
||||
new MSVCMacroOptionParser("(-|/)D\\s*\"([^\\s=\"]+)\"", "$2", "1"), };
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
static final AbstractOptionParser[] undefineOptionParsers = {
|
||||
// /U FOO
|
||||
new MacroOptionParser("(-|/)U\\s*([^\\s=\"]+)", "$2", ICSettingEntry.UNDEFINED),
|
||||
// /U "FOO"
|
||||
new MacroOptionParser("(-|/)U\\s*\"(.*?)\"", "$2", ICSettingEntry.UNDEFINED) };
|
||||
|
||||
static final AbstractOptionParser[] emptyParsers = new AbstractOptionParser[0];
|
||||
|
||||
static final AbstractOptionParser[] optionParsers;
|
||||
static {
|
||||
List<AbstractOptionParser> parsers = new ArrayList<>(Arrays.asList(includeOptionParsers));
|
||||
Collections.addAll(parsers, defineOptionParsers);
|
||||
Collections.addAll(parsers, msvcIncludeOptionParsers);
|
||||
Collections.addAll(parsers, forceIncludeOptionParsers);
|
||||
Collections.addAll(parsers, undefineOptionParsers);
|
||||
|
||||
optionParsers = parsers.toArray(new AbstractOptionParser[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* "foo" or "C:\foo\\"
|
||||
*
|
||||
|
@ -147,6 +175,39 @@ public class MSVCBuildCommandParser extends AbstractBuildCommandParser implement
|
|||
return optionParsers;
|
||||
}
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
@Override
|
||||
protected AbstractOptionParser[] getOptionParsers(String optionToParse) {
|
||||
if (optionToParse.length() <= 1) {
|
||||
return emptyParsers;
|
||||
}
|
||||
|
||||
// Skip - or /, we know it's there with the OPTIONS_PATTERN
|
||||
String optionName = optionToParse.substring(1);
|
||||
|
||||
if (optionName.startsWith("I")) {
|
||||
return includeOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("D")) {
|
||||
return defineOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("imsvc")) {
|
||||
return msvcIncludeOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("FI")) {
|
||||
return forceIncludeOptionParsers;
|
||||
}
|
||||
|
||||
if (optionName.startsWith("U")) {
|
||||
return undefineOptionParsers;
|
||||
}
|
||||
|
||||
return emptyParsers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MSVCBuildCommandParser cloneShallow() throws CloneNotSupportedException {
|
||||
return (MSVCBuildCommandParser) super.cloneShallow();
|
||||
|
|
Loading…
Add table
Reference in a new issue