Skip to content

Commit

Permalink
[libc++] Optimize ofstream::write
Browse files Browse the repository at this point in the history
  • Loading branch information
philnik777 committed Jan 21, 2025
1 parent 455b3d6 commit 87acdbe
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 11 deletions.
3 changes: 3 additions & 0 deletions libcxx/docs/ReleaseNotes/20.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ Improvements and New Features
std::errc::not_a_directory``, or use ``err.default_error_condition()`` to map to an ``error_condition``, and then test
its ``value()`` and ``category()``.

- ``ofstream::write`` has been optimized to pass through large strings to system calls directly instead of copying them
in chunks into a buffer.

Deprecations and Removals
-------------------------

Expand Down
12 changes: 12 additions & 0 deletions libcxx/include/fstream
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ _LIBCPP_EXPORTED_FROM_ABI void* __filebuf_windows_native_handle(FILE* __file) no

template <class _CharT, class _Traits>
class _LIBCPP_TEMPLATE_VIS basic_filebuf : public basic_streambuf<_CharT, _Traits> {
using __base _LIBCPP_NODEBUG = basic_streambuf<_CharT, _Traits>;

public:
typedef _CharT char_type;
typedef _Traits traits_type;
Expand Down Expand Up @@ -304,6 +306,16 @@ protected:
int sync() override;
void imbue(const locale& __loc) override;

_LIBCPP_HIDE_FROM_ABI_VIRTUAL streamsize xsputn(const char_type* __str, streamsize __len) override {
if (__always_noconv_ && __len >= (this->epptr() - this->pbase())) {
if (traits_type::eq_int_type(overflow(), traits_type::eof()))
return 0;

return std::fwrite(__str, sizeof(char_type), __len, __file_);
}
return __base::xsputn(__str, __len);
}

private:
char* __extbuf_;
const char* __extbufnext_;
Expand Down
25 changes: 25 additions & 0 deletions libcxx/test/benchmarks/streams/ofstream.bench.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <fstream>
#include <vector>

#include <benchmark/benchmark.h>

static void bm_write(benchmark::State& state) {
std::vector<char> buffer;
buffer.resize(16384);

std::ofstream stream("/dev/null");

for (auto _ : state)
stream.write(buffer.data(), buffer.size());
}
BENCHMARK(bm_write);

BENCHMARK_MAIN();
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,4 @@

std::basic_filebuf<char, std::char_traits<wchar_t> > f;
// expected-error-re@streambuf:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
// expected-error@fstream:* {{only virtual member functions can be marked 'override'}}
// expected-error@*:* 10 {{only virtual member functions can be marked 'override'}}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ std::basic_fstream<char, std::char_traits<wchar_t> > f;
// expected-error-re@ios:* {{static assertion failed{{.*}}traits_type::char_type must be the same type as CharT}}
// expected-error-re@streambuf:* {{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@*:* 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ int main(int, char**)
| std::ios_base::trunc) != 0);
assert(f.is_open());
f.sputn("abcdefghijklmnopqrstuvwxyz", 26);
LIBCPP_ASSERT(buf[0] == 'v');
pos_type p = f.pubseekoff(-15, std::ios_base::cur);
assert(p == 11);
assert(f.sgetc() == 'l');
Expand Down

0 comments on commit 87acdbe

Please sign in to comment.