Skip to content

Conversation

@ej-sanmartin
Copy link
Contributor

@ej-sanmartin ej-sanmartin commented Jan 9, 2026

Description

Original implementation for SDL_IOStream write file API was incredibly slow on Windows due to not having basic buffering. A write up at nmlgc/ssg#93 details critical performance issues due to this.

This PR adds basic buffering of size 1024 (same as windows_file_read read buffer) to windows_file_write and also implemented auto flushing for the new write buffer before read and seek operations. This adds safety by default. Users don't need to manually call SDL_FlushIO() between write to reads and write to seek transactions at the cost of (very) minimal speed overhead, which is negligible given the buffer massively improves write speed on Windows.

Existing Issue(s)

Fixes #12424

Tested

Built SDL3 locally and on this branch and wrote a minimal benchmark test for the following scenarios:

  • Small writes (1 byte)
  • Medium writes (100 bytes)
  • Large writes (2048 bytes)
  • SDL_SaveBMP_IO usage (~300 bytes)

With no write buffer:

Starting...

Running 5 iterations of each benchmark...

BENCHMARK 1 - Small Writes (1 byte x 10,000): Average: 62.899 ms

BENCHMARK 2 - Medium Writes (100 bytes x 1,000): Average: 6.104 ms

BENCHMARK 3 - Large Writes (2048 bytes x 500): Average: 5.775 ms

BENCHMARK 4 - SDL_SaveBMP_IO: Average: 17.973 ms

With write buffer:

Starting...

Running 5 iterations of each benchmark...

BENCHMARK 1 - Small Writes (1 byte x 10,000): Average: 0.657 ms

BENCHMARK 2 - Medium Writes (100 bytes x 1,000): Average: 1.481 ms

BENCHMARK 3 - Large Writes (2048 bytes x 500): Average: 7.009 ms

BENCHMARK 4 - SDL_SaveBMP_IO: Average: 3.161 ms

Small writes ~95x faster, medium writes ~4x faster, large writes slightly slower but expected, SDL_SaveBMP_IO ~6x faster.

@slouken
Copy link
Collaborator

slouken commented Jan 9, 2026

Wow, with write buffer you got no results! I'm not convinced this is an improvement. ;)

@ej-sanmartin
Copy link
Contributor Author

So fast nothing was outputted lolol

@ej-sanmartin
Copy link
Contributor Author

I'll fix the failed tests when the logs for the errors eventually load on my end 🫡

@slouken
Copy link
Collaborator

slouken commented Jan 9, 2026

Large writes are significantly slower. Maybe when we get a write larger than the buffer we can flush any pending writes and write it directly with no buffering?

@ej-sanmartin
Copy link
Contributor Author

Actually, this is already being done in lines 347-373, when writes ≥ buffer size (1024 bytes) this flushes any pending data and write directly via WriteFile, bypassing the buffer.

    // For large writes, flush buffer and write directly
    if (size >= WRITEBEHIND_BUFFER_SIZE) {
        if (!windows_flush_write_buffer(iodata, status)) {
            return 0;
        }
      // Continue with rest of function

The 1ms difference may be variances in the benchmark test itself per run, but since we are bypassing the buffer in larger writes, we are largely at the mercy of the syscalls. I think the major win from this change comes from the smaller writes, which is a massive improvement atm.

We could increase write buffer size but that adds size overhead, doesn't "fix" this issue really, and we dont have any data on average write size to anchor this in.

@slouken slouken added this to the 3.6.0 milestone Jan 12, 2026
@slouken slouken merged commit 7c9ae67 into libsdl-org:main Jan 12, 2026
45 checks passed
@slouken
Copy link
Collaborator

slouken commented Jan 12, 2026

Merged, thanks!

@ej-sanmartin ej-sanmartin deleted the feat/buffer-windows-file-write branch January 13, 2026 07:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SDL is very slow when doing multiple write operations to a file on Windows.

2 participants