aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2017-10-31 17:37:20 +0000
committerRui Ueyama <ruiu@google.com>2017-10-31 17:37:20 +0000
commit153600762f860cb6a8329411a490f86aa18265d1 (patch)
tree027216866b838f791ec9798f42e8ce25467be59e
parent98506f3291d690d957b5e3d89ffc420a9ae48b35 (diff)
[Support] Make the default chunk size of raw_fd_ostream to 1 GiB.
Previously, we call write(2) for each 32767 byte chunk. That is not efficient because Linux can handle much larger write requests. This patch changes the chunk size on Linux to 1 GiB. This patch also changes the default chunks size to SSIZE_MAX. I think that doesn't in practice change this function's behavior on any operating system because SSIZE_MAX on 64-bit machine is unrealistically large, and writing 2 GiB (SSIZE_MAX on 32-bit) on a 32-bit machine by a single call of write(2) is also unrealistic, as the userspace is usually limited to 2 GiB. That said, it is in general a good thing to do because a write larger than SSIZE_MAX is implementation-defined in POSIX. Differential Revision: https://reviews.llvm.org/D39444 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317015 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Support/raw_ostream.cpp23
1 files changed, 12 insertions, 11 deletions
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index d6b958d1844..e0261110308 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -578,24 +578,25 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
assert(FD >= 0 && "File already closed.");
pos += Size;
-#ifndef LLVM_ON_WIN32
+ // The maximum write size is limited to SSIZE_MAX because a write
+ // greater than SSIZE_MAX is implementation-defined in POSIX.
+ // Since SSIZE_MAX is not portable, we use SIZE_MAX >> 1 instead.
+ size_t MaxWriteSize = SIZE_MAX >> 1;
+
#if defined(__linux__)
- bool ShouldWriteInChunks = true;
-#else
- bool ShouldWriteInChunks = false;
-#endif
-#else
+ // It is observed that Linux returns EINVAL for a very large write (>2G).
+ // Make it a reasonably small value.
+ MaxWriteSize = 1024 * 1024 * 1024;
+#elif defined(LLVM_ON_WIN32)
// Writing a large size of output to Windows console returns ENOMEM. It seems
// that, prior to Windows 8, WriteFile() is redirecting to WriteConsole(), and
// the latter has a size limit (66000 bytes or less, depending on heap usage).
- bool ShouldWriteInChunks = !!::_isatty(FD) && !RunningWindows8OrGreater();
+ if (::_isatty(FD) && !RunningWindows8OrGreater())
+ MaxWriteSize = 32767;
#endif
do {
- size_t ChunkSize = Size;
- if (ChunkSize > 32767 && ShouldWriteInChunks)
- ChunkSize = 32767;
-
+ size_t ChunkSize = std::min(Size, MaxWriteSize);
ssize_t ret = ::write(FD, Ptr, ChunkSize);
if (ret < 0) {