# How fmt::output_file Achieves Faster File Writing in the fmt Library

> Discover how fmtlib's fmt::output_file speeds up file writing using direct OS calls and optimized buffering. Minimize system call overhead for peak performance.

- Repository: [Hello World Foundation/fmt](https://github.com/fmtlib/fmt)
- Tags: performance
- Published: 2026-09-04

---

**The `fmt::output_file` function achieves faster file writing by using direct OS system calls instead of C stdio APIs, maintaining a custom in-memory buffer to batch write operations, and allowing configurable buffer sizes to minimize system call overhead.**

The `fmt::output_file` interface in the fmt library (available in [`include/fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/os.h)) delivers superior file I/O performance compared to traditional C++ streams. Unlike `std::cout` or `fprintf`, which rely on the C standard library's buffering and locking mechanisms, `fmt::output_file` implements a lightweight, zero-overhead abstraction over raw file descriptors. This design eliminates per-character locking and reduces the frequency of expensive system calls, resulting in measurably faster file writing for formatted output.

## Low-Level File Descriptors Eliminate stdio Overhead

When `FMT_USE_FCNTL` is enabled (the default on POSIX platforms), `fmt::file` opens files using the native `open()` system call rather than `fopen()`. The implementation stores the resulting file descriptor (`fd_`) and performs all I/O using direct system calls: `write()` on POSIX systems and `WriteFile` on Windows.

This architecture bypasses the C standard library's `FILE*` abstraction entirely. Standard I/O implementations typically include thread-safe locking mechanisms and layered buffering that add overhead to every operation. By contrast, `fmt::file::write(const void* buffer, size_t count)` declared in [`include/fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/os.h) (lines 78-80) delegates directly to the OS kernel, eliminating intermediate buffering and synchronization overhead per write operation.

## Custom In-Memory Buffer Coalesces Multiple Writes

`fmt::ostream` privately inherits from `detail::buffer<char>` to accumulate formatted data in a contiguous memory region before writing to disk. This buffering strategy ensures that multiple `print()` operations result in a single system call when the buffer fills or when explicitly flushed.

The buffering mechanism works as follows:

- **Accumulation**: Calls to `ostream::print` format data into the internal buffer using `vformat_to(appender(*this), …)` (lines 90-95 in [`os.h`](https://github.com/fmtlib/fmt/blob/main/os.h))
- **Growth**: The buffer expands dynamically via `ostream::grow` to accommodate larger outputs without reallocation penalties
- **Flush**: When `ostream::flush` is invoked, it writes the entire buffer in one atomic operation: `file_.write(data(), size() * sizeof(data()[0]))` followed by `clear()` (lines 76-80)

This batching approach minimizes expensive context switches to kernel space, delivering higher throughput than unbuffered or line-buffered alternatives that invoke system calls for every write.

## Configurable Buffer Size for Specific Workloads

The default buffer size is set to `std::max(BUFSIZ, 32768)` as defined in `detail::ostream_params`. Users can override this default using the `buffer_size` parameter when calling `output_file` to tune performance for specific storage hardware.

Larger buffers reduce flush frequency, which improves throughput on both SSD and HDD storage by maximizing the amount of data transferred per system call. For write-heavy applications processing large volumes of data, increasing the buffer size to 1 MiB or higher significantly reduces I/O overhead while maintaining the same convenient formatting interface.

## Key Implementation Details in os.h

The `output_file` factory function (lines 1110-1114 in [`include/fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/os.h)) forwards its arguments to `detail::ostream_params` and returns an initialized `ostream` instance. The actual low-level I/O implementation resides in `src/os.cc`, which provides the platform-specific implementations of `file::write`, `file::read`, and file descriptor lifecycle management.

The `detail::buffer<T>` base class (defined in [`include/fmt/detail/buffer.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/detail/buffer.h)) provides the generic memory management interface, while [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) supplies the formatting machinery (`vformat_to`, `appender`) that feeds formatted strings into the buffer without intermediate string construction.

## Usage Examples

Basic usage creates a fast, buffered file writer with minimal syntax:

```cpp
auto out = fmt::output_file("log.txt");
out.print("Processed {} items in {:.2f}s\n", items, seconds);
out.flush();  // Optional immediate flush
// Automatic close and flush on scope exit

```

For high-throughput scenarios, tune the buffer size:

```cpp
auto out = fmt::output_file("bigdata.bin", buffer_size = 1 << 20);  // 1 MiB
out.print("{}\n", huge_string);  // Many writes coalesced into few system calls

```

On POSIX systems, specify custom open flags for specialized access patterns:

```cpp
auto out = fmt::output_file(
    "append.log",
    fmt::file::WRONLY | fmt::file::APPEND
);
out.print("New entry at {}\n", fmt::localtime());

```

## Summary

- **`fmt::output_file`** bypasses C stdio to use direct OS system calls (`write()`/`WriteFile`), eliminating per-operation locking and layered buffering overhead found in standard streams.
- **Custom buffering** via `detail::buffer<char>` accumulation allows multiple format operations to coalesce into single large writes, minimizing kernel context switch frequency.
- **Configurable buffer sizes** (defaulting to `std::max(BUFSIZ, 32768)`) let users optimize throughput for their specific storage hardware and write patterns.
- Implementation spans [`include/fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/os.h) (interface), `src/os.cc` (platform I/O), and [`include/fmt/detail/buffer.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/detail/buffer.h) (memory management), providing a cohesive high-performance output solution.

## Frequently Asked Questions

### How does `fmt::output_file` compare to `std::ofstream` for performance?

`fmt::output_file` typically outperforms `std::ofstream` because it avoids the C++ streams' locale machinery and the C stdio locking mechanisms. By using raw file descriptors and custom buffering in [`include/fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/os.h), it reduces per-character overhead and enables batched writes that minimize kernel context switches according to the fmt source code.

### Can I use `fmt::output_file` for binary data writing?

Yes. While designed for formatted text output, the underlying `fmt::file::write` method in `src/os.cc` writes raw bytes directly via system calls. For binary data, you can manage the buffer directly or write formatted representations, though for pure binary streams, the `fmt::file` class provides direct `write()` access without formatting overhead.

### What happens if I don't call `flush()` explicitly?

The `ostream` destructor automatically flushes any remaining buffered data to disk when the object goes out of scope, invoking the flush logic at lines 76-80 of [`os.h`](https://github.com/fmtlib/fmt/blob/main/os.h). However, if your application crashes or terminates abnormally before destruction, unflushed data in the buffer may be lost. For critical logging, call `flush()` periodically or configure buffer sizes appropriate for your reliability requirements.

### Is `FMT_USE_FCNTL` available on all platforms?

`FMT_USE_FCNTL` is automatically defined on POSIX platforms that support the [`fcntl.h`](https://github.com/fmtlib/fmt/blob/main/fcntl.h) header and file descriptor operations. On Windows, the library uses native `HANDLE`-based I/O via `WriteFile` instead. The implementation in `src/os.cc` provides the platform-specific adaptations, ensuring `fmt::output_file` delivers optimized performance across operating systems.