[libcxx-commits] [libcxx] [libc++] Revert fstream::read optimizations (PR #168894)

Jordan Rupprecht via libcxx-commits libcxx-commits at lists.llvm.org
Thu Nov 20 07:49:04 PST 2025


https://github.com/rupprecht created https://github.com/llvm/llvm-project/pull/168894

This causes various runtime failures, as reported in #168628.

This reverts both #165223 and #167779

>From 27f01c823b3d4fadb83e17c1735125e03fa8df95 Mon Sep 17 00:00:00 2001
From: Jordan Rupprecht <rupprecht at google.com>
Date: Thu, 20 Nov 2025 07:43:36 -0800
Subject: [PATCH 1/2] Revert "[libcxx] Fix xsgetn in basic_filebuf (#167779)"

This reverts commit ea16f7d9dbade0c138e4231aa12c92d91bc15b21.
---
 libcxx/include/fstream | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 90e35740c17cf..b07ca636094af 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -315,14 +315,8 @@ protected:
         traits_type::copy(__str, this->gptr(), __n);
         this->__gbump_ptrdiff(__n);
       }
-      const streamsize __remainder    = __len - __n;
-      const streamsize __buffer_space = this->egptr() - this->eback();
-
-      if (__remainder >= __buffer_space)
-        return std::fread(__str + __n, sizeof(char_type), __remainder, __file_) + __n;
-      else if (__remainder > 0)
-        return basic_streambuf<_CharT, _Traits>::xsgetn(__str + __n, __remainder) + __n;
-      return __n;
+      if (__len - __n >= this->egptr() - this->eback())
+        return std::fread(__str + __n, sizeof(char_type), __len - __n, __file_);
     }
     return basic_streambuf<_CharT, _Traits>::xsgetn(__str, __len);
   }

>From 794c731132114722835a6108d8f3ceb893f29d4b Mon Sep 17 00:00:00 2001
From: Jordan Rupprecht <rupprecht at google.com>
Date: Thu, 20 Nov 2025 07:43:49 -0800
Subject: [PATCH 2/2] Revert "[libc++] Optimize fstream::read (#165223)"

This reverts commit 9b114c5d9aa5e5ccf1aa89d9933c6ffaa1214386.
---
 libcxx/docs/ReleaseNotes/22.rst               |  4 ++--
 libcxx/include/fstream                        | 13 -----------
 .../{fstream.bench.cpp => ofstream.bench.cpp} | 22 ++-----------------
 .../filebuf/traits_mismatch.verify.cpp        |  2 +-
 .../fstreams/traits_mismatch.verify.cpp       |  2 +-
 5 files changed, 6 insertions(+), 37 deletions(-)
 rename libcxx/test/benchmarks/streams/{fstream.bench.cpp => ofstream.bench.cpp} (54%)

diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 7af1351e8cee6..b8e0e9b5a1814 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -67,8 +67,8 @@ Improvements and New Features
   by up to 2.5x
 - The performance of ``erase(iterator, iterator)`` in the unordered containers has been improved by up to 1.9x
 - The performance of ``map::insert_or_assign`` has been improved by up to 2x
-- ``ofstream::write`` and ``ifstream::read`` have been optimized to pass through large reads and writes to system calls
-  directly instead of copying them in chunks.
+- ``ofstream::write`` has been optimized to pass through large strings to system calls directly instead of copying them
+  in chunks into a buffer.
 - Multiple internal types have been refactored to use ``[[no_unique_address]]``, resulting in faster compile times and
   reduced debug information.
 
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index b07ca636094af..1f88d134fe061 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -308,19 +308,6 @@ protected:
     return basic_streambuf<_CharT, _Traits>::xsputn(__str, __len);
   }
 
