-
Notifications
You must be signed in to change notification settings - Fork 24
feat(heapwatch): add crate scaffolding and initial design #613
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
martintmk
wants to merge
6
commits into
main
Choose a base branch
from
user/martintmk/20260728-add-heapwatch-crate
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
7a31d99
feat(heapwatch): add crate scaffolding and initial design
martintmk c0803fa
fix(heapwatch): opt out of the coverage gate while the crate has no code
martintmk b0806cc
docs(heapwatch): align the peak invariant statement with invariant 5
martintmk 79e8ca9
docs(heapwatch): drop peak tracking, own counters per instance
martintmk c457298
docs(heapwatch): state the demand-vs-footprint limit explicitly
martintmk 228dfbb
docs(heapwatch): drop the caller-facing flush from the design
martintmk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| # Changelog |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|
|
||
| [package] | ||
| name = "heapwatch" | ||
| version = "0.1.0" | ||
| description = "A low-overhead global allocator wrapper that continuously accounts heap usage" | ||
| readme = "README.md" | ||
| keywords = ["allocator", "heap", "memory", "metrics", "diagnostics"] | ||
| categories = ["memory-management", "development-tools::profiling"] | ||
|
|
||
| edition.workspace = true | ||
| rust-version.workspace = true | ||
| authors.workspace = true | ||
| license.workspace = true | ||
| homepage.workspace = true | ||
| include.workspace = true | ||
| repository = "https://github.com/microsoft/oxidizer/tree/main/crates/heapwatch" | ||
|
|
||
| # The crate is scaffolding: it carries the design documents but no code, so | ||
| # there is nothing to instrument and no test to run. Without this opt-out the | ||
| # impact-scoped coverage run fails with nextest's "no tests to run" (exit 4). | ||
| # REMOVE THIS SECTION when the implementation lands, so the workspace-default | ||
| # 100% line-coverage gate applies again. | ||
| [package.metadata.coverage-gate] | ||
| min-lines-percent = 0 | ||
|
|
||
| [package.metadata.docs.rs] | ||
| rustdoc-args = ["--cfg", "docsrs"] | ||
| all-features = true | ||
|
|
||
| # >>> anvil-managed: anvil-lints | ||
| [lints] | ||
| workspace = true | ||
| # <<< anvil-managed: anvil-lints |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| <div align="center"> | ||
| <img src="https://raw.githubusercontent.com/microsoft/oxidizer/refs/heads/main/logo.svg" alt="Heapwatch Logo" width="96"> | ||
|
|
||
| # Heapwatch | ||
|
|
||
| [](https://crates.io/crates/heapwatch) | ||
| [](https://docs.rs/heapwatch) | ||
| [](https://crates.io/crates/heapwatch) | ||
| [](https://github.com/microsoft/oxidizer/actions/workflows/main.yml) | ||
| [](https://codecov.io/gh/microsoft/oxidizer) | ||
| [](https://github.com/microsoft/oxidizer/blob/main/LICENSE) | ||
| <a href="https://github.com/microsoft/oxidizer"><img src="https://raw.githubusercontent.com/microsoft/oxidizer/refs/heads/main/logo.svg" alt="This crate was developed as part of the Oxidizer project" width="20"></a> | ||
|
|
||
| </div> | ||
|
|
||
| A global allocator wrapper that continuously accounts heap usage. | ||
|
|
||
| Heapwatch wraps another allocator and, installed as a binary’s | ||
| `#[global_allocator]`, reports how many bytes that binary’s Rust heap holds | ||
| and how much has moved through it. It answers *how much*, never *who* — no | ||
| backtraces, no per-allocation metadata, no pointer-to-size shadow map — | ||
| which is what keeps the per-allocation cost to a few non-atomic adds, low | ||
| enough to leave enabled in production. | ||
|
|
||
| ## Status | ||
|
|
||
| **The API is not implemented yet — this crate is currently scaffolding.** | ||
| The architecture is settled and written up in [`DESIGN.md`][__link0], and the ideas | ||
| deliberately left out of it are recorded in [`TODO.md`][__link1]. Both land ahead of | ||
| the code so the design can be reviewed on its own terms. | ||
|
|
||
| ## The mechanism | ||
|
|
||
| Each thread accumulates its own totals with plain, non-atomic arithmetic and | ||
| publishes them into the allocator instance’s atomic totals in batches — once | ||
| *bytes allocated plus bytes freed* since its last publication crosses a | ||
| compile-time threshold, and again when the thread exits. That removes the | ||
| atomic read-modify-write per allocation that an exact accounting wrapper | ||
| pays, which is the cost that scales badly with core count. | ||
|
|
||
| The trade is a small, bounded, stated inaccuracy: a reading omits whatever | ||
| each live thread has not yet published, at most the threshold times the | ||
| number of live threads. That bound depends on neither the allocation rate | ||
| nor how long the process has been running. Reading is O(1) in the thread | ||
| count — a handful of relaxed loads through a handle obtained from the | ||
| allocator, with no registry to walk. | ||
|
|
||
| ## Measurement boundary | ||
|
|
||
| Heapwatch counts successful calls through the registered `GlobalAlloc`, and | ||
| counts them as *requested* rather than as reserved, since the trait has no | ||
| hook to ask the inner allocator what it actually rounded up to. Allocations | ||
| that never reach the global allocator — native and FFI heaps, direct OS | ||
| mappings, anything routed to `std::alloc::System` — are outside the | ||
| boundary, as are thread stacks, static data, and the inner allocator’s own | ||
| metadata and fragmentation. It therefore complements, rather than replaces, | ||
| allocator-native statistics and process-level metrics such as resident set | ||
| size. | ||
|
|
||
|
|
||
| <hr/> | ||
| <sub> | ||
| This crate was developed as part of <a href="https://github.com/microsoft/oxidizer">The Oxidizer Project</a>. Browse this crate's <a href="https://github.com/microsoft/oxidizer/tree/main/crates/heapwatch">source code</a>. | ||
| </sub> | ||
|
|
||
| [__link0]: https://github.com/microsoft/oxidizer/blob/main/crates/heapwatch/docs/DESIGN.md | ||
| [__link1]: https://github.com/microsoft/oxidizer/blob/main/crates/heapwatch/docs/TODO.md |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.