make VfsUtilPerformanceTest.PersistentFS_performance_ofManyFilesCreateDelete less dependent of native FS performance

This commit is contained in:
peter
2017-09-20 17:37:38 +02:00
parent 79d0701b57
commit 424e928eb9
2 changed files with 65 additions and 41 deletions
@@ -30,10 +30,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.*;
/**
* @author max
@@ -65,14 +62,23 @@ public class TempFileSystem extends LocalFileSystemBase {
return parentItem.findChild(file.getName());
}
@NotNull
private FSDir convertDirectory(@NotNull VirtualFile parent) {
final FSItem fsItem = convert(parent);
if (fsItem == null) {
FSRecords.invalidateCaches();
throw new IllegalStateException("cannot find parent directory: " + parent.getPath());
}
assert fsItem.isDirectory() : "parent is not a directory: " + parent.getPath();
return (FSDir)fsItem;
}
@Override
@NotNull
public VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile parent, @NotNull String dir) throws IOException {
final FSItem fsItem = convert(parent);
assert fsItem != null && fsItem.isDirectory();
final FSDir fsDir = (FSDir)fsItem;
final FSItem existingDir = fsDir.findChild(dir);
FSDir fsDir = convertDirectory(parent);
FSItem existingDir = fsDir.findChild(dir);
if (existingDir == null) {
fsDir.addChild(new FSDir(fsDir, dir));
}
@@ -85,15 +91,8 @@ public class TempFileSystem extends LocalFileSystemBase {
@NotNull
@Override
public VirtualFile createChildFile(Object requestor, @NotNull VirtualFile parent, @NotNull String file) throws IOException {
final FSItem fsItem = convert(parent);
if (fsItem == null) {
FSRecords.invalidateCaches();
throw new IllegalStateException("cannot find parent directory: " + parent.getPath());
}
assert fsItem.isDirectory() : "parent is not a directory: " + parent.getPath();
final FSDir fsDir = (FSDir)fsItem;
public VirtualFile createChildFile(Object requestor, @NotNull VirtualFile parent, @NotNull String file) {
FSDir fsDir = convertDirectory(parent);
assert fsDir.findChild(file) == null : "File " + file + " already exists in " + parent.getPath();
fsDir.addChild(new FSFile(fsDir, file));
@@ -101,6 +100,11 @@ public class TempFileSystem extends LocalFileSystemBase {
return new FakeVirtualFile(parent, file);
}
@Nullable public VirtualFile findModelChild(@NotNull VirtualFile parent, @NotNull String name) {
FSItem child = convertDirectory(parent).findChild(name);
return child == null ? null : new FakeVirtualFile(parent, name);
}
@NotNull
@Override
public VirtualFile copyFile(Object requestor,
@@ -111,7 +115,7 @@ public class TempFileSystem extends LocalFileSystemBase {
}
@Override
public void deleteFile(final Object requestor, @NotNull final VirtualFile file) throws IOException {
public void deleteFile(final Object requestor, @NotNull final VirtualFile file) {
final FSItem fsItem = convert(file);
if (fsItem == null) {
FSRecords.invalidateCaches();
@@ -137,7 +141,7 @@ public class TempFileSystem extends LocalFileSystemBase {
}
@Override
public void renameFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final String newName) throws IOException {
public void renameFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final String newName) {
final FSItem fsItem = convert(file);
assert fsItem != null;
fsItem.setName(newName);
@@ -195,7 +199,7 @@ public class TempFileSystem extends LocalFileSystemBase {
}
@Override
public void setWritable(@NotNull final VirtualFile file, final boolean writableFlag) throws IOException {
public void setWritable(@NotNull final VirtualFile file, final boolean writableFlag) {
final FSItem fsItem = convert(file);
assert fsItem != null;
fsItem.myWritable = writableFlag;
@@ -266,7 +270,9 @@ public class TempFileSystem extends LocalFileSystemBase {
}
void setName(@NotNull String name) {
myParent.myChildren.remove(myName);
myName = name;
myParent.myChildren.put(name, this);
}
public FSDir getParent() {
@@ -285,7 +291,7 @@ public class TempFileSystem extends LocalFileSystemBase {
}
private static class FSDir extends FSItem {
private final List<FSItem> myChildren = new ArrayList<>();
private final Map<String, FSItem> myChildren = new LinkedHashMap<>();
FSDir(@Nullable FSDir parent, @NotNull String name) {
super(parent, name);
@@ -294,13 +300,7 @@ public class TempFileSystem extends LocalFileSystemBase {
@Override
@Nullable
public FSItem findChild(final String name) {
for (FSItem child : myChildren) {
if (name.equals(child.myName)) {
return child;
}
}
return null;
return myChildren.get(name);
}
@Override
@@ -309,24 +309,20 @@ public class TempFileSystem extends LocalFileSystemBase {
}
void addChild(@NotNull FSItem item) {
myChildren.add(item);
myChildren.put(item.myName, item);
}
void removeChild(@NotNull FSItem fsItem) {
if (fsItem.myName.equals("src") && getParent() == null) {
throw new RuntimeException("removing src directory");
}
myChildren.remove(fsItem);
myChildren.remove(fsItem.myName);
}
@NotNull
@Override
public String[] list() {
String[] names = ArrayUtil.newStringArray(myChildren.size());
for (int i = 0; i < names.length; i++) {
names[i] = myChildren.get(i).myName;
}
return names;
return ArrayUtil.toStringArray(myChildren.keySet());
}
}
@@ -17,6 +17,8 @@ package com.intellij.openapi.vfs;
import com.intellij.concurrency.JobLauncher;
import com.intellij.concurrency.JobSchedulerImpl;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Disposer;
@@ -24,6 +26,7 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.IoTestUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
@@ -43,6 +46,7 @@ import com.intellij.util.ThrowableRunnable;
import com.intellij.util.TimeoutUtil;
import com.intellij.util.ui.UIUtil;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import org.junit.Rule;
import org.junit.Test;
@@ -279,10 +283,11 @@ public class VfsUtilPerformanceTest extends BareTestFixtureTestCase {
}
@Test
public void PersistentFS_performance_ofManyFilesCreateDelete() throws Exception {
public void PersistentFS_performance_ofManyFilesCreateDelete() {
int N = 100_000;
List<VFileEvent> events = new ArrayList<>(N);
VirtualDirectoryImpl temp = (VirtualDirectoryImpl)PlatformTestUtil.notNull(LocalFileSystem.getInstance().findFileByIoFile(myTempDir.newFolder()));
VirtualDirectoryImpl temp = createTempFsDirectory();
UIUtil.invokeAndWaitIfNeeded((Runnable)() -> {
PlatformTestUtil.startPerformanceTest("many files creations", 10000, () -> {
assertEquals(N, events.size());
@@ -296,7 +301,7 @@ public class VfsUtilPerformanceTest extends BareTestFixtureTestCase {
processEvents(events);
}
eventsForCreating(events, N, temp);
assertEquals(N, new File(temp.getPath()).listFiles().length); // do not call getChildren which caches everything
assertEquals(N, TempFileSystem.getInstance().list(temp).length); // do not call getChildren which caches everything
})
.assertTiming();
@@ -315,22 +320,45 @@ public class VfsUtilPerformanceTest extends BareTestFixtureTestCase {
processEvents(events);
}
eventsForDeleting(events, temp);
assertEquals(N, new File(temp.getPath()).listFiles().length); // do not call getChildren which caches everything
assertEquals(N, TempFileSystem.getInstance().list(temp).length); // do not call getChildren which caches everything
})
.assertTiming();
}
);
}
private VirtualDirectoryImpl createTempFsDirectory() {
VirtualDirectoryImpl temp = new WriteAction<VirtualDirectoryImpl>(){
@Override
protected void run(@NotNull Result<VirtualDirectoryImpl> result) throws Throwable {
result.setResult((VirtualDirectoryImpl)TempFileSystem.getInstance().findFileByPath("/").createChildDirectory(this, "temp"));
}
}.execute().getResultObject();
Disposer.register(getTestRootDisposable(), () -> {
try {
WriteAction.run(() -> temp.delete(this));
}
catch (IOException e) {
throw new RuntimeException();
}
});
return temp;
}
private static void processEvents(List<VFileEvent> events) {
WriteCommandAction.runWriteCommandAction(null, () -> PersistentFS.getInstance().processEvents(events));
}
private void eventsForCreating(List<VFileEvent> events, int N, VirtualDirectoryImpl temp) {
events.clear();
TempFileSystem fs = TempFileSystem.getInstance();
IntStream.range(0, N)
.mapToObj(i -> new VFileCreateEvent(this, temp, i + ".txt", false, false))
.peek(event -> FileUtil.createIfDoesntExist(new File(event.getPath())))
.peek(event -> {
if (fs.findModelChild(temp, event.getChildName()) == null) {
fs.createChildFile(this, temp, event.getChildName());
}
})
.forEach(events::add);
List<CharSequence> names = events.stream().map(e -> ((VFileCreateEvent)e).getChildName()).collect(Collectors.toList());
temp.removeChildren(new TIntHashSet(), names);