-  _LIBCPP_HIDE_FROM_ABI_VIRTUAL streamsize xsgetn(char_type* __str, streamsize __len) override {
-    if (__always_noconv_) {
-      const streamsize __n = std::min(this->egptr() - this->gptr(), __len);
-      if (__n != 0) {
-        traits_type::copy(__str, this->gptr(), __n);
-        this->__gbump_ptrdiff(__n);
-      }
-      if (__len - __n >= this->egptr() - this->eback())
-        return std::fread(__str + __n, sizeof(char_type), __len - __n, __file_);
-    }
-    return basic_streambuf<_CharT, _Traits>::xsgetn(__str, __len);
-  }
-
 private:
   char* __extbuf_;
   const char* __extbufnext_;
diff --git a/libcxx/test/benchmarks/streams/fstream.bench.cpp b/libcxx/test/benchmarks/streams/ofstream.bench.cpp
similarity index 54%
rename from libcxx/test/benchmarks/streams/fstream.bench.cpp
rename to libcxx/test/benchmarks/streams/ofstream.bench.cpp
index 3ca1801ca8d03..60606a9d67e2f 100644
--- a/libcxx/test/benchmarks/streams/fstream.bench.cpp
+++ b/libcxx/test/benchmarks/streams/ofstream.bench.cpp
@@ -11,7 +11,7 @@
 
 #include <benchmark/benchmark.h>
 
-static void bm_ofstream_write(benchmark::State& state) {
+static void bm_write(benchmark::State& state) {
   std::vector<char> buffer;
   buffer.resize(16384);
 
@@ -20,24 +20,6 @@ static void bm_ofstream_write(benchmark::State& state) {
   for (auto _ : state)
     stream.write(buffer.data(), buffer.size());
 }
-BENCHMARK(bm_ofstream_write);
-
-static void bm_ifstream_read(benchmark::State& state) {
-  std::vector<char> buffer;
-  buffer.resize(16384);
-
-  std::ofstream gen_testfile("testfile");
-  gen_testfile.write(buffer.data(), buffer.size());
-
-  std::ifstream stream("testfile");
-  assert(stream);
-
-  for (auto _ : state) {
-    stream.read(buffer.data(), buffer.size());
-    benchmark::DoNotOptimize(buffer);
-    stream.seekg(0);
-  }
-}
-BENCHMARK(bm_ifstream_read);
+BENCHMARK(bm_write);
 
 BENCHMARK_MAIN();
diff --git a/libcxx/test/libcxx/input.output/file.streams/fstreams/filebuf/traits_mismatch.verify.cpp b/libcxx/test/libcxx/input.output/file.streams/fstreams/filebuf/traits_mismatch.verify.cpp
index 30e7b66d42325..283adbc057d1e 100644
--- a/libcxx/test/libcxx/input.output/file.streams/fstreams/filebuf/traits_mismatch.verify.cpp
+++ b/libcxx/test/libcxx/input.output/file.streams/fstreams/filebuf/traits_mismatch.verify.cpp
@@ -19,4 +19,4 @@
 
 std::basic_filebuf<char, std::char_traits<wchar_t> > f;
 // expected-error-re@*:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
-// expected-error@*:* 11 {{only virtual member functions can be marked 'override'}}
+// expected-error@*:* 10 {{only virtual member functions can be marked 'override'}}
diff --git a/libcxx/test/libcxx/input.output/file.streams/fstreams/traits_mismatch.verify.cpp b/libcxx/test/libcxx/input.output/file.streams/fstreams/traits_mismatch.verify.cpp
index daafb36f9151a..ba6f3c31d3e34 100644
--- a/libcxx/test/libcxx/input.output/file.streams/fstreams/traits_mismatch.verify.cpp
+++ b/libcxx/test/libcxx/input.output/file.streams/fstreams/traits_mismatch.verify.cpp
@@ -21,7 +21,7 @@ std::basic_fstream<char, std::char_traits<wchar_t> > f;
 // expected-error-re@*:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
 // expected-error-re@*:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
 
-// expected-error@*:* 13 {{only virtual member functions can be marked 'override'}}
+// expected-error@*:* 12 {{only virtual member functions can be marked 'override'}}
 
 // FIXME: As of commit r324062 Clang incorrectly generates a diagnostic about mismatching
 // exception specifications for types which are already invalid for one reason or another.



More information about the libcxx-commits mailing list