Skip to content

Commit d8315b1

Browse files
committed
parallelize filling directory entries
fixes #4307
1 parent 0e2c03b commit d8315b1

File tree

4 files changed

+77
-15
lines changed

4 files changed

+77
-15
lines changed

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,12 @@ public final class Configuration {
269269
*/
270270
private int MaxRevisionThreadCount;
271271

272+
/**
273+
* Upper bound for number of threads used for getting directory entries.
274+
* This is total for the whole webapp.
275+
*/
276+
private int MaxDirectoryListingThreadCount;
277+
272278
/**
273279
* If false, do not display listing or projects/repositories on the index page.
274280
*/
@@ -586,6 +592,7 @@ public Configuration() {
586592
//mandoc is default(String)
587593
setMaxSearchThreadCount(2 * Runtime.getRuntime().availableProcessors());
588594
setMaxRevisionThreadCount(Runtime.getRuntime().availableProcessors());
595+
setMaxDirectoryListingThreadCount(Runtime.getRuntime().availableProcessors());
589596
setMergeCommitsEnabled(true);
590597
setMessageLimit(500);
591598
setNavigateWindowEnabled(false);
@@ -1353,6 +1360,14 @@ public void setMaxRevisionThreadCount(int count) {
13531360
this.MaxRevisionThreadCount = count;
13541361
}
13551362

1363+
public int getMaxDirectoryListingThreadCount() {
1364+
return MaxDirectoryListingThreadCount;
1365+
}
1366+
1367+
public void setMaxDirectoryListingThreadCount(int count) {
1368+
this.MaxDirectoryListingThreadCount = count;
1369+
}
1370+
13561371
public boolean isProjectsEnabled() {
13571372
return projectsEnabled;
13581373
}

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public final class RuntimeEnvironment {
103103
private final LazilyInstantiate<IndexerParallelizer> lzIndexerParallelizer;
104104
private final LazilyInstantiate<ExecutorService> lzSearchExecutor;
105105
private final LazilyInstantiate<ExecutorService> lzRevisionExecutor;
106+
private final LazilyInstantiate<ExecutorService> lzDirectoryListingExecutor;
106107
private static final RuntimeEnvironment instance = new RuntimeEnvironment();
107108

108109
private final LazilyInstantiate<SuperIndexSearcherFactory> lzSuperIndexSearcherFactory;
@@ -164,6 +165,7 @@ private RuntimeEnvironment() {
164165
lzIndexerParallelizer = LazilyInstantiate.using(() -> new IndexerParallelizer(this));
165166
lzSearchExecutor = LazilyInstantiate.using(this::newSearchExecutor);
166167
lzRevisionExecutor = LazilyInstantiate.using(this::newRevisionExecutor);
168+
lzDirectoryListingExecutor = LazilyInstantiate.using(this::newDirectoryListingExecutor);
167169
lzSuperIndexSearcherFactory = LazilyInstantiate.using(this::newSuperIndexSearcherFactory);
168170
lzIndexSearcherFactory = LazilyInstantiate.using(this::newIndexSearcherFactory);
169171
}
@@ -227,6 +229,20 @@ public void shutdownRevisionExecutor() throws InterruptedException {
227229
getRevisionExecutor().awaitTermination(getIndexerCommandTimeout(), TimeUnit.SECONDS);
228230
}
229231

232+
public ExecutorService getDirectoryListingExecutor() {
233+
return lzDirectoryListingExecutor.get();
234+
}
235+
236+
private ExecutorService newDirectoryListingExecutor() {
237+
return Executors.newFixedThreadPool(this.getMaxDirectoryListingThreadCount(),
238+
new OpenGrokThreadFactory("directory-listing"));
239+
}
240+
241+
public void shutdownDirectoryListingExecutor() throws InterruptedException {
242+
getDirectoryListingExecutor().shutdownNow();
243+
getDirectoryListingExecutor().awaitTermination(getWebappStartCommandTimeout(), TimeUnit.SECONDS);
244+
}
245+
230246
private SuperIndexSearcherFactory newSuperIndexSearcherFactory() {
231247
return new SuperIndexSearcherFactory();
232248
}
@@ -1388,6 +1404,14 @@ public int getMaxRevisionThreadCount() {
13881404
return syncReadConfiguration(Configuration::getMaxRevisionThreadCount);
13891405
}
13901406

1407+
public int getMaxDirectoryListingThreadCount() {
1408+
return syncReadConfiguration(Configuration::getMaxDirectoryListingThreadCount);
1409+
}
1410+
1411+
public void setMaxDirectoryListingThreadCount(int threadCount) {
1412+
syncWriteConfiguration(threadCount, Configuration::setMaxDirectoryListingThreadCount);
1413+
}
1414+
13911415
public int getCurrentIndexedCollapseThreshold() {
13921416
return syncReadConfiguration(Configuration::getCurrentIndexedCollapseThreshold);
13931417
}

opengrok-indexer/src/main/java/org/opengrok/indexer/history/FileHistoryCache.java

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@
3737
import java.nio.file.Path;
3838
import java.util.ArrayList;
3939
import java.util.HashMap;
40+
import java.util.HashSet;
4041
import java.util.Iterator;
4142
import java.util.List;
4243
import java.util.Map;
4344
import java.util.Set;
4445
import java.util.concurrent.CountDownLatch;
46+
import java.util.concurrent.ExecutorService;
47+
import java.util.concurrent.Future;
4548
import java.util.concurrent.atomic.AtomicInteger;
4649
import java.util.logging.Level;
4750
import java.util.logging.Logger;
@@ -766,32 +769,51 @@ public boolean fillLastHistoryEntries(List<DirectoryEntry> entries) {
766769

767770
boolean ret = true;
768771

772+
Statistics statistics = new Statistics();
773+
774+
final ExecutorService executor = env.getDirectoryListingExecutor();
775+
Set<Future<Boolean>> futures = new HashSet<>();
769776
for (DirectoryEntry directoryEntry : entries) {
770-
try {
771-
File file = directoryEntry.getFile();
772-
if (file.isDirectory()) {
773-
directoryEntry.setDescription("-");
774-
directoryEntry.setDate(null);
775-
continue;
777+
futures.add(executor.submit(() -> {
778+
try {
779+
File file = directoryEntry.getFile();
780+
if (file.isDirectory()) {
781+
directoryEntry.setDescription("-");
782+
directoryEntry.setDate(null);
783+
return true;
784+
}
785+
786+
HistoryEntry historyEntry = getLastHistoryEntry(file);
787+
if (historyEntry != null && historyEntry.getDate() != null) {
788+
directoryEntry.setDescription(historyEntry.getDescription());
789+
directoryEntry.setDate(historyEntry.getDate());
790+
} else {
791+
LOGGER.log(Level.FINE, "cannot get last history entry for ''{0}''",
792+
directoryEntry.getFile());
793+
return false;
794+
}
795+
} catch (CacheException e) {
796+
LOGGER.log(Level.FINER, "cannot get last history entry for ''{0}''", directoryEntry.getFile());
797+
return false;
776798
}
799+
return true;
800+
}));
801+
}
777802

778-
HistoryEntry historyEntry = getLastHistoryEntry(file);
779-
if (historyEntry != null && historyEntry.getDate() != null) {
780-
directoryEntry.setDescription(historyEntry.getDescription());
781-
directoryEntry.setDate(historyEntry.getDate());
782-
} else {
783-
LOGGER.log(Level.FINE, "cannot get last history entry for ''{0}''",
784-
directoryEntry.getFile());
803+
for (Future<Boolean> future : futures) {
804+
try {
805+
if (!future.get()) {
785806
ret = false;
786807
break;
787808
}
788-
} catch (CacheException e) {
789-
LOGGER.log(Level.FINER, "cannot get last history entry for ''{0}''", directoryEntry.getFile());
809+
} catch (Exception e) {
790810
ret = false;
791811
break;
792812
}
793813
}
794814

815+
statistics.report(LOGGER, Level.FINER, "done filling directory entries");
816+
795817
// Enforce the all-or-nothing semantics.
796818
if (!ret) {
797819
entries.forEach(e -> e.setDate(null));

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ public void contextDestroyed(final ServletContextEvent servletContextEvent) {
204204
try {
205205
env.shutdownRevisionExecutor();
206206
env.shutdownSearchExecutor();
207+
env.shutdownDirectoryListingExecutor();
207208
} catch (InterruptedException e) {
208209
LOGGER.log(Level.WARNING, "Could not shutdown revision executor", e);
209210
}

0 commit comments

Comments
 (0)