Skip to content

Commit fb53154

Browse files
author
Vladimir Kotal
authored
make getDiffData() parallel (#2955)
fixes #2953
1 parent 30bbb48 commit fb53154

File tree

4 files changed

+65
-4
lines changed

4 files changed

+65
-4
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/configuration/Configuration.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,16 @@ public final class Configuration {
266266

267267
/**
268268
* Upper bound for number of threads used for performing multi-project
269-
* searches. This is total for the whole webapp/CLI utility.
269+
* searches. This is total for the whole webapp.
270270
*/
271271
private int MaxSearchThreadCount;
272272

273+
/**
274+
* Upper bound for number of threads used for getting revision contents.
275+
* This is total for the whole webapp.
276+
*/
277+
private int MaxRevisionThreadCount;
278+
273279
/**
274280
* If false, do not display listing or projects/repositories on the index page.
275281
*/
@@ -470,6 +476,7 @@ public Configuration() {
470476
//luceneLocking default is OFF
471477
//mandoc is default(String)
472478
setMaxSearchThreadCount(2 * Runtime.getRuntime().availableProcessors());
479+
setMaxRevisionThreadCount(Runtime.getRuntime().availableProcessors());
473480
setMessageLimit(500);
474481
setNavigateWindowEnabled(false);
475482
setOptimizeDatabase(true);
@@ -1222,7 +1229,15 @@ public int getMaxSearchThreadCount() {
12221229
public void setMaxSearchThreadCount(int count) {
12231230
this.MaxSearchThreadCount = count;
12241231
}
1225-
1232+
1233+
public int getMaxRevisionThreadCount() {
1234+
return MaxRevisionThreadCount;
1235+
}
1236+
1237+
public void setMaxRevisionThreadCount(int count) {
1238+
this.MaxRevisionThreadCount = count;
1239+
}
1240+
12261241
public boolean isProjectsEnabled() {
12271242
return projectsEnabled;
12281243
}

opengrok-indexer/src/main/java/org/opengrok/indexer/configuration/RuntimeEnvironment.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import java.util.concurrent.ExecutorService;
4444
import java.util.concurrent.Executors;
4545
import java.util.concurrent.ThreadFactory;
46+
import java.util.concurrent.TimeUnit;
4647
import java.util.concurrent.locks.Lock;
4748
import java.util.concurrent.locks.ReentrantReadWriteLock;
4849
import java.util.logging.Level;
@@ -57,6 +58,7 @@
5758
import org.apache.lucene.store.AlreadyClosedException;
5859
import org.apache.lucene.store.Directory;
5960
import org.apache.lucene.store.FSDirectory;
61+
import org.apache.lucene.util.NamedThreadFactory;
6062
import org.opengrok.indexer.authorization.AuthorizationFramework;
6163
import org.opengrok.indexer.authorization.AuthorizationStack;
6264
import org.opengrok.indexer.history.HistoryGuru;
@@ -91,6 +93,7 @@ public final class RuntimeEnvironment {
9193
private final ReentrantReadWriteLock configLock;
9294
private final LazilyInstantiate<IndexerParallelizer> lzIndexerParallelizer;
9395
private final LazilyInstantiate<ExecutorService> lzSearchExecutor;
96+
private final LazilyInstantiate<ExecutorService> lzRevisionExecutor;
9497
private static final RuntimeEnvironment instance = new RuntimeEnvironment();
9598

9699
private final Map<Project, List<RepositoryInfo>> repository_map = new ConcurrentHashMap<>();
@@ -129,6 +132,7 @@ private RuntimeEnvironment() {
129132
lzIndexerParallelizer = LazilyInstantiate.using(() ->
130133
new IndexerParallelizer(this));
131134
lzSearchExecutor = LazilyInstantiate.using(() -> newSearchExecutor());
135+
lzRevisionExecutor = LazilyInstantiate.using(() -> newRevisionExecutor());
132136
}
133137

134138
// Instance of authorization framework and its lock.
@@ -153,6 +157,20 @@ public Thread newThread(Runnable runnable) {
153157
});
154158
}
155159

160+
public ExecutorService getRevisionExecutor() {
161+
return lzRevisionExecutor.get();
162+
}
163+
164+
private ExecutorService newRevisionExecutor() {
165+
return Executors.newFixedThreadPool(this.getMaxRevisionThreadCount(),
166+
new NamedThreadFactory("get-revision"));
167+
}
168+
169+
public void shutdownRevisionExecutor() throws InterruptedException {
170+
getRevisionExecutor().shutdownNow();
171+
getRevisionExecutor().awaitTermination(getCommandTimeout(), TimeUnit.SECONDS);
172+
}
173+
156174
/**
157175
* Get the one and only instance of the RuntimeEnvironment.
158176
*
@@ -1298,6 +1316,14 @@ public int getMaxSearchThreadCount() {
12981316
return (int) getConfigurationValue("maxSearchThreadCount");
12991317
}
13001318

1319+
public void setMaxRevisionThreadCount(int count) {
1320+
setConfigurationValue("maxRevisionThreadCount", count);
1321+
}
1322+
1323+
public int getMaxRevisionThreadCount() {
1324+
return (int) getConfigurationValue("maxRevisionThreadCount");
1325+
}
1326+
13011327
public int getCurrentIndexedCollapseThreshold() {
13021328
return (int) getConfigurationValue("currentIndexedCollapseThreshold");
13031329
}

opengrok-indexer/src/main/java/org/opengrok/indexer/web/PageConfig.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
import java.util.Set;
5050
import java.util.SortedSet;
5151
import java.util.TreeSet;
52+
import java.util.concurrent.ExecutorService;
53+
import java.util.concurrent.Future;
5254
import java.util.logging.Level;
5355
import java.util.logging.Logger;
5456
import java.util.regex.Pattern;
@@ -58,6 +60,7 @@
5860
import javax.servlet.http.HttpServletRequest;
5961
import javax.servlet.http.HttpServletResponse;
6062
import javax.ws.rs.core.HttpHeaders;
63+
6164
import org.opengrok.indexer.Info;
6265
import org.opengrok.indexer.analysis.AbstractAnalyzer;
6366
import org.opengrok.indexer.analysis.AnalyzerGuru;
@@ -148,6 +151,8 @@ public final class PageConfig {
148151
private static final String ATTR_NAME = PageConfig.class.getCanonicalName();
149152
private HttpServletRequest req;
150153

154+
private ExecutorService executor;
155+
151156
/**
152157
* Sets current request's attribute.
153158
*
@@ -255,9 +260,18 @@ public DiffData getDiffData() {
255260
InputStream[] in = new InputStream[2];
256261
try {
257262
// Get input stream for both older and newer file.
263+
ExecutorService executor = this.executor;
264+
Future<?>[] future = new Future<?>[2];
258265
for (int i = 0; i < 2; i++) {
259266
File f = new File(srcRoot + filepath[i]);
260-
in[i] = HistoryGuru.getInstance().getRevision(f.getParent(), f.getName(), data.rev[i]);
267+
final String revision = data.rev[i];
268+
future[i] = executor.submit(() -> HistoryGuru.getInstance().
269+
getRevision(f.getParent(), f.getName(), revision));
270+
}
271+
272+
for (int i = 0; i < 2; i++) {
273+
// The Executor used by given repository will enforce the timeout.
274+
in[i] = (InputStream) future[i].get();
261275
if (in[i] == null) {
262276
data.errorMsg = "Unable to get revision "
263277
+ Util.htmlize(data.rev[i]) + " for file: "
@@ -287,7 +301,7 @@ public DiffData getDiffData() {
287301
ArrayList<String> lines = new ArrayList<>();
288302
Project p = getProject();
289303
for (int i = 0; i < 2; i++) {
290-
// SRCROOT is read with UTF-8 as a default.
304+
// All files under source root are read with UTF-8 as a default.
291305
try (BufferedReader br = new BufferedReader(
292306
ExpandTabsReader.wrap(IOUtils.createBOMStrippedReader(
293307
in[i], StandardCharsets.UTF_8.name()), p))) {
@@ -1530,6 +1544,7 @@ public static PageConfig get(HttpServletRequest request) {
15301544
private PageConfig(HttpServletRequest req) {
15311545
this.req = req;
15321546
this.authFramework = RuntimeEnvironment.getInstance().getAuthorizationFramework();
1547+
this.executor = RuntimeEnvironment.getInstance().getRevisionExecutor();
15331548
}
15341549

15351550
/**

opengrok-web/src/main/java/org/opengrok/web/WebappListener.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ public void contextDestroyed(final ServletContextEvent servletContextEvent) {
114114
env.getIndexerParallelizer().bounce();
115115
env.watchDog.stop();
116116
env.stopExpirationTimer();
117+
try {
118+
env.shutdownRevisionExecutor();
119+
} catch (InterruptedException e) {
120+
LOGGER.log(Level.WARNING, "Could not shutdown revision executor", e);
121+
}
117122
try {
118123
saveStatistics();
119124
} catch (IOException ex) {

0 commit comments

Comments
 (0)