Skip to content

Commit

Permalink
Merge branch 'eclipse-platform:master' into perf_improvement_batch_re…
Browse files Browse the repository at this point in the history
…place
  • Loading branch information
mehmet-karaman authored Sep 17, 2024
2 parents 4ecdd27 + a43889d commit 66f734e
Show file tree
Hide file tree
Showing 32 changed files with 320 additions and 307 deletions.
2 changes: 1 addition & 1 deletion bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jface.text
Bundle-Version: 3.25.200.qualifier
Bundle-Version: 3.25.300.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;

import org.eclipse.text.readers.SubstitutionReader;

import org.eclipse.jface.text.TextPresentation;


Expand All @@ -34,7 +36,7 @@
* <p>
* Moved into this package from <code>org.eclipse.jface.internal.text.revisions</code>.</p>
*/
public class HTML2TextReader extends SubstitutionTextReader {
public class HTML2TextReader extends SubstitutionReader {

private static final String EMPTY_STRING= ""; //$NON-NLS-1$
private static final Map<String, String> fgEntityLookup;
Expand Down
2 changes: 1 addition & 1 deletion bundles/org.eclipse.text.quicksearch/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.text.quicksearch;singleton:=true
Bundle-Version: 1.2.400.qualifier
Bundle-Version: 1.2.500.qualifier
Bundle-Activator: org.eclipse.text.quicksearch.internal.ui.QuickSearchActivator
Require-Bundle: org.eclipse.ui;bundle-version="[3.113.0,4.0.0)",
org.eclipse.core.resources;bundle-version="[3.13.0,4.0.0)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public int getOffset() {

private boolean caseInsensitive;
private String orgPattern; //Original pattern case preserved even if search is case insensitive.
private Pattern pattern;
final Pattern pattern;

/**
* A query that matches anything.
Expand All @@ -60,15 +60,11 @@ public QuickTextQuery() {
public QuickTextQuery(String substring, boolean caseInsensitive) {
this.orgPattern = substring;
this.caseInsensitive = caseInsensitive;
createMatcher(substring, caseInsensitive);
String regex = createRegEx(substring);
pattern = Pattern.compile(regex, caseInsensitive ? Pattern.CASE_INSENSITIVE : 0);
}

/**
* Compile a pattern string into an RegExp and create a Matcher for that
* regexp. This is so we can 'compile' the pattern once and then keep reusing
* the matcher or compiled pattern.
*/
private void createMatcher(String patString, boolean caseSensitive) {
private String createRegEx(String patString) {
StringBuilder segment = new StringBuilder(); //Accumulates text that needs to be 'quoted'
StringBuilder regexp = new StringBuilder(); //Accumulates 'compiled' pattern
int pos = 0, len = patString.length();
Expand Down Expand Up @@ -101,8 +97,7 @@ private void createMatcher(String patString, boolean caseSensitive) {
//Don't forget to process that last segment.
appendSegment(segment, regexp);

this.pattern = Pattern.compile(regexp.toString(), caseSensitive? Pattern.CASE_INSENSITIVE : 0);
// this.matcher = pattern.matcher("");
return regexp.toString();
}

private void appendSegment(StringBuilder segment, StringBuilder regexp) {
Expand Down Expand Up @@ -157,25 +152,6 @@ private String normalize(String pat, boolean caseSensitive) {
return pat;
}

/**
* @return whether the LineItem text contains the search pattern.
*/
public boolean matchItem(LineItem item) {
return matchItem(item.getText());
}

/**
* Same as matchItem except only takes the text of the item. This can
* be useful for efficient processing. In particular to avoid creating
* LineItem instances for non-matching lines.
*/
public boolean matchItem(String item) {
//Alternate implementation. This is thread safe without synchronized,
// but it creates some garbage.
Matcher matcher = pattern.matcher(item); //Creating garbage here
return matcher.find();
}

/**
* A trivial query is one that either
* - matches anything
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@
package org.eclipse.text.quicksearch.internal.core;

import java.io.InputStreamReader;
import java.util.HashSet;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
Expand All @@ -32,21 +40,22 @@
import org.eclipse.text.quicksearch.internal.util.LineReader;

public class QuickTextSearcher {
private static int MAX_BUFFER_LENGTH = 999_999; // read max 1MB bytes => max 2MB chars.
private final QuickTextSearchRequestor requestor;
private QuickTextQuery query;

/**
* Keeps track of currently found matches. Items are added as they are found and may also
* be removed when the query changed and they become invalid.
*/
private Set<LineItem> matches = new HashSet<>(2000);
private final Set<LineItem> matches = ConcurrentHashMap.newKeySet(2000);

/**
* Scheduling rule used by Jobs that work on the matches collection.
*/
private ISchedulingRule matchesRule = new LightSchedulingRule("QuickSearchMatchesRule"); //$NON-NLS-1$

private SearchInFilesWalker walker = null;
private final SearchInFilesWalker walker;
private IncrementalUpdateJob incrementalUpdate;

/**
Expand Down Expand Up @@ -75,7 +84,8 @@ public class QuickTextSearcher {
* While searching in a file, this field will be set. This can be used to show the name
* of the 'current file' in the progress area of the quicksearch dialog.
*/
private IFile currentFile = null;
private volatile IFile currentFile = null;
public volatile int searchTookMs;

/**
* Flag to disable incremental filtering logic based on incremental
Expand Down Expand Up @@ -124,35 +134,62 @@ private SearchInFilesWalker createWalker(PriorityFunction priorities) {

private final class SearchInFilesWalker extends ResourceWalker {


@Override
protected void visit(IFile f, IProgressMonitor mon) {
if (checkCanceled(mon)) {
return;
public IStatus run(IProgressMonitor monitor) {
searchTookMs = 0;
long n0 = System.nanoTime();
try {
return super.run(monitor);
} finally {
currentFile = null;
long n1 = System.nanoTime();
if (matches.isEmpty()) {
searchTookMs = (int) ((n1 - n0) / 1_000_000);
}
}
}

@Override
protected boolean searchIn(IFile f, BooleanSupplier canceled) {
currentFile = f;
try (LineReader lr = new LineReader(new InputStreamReader(f.getContents(true), f.getCharset()), MAX_LINE_LEN)) {
String line = null;
return search(f, canceled, MAX_LINE_LEN, query.pattern, QuickTextSearcher.this::add);
}

private static boolean search(IFile f, BooleanSupplier canceled,
int maxLineLength, Pattern pattern, Consumer<LineItem> add) {
if (canceled.getAsBoolean()) {
return false;
}
try (LineReader lr = new LineReader(getReader(f),
maxLineLength)) {
String line;
int lineIndex = 1;
while ((line = lr.readLine()) != null) {
int offset = lr.getLastLineOffset();
if (checkCanceled(mon)) {
return;
if (canceled.getAsBoolean()) {
return false;
}

boolean found = query.matchItem(line);
if (found) {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
LineItem lineItem = new LineItem(f, line, lineIndex, offset);
add(lineItem);
add.accept(lineItem);
}

lineIndex++;
}
} catch (Exception e) {
// ignored
} finally {
currentFile = null;
}
return true;
}

private static Reader getReader(IFile f) throws UnsupportedEncodingException, CoreException {
String shortString = toShortString(f);
if (shortString != null) {
return new StringReader(shortString);
} else {
return new InputStreamReader(f.getContents(true), f.getCharset());
}
}

Expand All @@ -164,18 +201,27 @@ public void resume() {
}
}

private boolean checkCanceled(IProgressMonitor mon) {
return mon.isCanceled();
}

public void requestMoreResults() {
int currentSize = matches.size();
maxResults = Math.max(maxResults, currentSize + currentSize/10);
resume();
}
/**
* Try to get a content as String. Avoids Streaming.
*/
private static String toShortString(IFile file) {
/**
* Just any number such that the most source files will fit in. And not too
* big to avoid out of memory.
**/
try {
byte[] content = file.readNBytes(MAX_BUFFER_LENGTH);
int length = content.length;
if (length >= MAX_BUFFER_LENGTH) {
return null;
}
String charset = file.getCharset();
return new String(content, charset);
} catch (Exception e) {
return null;
}

}

/**
* This job updates already found matches when the query is changed.
* Both the walker job and this job share the same scheduling rule so
Expand Down Expand Up @@ -203,17 +249,20 @@ protected IStatus run(IProgressMonitor monitor) {
} else {
query = nq;
forceRefresh = false;
performRestart();
if (!monitor.isCanceled()) { // avoid restart if dialog got closed
performRestart();
}
}
return monitor.isCanceled()?Status.CANCEL_STATUS:Status.OK_STATUS;
return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
}

private void performIncrementalUpdate(IProgressMonitor mon) {
Iterator<LineItem> items = matches.iterator();
while (items.hasNext() && !mon.isCanceled()) {

LineItem item = items.next();
if (query.matchItem(item)) {
Matcher matcher = query.pattern.matcher(item.getText());
if (matcher.find()) {
//Match still valid but may need updating highlighted text in the UI:
requestor.update(item);
} else {
Expand All @@ -228,31 +277,26 @@ private void performIncrementalUpdate(IProgressMonitor mon) {
}

private void performRestart() {
//walker may be null if dialog got closed already before we managed to
// 'performRestart'.
if (walker!=null) {
//since we are inside Job here that uses same scheduling rule as walker, we
//know walker is not currently executing. so walker cancel should be instantenous
matches.clear();
requestor.clear();
walker.cancel();
if (!query.isTrivial()) {
walker.init(); //Reinitialize the walker work queue to its starting state
walker.resume(); //Allow walker to resume when we release the scheduling rule.
} else {
walker.stop();
}
//since we are inside Job here that uses same scheduling rule as walker, we
//know walker is not currently executing. so walker cancel should be instantenous
matches.clear();
requestor.clear();
walker.cancel();
if (!query.isTrivial()) {
walker.init(); //Reinitialize the walker work queue to its starting state
walker.resume(); //Allow walker to resume when we release the scheduling rule.
} else {
walker.stop();
}
}

}

private void add(LineItem line) {
if (matches.add(line)) {
if (!isActive()) {
walker.suspend();
} else if (matches.add(line)) {
requestor.add(line);
if (!isActive()) {
walker.suspend();
}
}
}

Expand All @@ -261,7 +305,7 @@ public void setQuery(QuickTextQuery newQuery, boolean force) {
return;
}
this.newQuery = newQuery;
this.forceRefresh = true;
this.forceRefresh = force;
scheduleIncrementalUpdate();
}

Expand Down Expand Up @@ -304,19 +348,13 @@ public boolean isDone() {
//Walker can be null if job was canceled because dialog closed. But stuff like
//the job that shows 'Searching ...' doesn't instantly stop and may still
//be asking the incremental update job whether its done.
return /*(incrementalUpdate != null && incrementalUpdate.getState() != Job.NONE) ||*/ (walker!=null && walker.isDone());
}

public void requestMoreResults() {
if (walker!=null && !walker.isDone()) {
walker.requestMoreResults();
}
return /*(incrementalUpdate != null && incrementalUpdate.getState() != Job.NONE) ||*/ walker.isDone();
}

public void cancel() {
if (walker!=null) {
walker.cancel();
walker = null;
walker.cancel();
if (incrementalUpdate instanceof IncrementalUpdateJob update) {
update.cancel();
}
}

Expand Down
Loading

0 comments on commit 66f734e

Please sign in to comment.