Skip to content

Massive speedup to file_equal and file_to_string#1584

Open
DefaultRyan wants to merge 2 commits into
masterfrom
user/defaultryan/file_equal
Open

Massive speedup to file_equal and file_to_string#1584
DefaultRyan wants to merge 2 commits into
masterfrom
user/defaultryan/file_equal

Conversation

@DefaultRyan
Copy link
Copy Markdown
Member

I was testing some quality of life improvements, and I saw that in incremental situations when there are already headers in the output folder, cppwinrt.exe takes twice as long to run!

Before writing pending output, it reads the existing file in and compares it, skipping the write if the contents are identical. The comparison itself is fast enough, using std::equal which boils down to memcmp, but the read is using std::ifstream::operator<< to read a std::string, and this operation processes the file contents a single character at a time, resulting in tons of overhead.

With this change, we now do a single bulk read of the file contents. Additionally, before we read the contents, we check the file size in the filesystem before reading the contents, allowing us to short-circuit even faster.

A before/after comparison on a Release x64 run of regenerating the local SDK projection without cleaning the output folder first, shows a 50% speedup in wall clock time.

Here's the results from an instrumented profile run in Visual Studio.
Before:
image
image

After:
image
image

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes incremental generation performance by speeding up the “read existing file and compare” path used to skip redundant writes in cppwinrt.exe.

Changes:

  • Replace stringstream << rdbuf() file reads with a single bulk read sized up-front via tellg().
  • Short-circuit file_equal earlier by checking the on-disk file size before reading and comparing.

Comment thread cppwinrt/text_writer.h
Comment thread cppwinrt/text_writer.h Outdated
jonwis
jonwis previously approved these changes May 22, 2026
Copy link
Copy Markdown
Member

@jonwis jonwis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic! But do note @lhecker 's comment. I know we try and be crossplat-ready here, but 2x again is nothing to sneeze at... in aifabric builds, cppwinrt runtime is definitely a factor across all the projects that use it.

@oldnewthing
Copy link
Copy Markdown
Member

We can do what cmd_reader.h does and put the Windows-optimized version under #if defined(_WIN32) || defined(_WIN64).

@DefaultRyan
Copy link
Copy Markdown
Member Author

@jonwis, @lhecker
I'm open to measure the realistic impact of a Windows-specific code path. But we're already close to diminishing returns on this particular code. As it stands right now, this brings the time spent in file_equal() down to less than 2% of the total run time of cppwinrt.exe in the case where we completely skip the file write because the pending output perfectly matches the existing output. Probably on the order of 100 ms or less on average for generating a full SDK/platform projection?

There is probably more impactful possibilities for speeding up cppwinrt.exe.

For example, we are spending nearly 10% of our processing time on repeated (~1M) std::map lookups. An educated guess is that much of this is from repeatedly resolving a winmd's TypeRef namespace+name into a TypeDef, likely in find_required().

@DefaultRyan DefaultRyan requested a review from jonwis May 23, 2026 03:11
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.

5 participants