Просмотр исходного кода

Small performance optimization for ignore rules/fnmatcher

 - don't check empty segments generated by String.split()
 - don't continue to add segments if the matcher fails to match input
 - don't add empty heads
 - don't iterate over empty heads.

Bug: 440732
Change-Id: I7d04dccfe24d91275d17ba246662337d6dba66df
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
tags/v3.5.0.201409071800-rc1
Andrey Loskutov 9 лет назад
Родитель
Сommit
3a161ac467

+ 13
- 3
org.eclipse.jgit/src/org/eclipse/jgit/fnmatch/FileNameMatcher.java Просмотреть файл

return new WildCardHead(star); return new WildCardHead(star);
} }


private void extendStringToMatchByOneCharacter(final char c) {
/**
* @param c new character to append
* @return true to continue, false if the matcher can stop appending
*/
private boolean extendStringToMatchByOneCharacter(final char c) {
final List<Head> newHeads = listForLocalUseage; final List<Head> newHeads = listForLocalUseage;
newHeads.clear(); newHeads.clear();
List<Head> lastAddedHeads = null; List<Head> lastAddedHeads = null;
// This is the case with the heads "a" and "*" of "a*b" which // This is the case with the heads "a" and "*" of "a*b" which
// both can return the list ["*","b"] // both can return the list ["*","b"]
if (headsToAdd != lastAddedHeads) { if (headsToAdd != lastAddedHeads) {
newHeads.addAll(headsToAdd);
if (!headsToAdd.isEmpty())
newHeads.addAll(headsToAdd);
lastAddedHeads = headsToAdd; lastAddedHeads = headsToAdd;
} }
} }
listForLocalUseage = heads; listForLocalUseage = heads;
heads = newHeads; heads = newHeads;
return !newHeads.isEmpty();
} }


private static int indexOfUnescaped(final String searchString, private static int indexOfUnescaped(final String searchString,
public void append(final String stringToMatch) { public void append(final String stringToMatch) {
for (int i = 0; i < stringToMatch.length(); i++) { for (int i = 0; i < stringToMatch.length(); i++) {
final char c = stringToMatch.charAt(i); final char c = stringToMatch.charAt(i);
extendStringToMatchByOneCharacter(c);
if (!extendStringToMatchByOneCharacter(c))
break;
} }
} }


* @return true, if the string currently being matched does match. * @return true, if the string currently being matched does match.
*/ */
public boolean isMatch() { public boolean isMatch() {
if (heads.isEmpty())
return false;

final ListIterator<Head> headIterator = heads final ListIterator<Head> headIterator = heads
.listIterator(heads.size()); .listIterator(heads.size());
while (headIterator.hasPrevious()) { while (headIterator.hasPrevious()) {

+ 15
- 5
org.eclipse.jgit/src/org/eclipse/jgit/ignore/IgnoreRule.java Просмотреть файл

final String[] segments = target.split("/"); //$NON-NLS-1$ final String[] segments = target.split("/"); //$NON-NLS-1$
for (int idx = 0; idx < segments.length; idx++) { for (int idx = 0; idx < segments.length; idx++) {
final String segmentName = segments[idx]; final String segmentName = segments[idx];
// String.split("/") creates empty segment for leading slash
if (segmentName.length() == 0)
continue;
if (segmentName.equals(pattern) && if (segmentName.equals(pattern) &&
doesMatchDirectoryExpectations(isDirectory, idx, segments.length)) doesMatchDirectoryExpectations(isDirectory, idx, segments.length))
return true; return true;
if (nameOnly) { if (nameOnly) {
for (int idx = 0; idx < segments.length; idx++) { for (int idx = 0; idx < segments.length; idx++) {
final String segmentName = segments[idx]; final String segmentName = segments[idx];
// String.split("/") creates empty segment for leading slash
if (segmentName.length() == 0)
continue;
//Iterate through each sub-directory //Iterate through each sub-directory
matcher.reset(); matcher.reset();
matcher.append(segmentName); matcher.append(segmentName);
//TODO: This is the slowest operation //TODO: This is the slowest operation
//This matches e.g. "/src/ne?" to "/src/new/file.c" //This matches e.g. "/src/ne?" to "/src/new/file.c"
matcher.reset(); matcher.reset();

for (int idx = 0; idx < segments.length; idx++) { for (int idx = 0; idx < segments.length; idx++) {
final String segmentName = segments[idx]; final String segmentName = segments[idx];
if (segmentName.length() > 0) {
matcher.append("/" + segmentName); //$NON-NLS-1$
}
// String.split("/") creates empty segment for leading slash
if (segmentName.length() == 0)
continue;


if (matcher.isMatch() &&
doesMatchDirectoryExpectations(isDirectory, idx, segments.length))
matcher.append("/" + segmentName); //$NON-NLS-1$

if (matcher.isMatch()
&& doesMatchDirectoryExpectations(isDirectory, idx,
segments.length))
return true; return true;
} }
} }

Загрузка…
Отмена
Сохранить