IDEA-342836 Speed up build on Maven+WSL by using fewer system calls

A common anti-pattern is to check that some file exists before doing any operation with the file. The approach is wrong with two reasons:
* The check for the file existence implies at least one additional system call. System calls are expensive in general and are absurdly expensive for WSL file system.
* The file still may be deleted by an external process after the existence check but before the handling. So, such approach sometimes simply doesn't work as expected.

`java.nio.file.Files.exists` is especially slow on Windows, because it tries to create the file under the hood. See `sun.nio.fs.WindowsFileSystemProvider.checkReadAccess`.

This commit removes the unnecessary `Files.exist`. Instead, the code invokes the intended system calls directly, but the code is ready to catch and handle `FileNotFoundException`.

On my machine, the change helped to reduce the total time of execution of `com.intellij.compiler.server.WslBuildCommandLineBuilder#copyPathToTargetIfRequired` from 129 seconds to 3 seconds.

GitOrigin-RevId: d7093e28c6230bcc3c315b00acaf53f6ee20f28f
This commit is contained in:
Vladimir Lagunov
2024-01-11 19:41:28 +01:00
committed by intellij-monorepo-bot
parent c85128bba8
commit 42cb20b032

View File

@@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.api.GlobalOptions;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.charset.Charset;
@@ -127,7 +128,13 @@ final class WslBuildCommandLineBuilder implements BuildCommandLineBuilder {
Path targetFile = myHostClasspathDirectory.resolve(path.getFileName());
try {
FileTime originalFileTimestamp = Files.getLastModifiedTime(path);
FileTime targetFileTimestamp = Files.exists(targetFile) ? Files.getLastModifiedTime(targetFile) : null;
FileTime targetFileTimestamp;
try {
targetFileTimestamp = Files.getLastModifiedTime(targetFile);
}
catch (FileNotFoundException ignored) {
targetFileTimestamp = null;
}
if (targetFileTimestamp == null || targetFileTimestamp.compareTo(originalFileTimestamp) < 0) {
FileUtil.copyFileOrDir(path.toFile(), targetFile.toFile());
}