- removed registry flag idea.concurrent.scanning.files.to.index (assuming it is always true)
- removed TaskQueue class and its usages since it was previous generation of concurrent
- encapsulate access to myChangedFilesToUpdate
This commit is contained in:
Maxim.Mossienko
2016-11-04 13:50:20 +01:00
parent 42544cb766
commit 0d58978b41
4 changed files with 20 additions and 161 deletions
@@ -38,7 +38,6 @@ import com.intellij.openapi.roots.*;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
@@ -279,8 +278,7 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater
public static void invokeConcurrentlyIfPossible(final List<Runnable> tasks) {
if (tasks.size() == 1 ||
ApplicationManager.getApplication().isWriteAccessAllowed() ||
!Registry.is("idea.concurrent.scanning.files.to.index")) {
ApplicationManager.getApplication().isWriteAccessAllowed()) {
for(Runnable r:tasks) r.run();
return;
}
@@ -644,7 +644,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
@Nullable GlobalSearchScope filter,
@Nullable VirtualFile restrictedFile) {
ProgressManager.checkCanceled();
myContentlessIndicesUpdateQueue.ensureUpToDate(); // some contentful indices depends on contentless ones
ApplicationManager.getApplication().assertReadAccessAllowed();
if (!needsFileContentLoading(indexId)) {
return; //indexed eagerly in foreground while building unindexed file list
@@ -921,8 +920,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
private static final Key<SoftReference<ProjectIndexableFilesFilter>> ourProjectFilesSetKey = Key.create("projectFiles");
void filesUpdateEnumerationFinished() {
myContentlessIndicesUpdateQueue.ensureUpToDate();
myContentlessIndicesUpdateQueue.signalUpdateEnd();
}
@TestOnly
@@ -971,8 +968,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
void filesUpdateStarted(Project project) {
myContentlessIndicesUpdateQueue.signalUpdateStart();
myContentlessIndicesUpdateQueue.ensureUpToDate();
myProjectsBeingUpdated.add(project);
++myFilesModCount;
}
@@ -1353,8 +1348,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
return true;
}
private final TaskQueue myContentlessIndicesUpdateQueue = new TaskQueue(10000);
private final StorageGuard myStorageLock = new StorageGuard();
private volatile boolean myPreviousDataBufferingState;
private final Object myBufferingStateUpdateLock = new Object();
@@ -1444,7 +1437,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
int getChangedFileCount() {
return myChangedFilesCollector.getAllFilesToUpdate().size();
return myChangedFilesCollector.getChangedFileCount();
}
@NotNull
@@ -1467,14 +1460,14 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
public boolean isFileUpToDate(VirtualFile file) {
return !myChangedFilesCollector.myFilesToUpdate.containsKey(Math.abs(getIdMaskingNonIdBasedFile(file)));
return !myChangedFilesCollector.isScheduledForUpdate(file);
}
// caller is responsible to ensure no concurrent same document processing
void processRefreshedFile(@Nullable Project project, @NotNull final com.intellij.ide.caches.FileContent fileContent) {
// ProcessCanceledException will cause re-adding the file to processing list
final VirtualFile file = fileContent.getVirtualFile();
if (myChangedFilesCollector.myFilesToUpdate.containsKey(Math.abs(getIdMaskingNonIdBasedFile(file)))) {
if (myChangedFilesCollector.isScheduledForUpdate(file)) {
indexFileContent(project, fileContent);
}
}
@@ -1503,7 +1496,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
IndexingStamp.flushCache(fileId);
}
myChangedFilesCollector.myFilesToUpdate.remove(fileId);
myChangedFilesCollector.removeFileIdFromFilesScheduledForUpdate(fileId);
}
private void doIndexFileContent(@Nullable Project project, @NotNull final com.intellij.ide.caches.FileContent content) {
@@ -1657,12 +1650,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
private void scheduleUpdate(@NotNull final ID<?, ?> indexId, final Computable<Boolean> update, VirtualFile file, final int inputId, final boolean hasContent) {
if (myNotRequiringContentIndices.contains(indexId) && !Registry.is("idea.concurrent.scanning.files.to.index")) {
myContentlessIndicesUpdateQueue.submit(
() -> updateWithBufferingEnabled(update),
() -> indexedStampUpdate(indexId, file, inputId, hasContent));
}
else if (updateWithBufferingEnabled(update)) {
if (updateWithBufferingEnabled(update)) {
AccessToken accessToken = ReadAction.start();
try {
indexedStampUpdate(indexId, file, inputId, hasContent);
@@ -1873,6 +1861,10 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
}
private void removeFileIdFromFilesScheduledForUpdate(int fileId) {
myFilesToUpdate.remove(fileId);
}
Collection<VirtualFile> getAllFilesToUpdate() {
if (myFilesToUpdate.isEmpty()) {
return Collections.emptyList();
@@ -1882,9 +1874,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
@Override
public void before(@NotNull List<? extends VFileEvent> events) {
myContentlessIndicesUpdateQueue.signalUpdateStart();
myContentlessIndicesUpdateQueue.ensureUpToDate();
for (VFileEvent event : events) {
if (memoryStorageCleaningNeeded(event)) {
cleanupMemoryStorage();
@@ -1903,10 +1892,15 @@ public class FileBasedIndexImpl extends FileBasedIndex {
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
myContentlessIndicesUpdateQueue.ensureUpToDate();
super.after(events);
myContentlessIndicesUpdateQueue.signalUpdateEnd();
}
public boolean isScheduledForUpdate(VirtualFile file) {
return myFilesToUpdate.containsKey(Math.abs(getIdMaskingNonIdBasedFile(file)));
}
public int getChangedFileCount() {
return myFilesToUpdate.size();
}
}
@@ -2113,9 +2107,9 @@ public class FileBasedIndexImpl extends FileBasedIndex {
final int fileId = Math.abs(getIdMaskingNonIdBasedFile(file));
if (!file.isValid()) {
removeDataFromIndicesForFile(fileId);
myChangedFilesCollector.myFilesToUpdate.remove(fileId);
myChangedFilesCollector.removeFileIdFromFilesScheduledForUpdate(fileId);
} else if (getIndexableSetForFile(file) == null) { // todo remove data from indices for removed
myChangedFilesCollector.myFilesToUpdate.remove(fileId);
myChangedFilesCollector.removeFileIdFromFilesScheduledForUpdate(fileId);
}
}
@@ -1,132 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.indexing;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.registry.Registry;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by Maxim.Mossienko on 7/18/13.
*/
class TaskQueue {
private final AtomicInteger myDoWorkRequest = new AtomicInteger();
private final AtomicInteger myUpdatesCount = new AtomicInteger();
private final BlockingQueue<Runnable> myPendingWriteRequestsQueue = new LinkedBlockingQueue<>();
private final BlockingQueue<Runnable> myTimestampUpdates = new LinkedBlockingQueue<>();
private final int myLimit;
private final int myStealLimit;
private final int myTimeStampUpdateSizeLimit;
public TaskQueue(int limit) {
myLimit = limit;
myStealLimit = Math.max(1, (int)(limit * 0.01));
myTimeStampUpdateSizeLimit = 32;
}
void submit(@NotNull final Computable<Boolean> update, @NotNull final Runnable successRunnable) {
int currentTasksCount = myUpdatesCount.incrementAndGet();
myPendingWriteRequestsQueue.add(() -> {
try {
Boolean result = update.compute();
if (result == Boolean.TRUE) {
myTimestampUpdates.add(successRunnable);
}
}
finally {
myUpdatesCount.decrementAndGet();
}
});
if (currentTasksCount > myLimit) {
Runnable runnable = myPendingWriteRequestsQueue.poll();
int processed = 0;
while (runnable != null) {
runnable.run();
if (++processed == myStealLimit) break;
runnable = myPendingWriteRequestsQueue.poll();
}
}
int size = myTimestampUpdates.size();
if (size > myTimeStampUpdateSizeLimit) {
applyTimeStamps(size);
}
}
private void applyTimeStamps(final int max) {
final Runnable runnable = myTimestampUpdates.poll();
if (runnable == null) return;
ApplicationManager.getApplication().runReadAction(() -> {
int updates = 0;
for (Runnable r = runnable; r != null; r = myTimestampUpdates.poll()) {
r.run();
if (++updates == max) break;
}
});
}
public void ensureUpToDate() {
try {
if (Registry.is("idea.concurrent.scanning.files.to.index")) return;
while(myUpdatesCount.get() > 0) {
Runnable runnable = myPendingWriteRequestsQueue.poll(10, TimeUnit.MILLISECONDS);
if (runnable != null) runnable.run();
}
applyTimeStamps(Integer.MAX_VALUE);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public void signalUpdateEnd() {
myDoWorkRequest.decrementAndGet();
}
public void signalUpdateStart() {
int workRequests = myDoWorkRequest.getAndIncrement();
if (workRequests == 0) {
if(Registry.is("idea.concurrent.scanning.files.to.index")) return;
myDoWorkRequest.incrementAndGet();
// we have 3 content independent indices but only one of them is heavy IO bound so there is no need in more than one thread
ApplicationManager.getApplication().executeOnPooledThread(() -> {
try {
while(true) {
Runnable runnable = myPendingWriteRequestsQueue.poll(2000, TimeUnit.MILLISECONDS);
if (runnable != null) {
runnable.run();
} else {
// we have no work for 2s and there is no currently running updates
if(myDoWorkRequest.compareAndSet(1, 0)) {
break;
}
}
}
}
catch (InterruptedException ignore) {}
});
}
}
}
@@ -790,7 +790,6 @@ rubymine.rails.console.use.spring=false
ruby.chef.foodcritic.timeout=150
search.everywhere.pattern.checking=true
search.everywhere.pattern.checking.description=Avoid searching classes and symbols if pattern contains only one dot
idea.concurrent.scanning.files.to.index=true
welcome.screen.project.grouping.enabled=true
welcome.screen.project.grouping.enabled.description=Allows to group recent projects