Skip to content

Various performance improvements on Windows - #175

Merged
de-vri-es merged 3 commits into
RazrFalcon:masterfrom
mat-gas:mmap-ro-force
Aug 20, 2026
Merged

de-vri-es merged 3 commits into
RazrFalcon:masterfrom
mat-gas:mmap-ro-force

Conversation

@mat-gas

@mat-gas mat-gas commented Aug 13, 2026

Copy link
Copy Markdown

Various performance improvements on Windows:

  • mmap2 performs extra checks on the file handle (2 extra CreateFileMapping) to check if the mapping can be "upgraded" to write or execute.

    When requesting a pure readonly mapping, those extra checks are useless.

    So add a no_probe_handle function to MmapOptions (a la no_reserve_swap on Unix) to avoid probing those handles

  • When creating a new mapping or dropping it, allocation_granularity is queried, which leads to calling GetSystemInfo that performs at least 2 syscalls (see screenshot, 1 more syscall in GetSystemInfoInternal) .
    Cache the result to avoid getting the same information each time (stored like page_size on Unix)

image

Quick benchmark: around 30% performance gain (27 -> 17 us for mapping a file + destroying the handle)

@de-vri-es

Copy link
Copy Markdown
Collaborator

Hey, thanks for the PR!

Could you elaborate a bit on the intended use case for this?

@mat-gas

mat-gas commented Aug 13, 2026

Copy link
Copy Markdown
Author

We use mmap on windows and map a lot (thousands) files as read only.
The file handke we have are read only, so we already know the mapping will also be read only at best.
Knowing this, we'd like to avoid the 2 unecessary CreateFileMapping that test for write or execute every time we map a file.

Easiest way was to add a new public function and not modify "map()" but you tell me what you feel is best

@de-vri-es

de-vri-es commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Right, thanks for the explanation! Good to know it's really about the overhead of the syscalls :)

Since this new function still returns a Mmap, just like regular map(), this feels like it could just a runtime option stored in MmapOptions. Something like probe_handle(&mut self, enable_probing: bool) -> &mut Self

That feels less intrusive than adding another mapping function, plus it can be honored by both map() and map_exec().

@mat-gas

mat-gas commented Aug 13, 2026

Copy link
Copy Markdown
Author

Gotcha, i'll implement it that way
Thanks

Mathieu Gaspard added 2 commits August 17, 2026 09:41
By default, creating a file-backed mapping on Windows issues up to two
extra CreateFileMappingW calls to probe whether the handle supports
write and/or execute access, so that the section is created with the
widest protection the handle allows and the view can later be
transitioned with make_mut()/make_exec(). A side effect is that mapping
a file read-only through a writable handle still creates a writable
section on it.

With MmapOptions::no_probe_handle() set, the section and view are
created in a single call each, with exactly the protection the mapping
type requires (e.g. PAGE_READONLY/FILE_MAP_READ for map()). This
guarantees a read-only mapping never creates a writable section, at the
cost that transitioning the returned mapping to a wider protection
fails.
GetSystemInfo is implemented as two NtQuerySystemInformation system
calls, and allocation_granularity() is called at least twice over a
mapping's lifetime (creation and unmapping on drop), plus once per
flush. Cache the value in a static, the same way page_size() already is
on unix; the racy initialization is benign since GetSystemInfo is
idempotent and the granularity is constant for the lifetime of the
system.
@mat-gas mat-gas changed the title Add map_read_only_exact to force having a RO mapping. Various performance improvements on Windows Aug 17, 2026
@mat-gas

mat-gas commented Aug 17, 2026

Copy link
Copy Markdown
Author

@de-vri-es Done, i've also added another performance improvement in the allocation_granularity function to cache the result instead of querying it 2-3 times/map

@de-vri-es

Copy link
Copy Markdown
Collaborator

Looks good! Thanks for the changes. I've pushed one commit to disable the clippy lint that was triggering. Will merge once CI is green :)

@de-vri-es
de-vri-es merged commit a02e2a4 into RazrFalcon:master Aug 20, 2026
15 checks passed
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.

2 participants