Skip to content

Commit 87acdbe

Browse files
committed
[libc++] Optimize ofstream::write
1 parent 455b3d6 commit 87acdbe

File tree

6 files changed

+42
-11
lines changed

6 files changed

+42
-11
lines changed

libcxx/docs/ReleaseNotes/20.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ Improvements and New Features
111111
std::errc::not_a_directory``, or use ``err.default_error_condition()`` to map to an ``error_condition``, and then test
112112
its ``value()`` and ``category()``.
113113

114+
- ``ofstream::write`` has been optimized to pass through large strings to system calls directly instead of copying them
115+
in chunks into a buffer.
116+
114117
Deprecations and Removals
115118
-------------------------
116119

libcxx/include/fstream

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ _LIBCPP_EXPORTED_FROM_ABI void* __filebuf_windows_native_handle(FILE* __file) no
232232

233233
template <class _CharT, class _Traits>
234234
class _LIBCPP_TEMPLATE_VIS basic_filebuf : public basic_streambuf<_CharT, _Traits> {
235+
using __base _LIBCPP_NODEBUG = basic_streambuf<_CharT, _Traits>;
236+
235237
public:
236238
typedef _CharT char_type;
237239
typedef _Traits traits_type;
@@ -304,6 +306,16 @@ protected:
304306
int sync() override;
305307
void imbue(const locale& __loc) override;
306308

309+
_LIBCPP_HIDE_FROM_ABI_VIRTUAL streamsize xsputn(const char_type* __str, streamsize __len) override {
310+
if (__always_noconv_ && __len >= (this->epptr() - this->pbase())) {
311+
if (traits_type::eq_int_type(overflow(), traits_type::eof()))
312+
return 0;
313+
314+
return std::fwrite(__str, sizeof(char_type), __len, __file_);
315+
}
316+
return __base::xsputn(__str, __len);
317+
}
318+
307319
private:
308320
char* __extbuf_;
309321
const char* __extbufnext_;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <fstream>
10+
#include <vector>
11+
12+
#include <benchmark/benchmark.h>
13+
14+
static void bm_write(benchmark::State& state) {
15+
std::vector<char> buffer;
16+
buffer.resize(16384);
17+
18+
std::ofstream stream("/dev/null");
19+
20+
for (auto _ : state)
21+
stream.write(buffer.data(), buffer.size());
22+
}
23+
BENCHMARK(bm_write);
24+
25+
BENCHMARK_MAIN();

libcxx/test/libcxx/input.output/file.streams/fstreams/filebuf/traits_mismatch.verify.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,4 @@
2121

2222
std::basic_filebuf<char, std::char_traits<wchar_t> > f;
2323
// expected-error-re@streambuf:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
24-
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
25-
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
26-
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
27-
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
28-
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
29-
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
30-
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
31-
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
32-
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
24+
// expected-error@*:* 10 {{only virtual member functions can be marked 'override'}}

libcxx/test/libcxx/input.output/file.streams/fstreams/traits_mismatch.verify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ std::basic_fstream<char, std::char_traits<wchar_t> > f;
2323
// expected-error-re@ios:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
2424
// expected-error-re@streambuf:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
2525

26-
// expected-error@*:* 11 {{only virtual member functions can be marked 'override'}}
26+
// expected-error@*:* 12 {{only virtual member functions can be marked 'override'}}
2727

2828
// FIXME: As of commit r324062 Clang incorrectly generates a diagnostic about mismatching
2929
// exception specifications for types which are already invalid for one reason or another.

libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/seekoff.pass.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ int main(int, char**)
2929
| std::ios_base::trunc) != 0);
3030
assert(f.is_open());
3131
f.sputn("abcdefghijklmnopqrstuvwxyz", 26);
32-
LIBCPP_ASSERT(buf[0] == 'v');
3332
pos_type p = f.pubseekoff(-15, std::ios_base::cur);
3433
assert(p == 11);
3534
assert(f.sgetc() == 'l');

0 commit comments

Comments
 (0)