summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2021-01-26 16:01:36 -0800
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2021-04-08 16:26:35 -0700
commit429088b9e214b2f39f6063a6b3639560fc7db47b (patch)
treebe73669c2b9eb26017bf129158980fa1c8bbac3f
parent38b106f6815716db4757a813d28ba4649d083c14 (diff)
downloadllvm-429088b9e214b2f39f6063a6b3639560fc7db47b.tar.gz
Support: Extract fs::resize_file_before_mapping_readwrite from FileOutputBuffer
Add a variant of `fs::resize_file` for use immediately before opening a file with `mapped_file_region::readwrite`. On Windows, `_chsize` (`ftruncate`) is slow, but `CreateFileMapping` (`mmap`) automatically extends the file so the call to `fs::resize_file` can be skipped. This optimization was added to `FileOutputBuffer` in da9bc2e56d5a5c6332a9def1a0065eb399182b93; this commit just extracts the logic out and adds a unit test. Differential Revision: https://reviews.llvm.org/D95490
-rw-r--r--llvm/include/llvm/Support/FileSystem.h15
-rw-r--r--llvm/lib/Support/FileOutputBuffer.cpp9
-rw-r--r--llvm/unittests/Support/Path.cpp28
3 files changed, 43 insertions, 9 deletions
diff --git a/llvm/include/llvm/Support/FileSystem.h b/llvm/include/llvm/Support/FileSystem.h
index 2ed7d87690cb..da3627721ebd 100644
--- a/llvm/include/llvm/Support/FileSystem.h
+++ b/llvm/include/llvm/Support/FileSystem.h
@@ -411,6 +411,21 @@ std::error_code copy_file(const Twine &From, int ToFD);
/// platform-specific error_code.
std::error_code resize_file(int FD, uint64_t Size);
+/// Resize \p FD to \p Size before mapping \a mapped_file_region::readwrite. On
+/// non-Windows, this calls \a resize_file(). On Windows, this is a no-op,
+/// since the subsequent mapping (via \c CreateFileMapping) automatically
+/// extends the file.
+inline std::error_code resize_file_before_mapping_readwrite(int FD,
+ uint64_t Size) {
+#ifdef _WIN32
+ (void)FD;
+ (void)Size;
+ return std::error_code();
+#else
+ return resize_file(FD, Size);
+#endif
+}
+
/// Compute an MD5 hash of a file's contents.
///
/// @param FD Input file descriptor.
diff --git a/llvm/lib/Support/FileOutputBuffer.cpp b/llvm/lib/Support/FileOutputBuffer.cpp
index 3342682270dc..6d2125802f25 100644
--- a/llvm/lib/Support/FileOutputBuffer.cpp
+++ b/llvm/lib/Support/FileOutputBuffer.cpp
@@ -132,17 +132,10 @@ createOnDiskBuffer(StringRef Path, size_t Size, unsigned Mode) {
return FileOrErr.takeError();
fs::TempFile File = std::move(*FileOrErr);
-#ifndef _WIN32
- // On Windows, CreateFileMapping (the mmap function on Windows)
- // automatically extends the underlying file. We don't need to
- // extend the file beforehand. _chsize (ftruncate on Windows) is
- // pretty slow just like it writes specified amount of bytes,
- // so we should avoid calling that function.
- if (auto EC = fs::resize_file(File.FD, Size)) {
+ if (auto EC = fs::resize_file_before_mapping_readwrite(File.FD, Size)) {
consumeError(File.discard());
return errorCodeToError(EC);
}
-#endif
// Mmap it.
std::error_code EC;
diff --git a/llvm/unittests/Support/Path.cpp b/llvm/unittests/Support/Path.cpp
index 35b41092fdda..6615d2f2806f 100644
--- a/llvm/unittests/Support/Path.cpp
+++ b/llvm/unittests/Support/Path.cpp
@@ -1289,6 +1289,31 @@ TEST_F(FileSystemTest, Resize) {
ASSERT_NO_ERROR(fs::remove(TempPath));
}
+TEST_F(FileSystemTest, ResizeBeforeMapping) {
+ // Create a temp file.
+ int FD;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath));
+ ASSERT_NO_ERROR(fs::resize_file_before_mapping_readwrite(FD, 123));
+
+ // Map in temp file. On Windows, fs::resize_file_before_mapping_readwrite is
+ // a no-op and the mapping itself will resize the file.
+ std::error_code EC;
+ {
+ fs::mapped_file_region mfr(fs::convertFDToNativeFile(FD),
+ fs::mapped_file_region::readwrite, 123, 0, EC);
+ ASSERT_NO_ERROR(EC);
+ // Unmap temp file
+ }
+
+ // Check the size.
+ fs::file_status Status;
+ ASSERT_NO_ERROR(fs::status(FD, Status));
+ ASSERT_EQ(Status.getSize(), 123U);
+ ::close(FD);
+ ASSERT_NO_ERROR(fs::remove(TempPath));
+}
+
TEST_F(FileSystemTest, MD5) {
int FD;
SmallString<64> TempPath;
@@ -1310,7 +1335,8 @@ TEST_F(FileSystemTest, FileMapping) {
ASSERT_NO_ERROR(
fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath));
unsigned Size = 4096;
- ASSERT_NO_ERROR(fs::resize_file(FileDescriptor, Size));
+ ASSERT_NO_ERROR(
+ fs::resize_file_before_mapping_readwrite(FileDescriptor, Size));
// Map in temp file and add some content
std::error_code EC;