MemoryWatcher.Remote
0.0.0-preview.9
See the version list below for details.
dotnet add package MemoryWatcher.Remote --version 0.0.0-preview.9
NuGet\Install-Package MemoryWatcher.Remote -Version 0.0.0-preview.9
<PackageReference Include="MemoryWatcher.Remote" Version="0.0.0-preview.9" />
<PackageVersion Include="MemoryWatcher.Remote" Version="0.0.0-preview.9" />
<PackageReference Include="MemoryWatcher.Remote" />
paket add MemoryWatcher.Remote --version 0.0.0-preview.9
#r "nuget: MemoryWatcher.Remote, 0.0.0-preview.9"
#:package MemoryWatcher.Remote@0.0.0-preview.9
#addin nuget:?package=MemoryWatcher.Remote&version=0.0.0-preview.9&prerelease
#tool nuget:?package=MemoryWatcher.Remote&version=0.0.0-preview.9&prerelease
MemoryWatcher
Cross-platform, Native AOT-oriented memory watching toolkit for C# 14 / .NET 10. The repository is built around capability negotiation and honest precision contracts instead of pretending one OS primitive can observe every memory scenario with zero cost and zero loss.
Packages | Internal Projects | Quick Example | Precision Model | Build and Test | Native AOT | Documentation | Public API
Packages
Packable libraries currently produced by this repository:
| Package | Role | Status |
|---|---|---|
MemoryWatcher |
Managed snapshot/diff engine, planners, interpretation helpers, ring-buffer sink, and polling loop primitives | Scaffolded, not published yet |
MemoryWatcher.Abstractions |
Contracts, value types, capability models, watch regions, result types, and observation semantics | Scaffolded, not published yet |
MemoryWatcher.Unsafe |
In-process unsafe pointer, bit-region, and typed-value watcher fast paths | Scaffolded, not published yet |
MemoryWatcher.Native |
External-process memory sources, resolver helpers, OS-specific watchpoint control, and native capability negotiation | Scaffolded, not published yet |
MemoryWatcher.Remote |
Managed session/watch client over the MemoryWatcher.RemoteAot shared-library ABI, packaged with staged win-x64 and linux-x64 native assets for normal NuGet consumption |
Scaffolded, not published yet |
These packages target net10.0 and are intended to stay honest about platform
limits rather than flattening them away.
Internal Projects
Non-packable projects that complete the repository:
| Project | Role |
|---|---|
MemoryWatcher.RemoteAot |
Native AOT shared library exposing a stable external-process C ABI |
MemoryWatcher.Agent |
Native AOT agent shared library for in-process exports and dirty/page-fault-assisted workflows |
MemoryWatcher.Sample |
Minimal runnable example of the managed watcher path |
MemoryWatcher.MicroBenchmarks |
Polling-path performance probes |
MemoryWatcher.SmokeTests |
Executable smoke coverage for core watcher behavior |
MemoryWatcher.DocTests |
Public API snapshot generation for docs/PublicApi.md |
What This Repository Actually Supports
Implemented layers include:
- Managed snapshot watching with a single-bit fast path.
- Segmented and hash-indexed snapshot watching for larger observed regions.
- Unsafe in-process pointer and typed-value watchers.
- Windows
ReadProcessMemory+VirtualQueryExprocess memory access. - Linux
process_vm_readv,/proc/<pid>/maps, soft-dirty, and related remote process tracking paths. - macOS Mach-based remote reads from an authorized task port.
- Cooperative dirty-page tracking and agent-fed page-fault-assisted watching.
- Windows x64/WOW64 and Linux hardware watchpoint controller surfaces.
- Native AOT shared-library exports for both in-process agent and external-process consumption.
- Module-relative, absolute, pointer-chain, pattern-scan, and exported-symbol resolver models.
- Span-based interpretation helpers for bits, integers, floats, and text formats.
Precision Model
The repository is explicit about what it can and cannot guarantee.
- Polling watchers are single-bit precise between samples. If a bit differs at the next observation, the watcher can report that difference precisely.
- Polling does not prove transient edges. A
0 -> 1 -> 0transition that begins and ends between two polls may be missed. - Edge-exact observation requires event-backed paths. That means hardware watchpoints or real fault/dirty-page signals where the OS, privileges, and target process model actually support them.
- Capability reports are intentionally conservative. If a path can miss ABA patterns or depends on per-thread debugger state, the API should admit that instead of hiding it.
See docs/PRECISION.md and docs/BACKENDS.md for the detailed contract.
Quick Example
using MemoryWatcher;
byte[] memory = [0];
using var source = new ManagedMemorySource(memory, MemoryAddress.Zero);
using IBitMemoryWatcher watcher = BitWatcherFactory.CreateSnapshot(
source,
BitWatchRegion.SingleBit(MemoryAddress.Zero, 0),
MemoryWatchOptions.SubMillisecondSnapshot);
Span<BitChange> output = stackalloc BitChange[1];
memory[0] = 1;
BitPollResult result = watcher.Poll(output);
For a runnable sample, see samples/MemoryWatcher.Sample/Program.cs.
External-Process Facade
If you want a friendlier managed API for remote process work, use
MemoryWatcher.Native.UnsafeMemoryWatcher:
using MemoryWatcher;
using MemoryWatcher.Native;
using var watcher = new UnsafeMemoryWatcher(new UnsafeMemoryWatcherOptions
{
ProcessId = targetPid
});
using UnsafeMemoryObservation hp = watcher.Observe(
UnsafeMemoryRegion.DWord(new MemoryAddress(0x00ABCDEF)),
UnsafeMemoryObservationPrecision.ByDWord);
Span<UnsafeMemoryUnitChange> units = stackalloc UnsafeMemoryUnitChange[8];
UnsafeMemoryUnitPollResult poll = hp.Poll(units);
If you want a managed client over the shared-library ABI, use
MemoryWatcher.Remote.
If you need the language-agnostic shared-library boundary itself, use
MemoryWatcher.RemoteAot.
Fastest Polling Path
UnsafeSingleBitWatcher is the lowest-overhead portable polling path in the
repository: one byte load, one XOR, one mask test, and an optional event write
into caller-owned storage. If missed-edge probability matters, pair it with a
dedicated SubMillisecondPollingLoop or run it from a known target hook/tick.
Hardware Watchpoints
This repository exposes hardware watchpoint controllers and related backends, not a fake “universal hardware watcher.”
- On Windows, use the controller/session surface and consume debugger or in-process exception delivery yourself.
- On Linux,
HardwareWatchpointBackendcan combine hardware events with a post-event bit diff throughperf_event_open. - Thread affinity, privilege requirements, and event delivery semantics remain OS-specific by design.
Build and Test
Build.cs is the repository task runner:
dotnet run Build.cs build Release
dotnet run Build.cs test Release
dotnet run Build.cs -- test -c Release --no-build --no-restore
dotnet run Build.cs bench
dotnet run Build.cs coverage
dotnet run Build.cs pack
dotnet run Build.cs public-api
When forwarding option-style script args such as -c, -o, or --no-build,
insert -- after Build.cs.
Native AOT
dotnet publish samples/MemoryWatcher.Sample -c Release -r win-x64 /p:PublishAot=true
dotnet publish samples/MemoryWatcher.Sample -c Release -r linux-x64 /p:PublishAot=true
dotnet publish samples/MemoryWatcher.Sample -c Release -r osx-arm64 /p:PublishAot=true
dotnet pack src/MemoryWatcher.Remote -c Release
dotnet publish src/MemoryWatcher.RemoteAot -c Release -r win-x64
dotnet publish src/MemoryWatcher.RemoteAot -c Release -r linux-x64
dotnet pack src/MemoryWatcher.Remote -c Release produces the managed client package
and embeds the MemoryWatcher.RemoteAot native artifact for the selected pack RID.
On Windows the default pack RID is win-x64; on Linux it is linux-x64.
To publish the normal cross-host MemoryWatcher.Remote NuGet used by downstream
apps, first stage both native outputs and then pack with both runtime ids:
pwsh ./eng/publish-remoteaot.ps1 -Rid win-x64
pwsh ./eng/publish-remoteaot.ps1 -Rid linux-x64
dotnet run Build.cs -- pack Release -p:SkipRemoteAotPublishForPack=true /p:RemoteAotPackRuntimeIdentifiers=win-x64%3Blinux-x64
dotnet run Build.cs -- remote-package-smoke Release --expected-rids win-x64,linux-x64
That flow produces a single MemoryWatcher.Remote package with:
runtimes/win-x64/native/MemoryWatcher.RemoteAot.dllruntimes/linux-x64/native/MemoryWatcher.RemoteAot.so
The remote-package-smoke build command restores a temp consumer from the
freshly packed NuGet and verifies that NativeMemoryWatchSessionFactory can
load the bundled native library and read a self-process memory snapshot.
MemoryWatcher.RemoteAot is the external-process Native AOT shared library.
MemoryWatcher.Agent is the in-process agent/export path.
Repository Layout
src/
MemoryWatcher.Abstractions/ Contracts and value types
MemoryWatcher.Core/ Managed watcher engine and interpretation
MemoryWatcher.Unsafe/ Unsafe in-process fast paths
MemoryWatcher.Native/ OS-specific and remote-process backends
MemoryWatcher.Remote/ Managed client over the RemoteAot ABI
MemoryWatcher.RemoteAot/ External-process Native AOT shared library
MemoryWatcher.Agent/ In-process Native AOT agent shared library
samples/
MemoryWatcher.Sample/
benchmarks/
MemoryWatcher.MicroBenchmarks/
tests/
MemoryWatcher.SmokeTests/
MemoryWatcher.DocTests/
docs/
Precision, backend, and ABI documentation
Documentation
- docs/BACKENDS.md: backend matrix, platform scope, and implementation notes
- docs/PRECISION.md: precision semantics and ABA-loss caveats
- docs/REMOTE_AOT.md: external-process Native AOT ABI and publish guidance
- docs/REMOTE_AOT_ABI.h: C declarations for the remote shared library
- docs/AGENT_ABI.h: C declarations for the in-process agent surface
- docs/IMPLEMENTATION.md: implementation notes and design detail
- docs/IMPLEMENTATION_STATUS.md: current scaffold/build-out status
- docs/PublicApi.md: generated public API snapshot
Public API
See docs/PublicApi.md for the generated public API
reference. It is refreshed by tests/MemoryWatcher.DocTests during the
repository test pass.
License
MIT — Copyright (c) 2026 Bia10
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- MemoryWatcher.Abstractions (>= 0.0.0-preview.9)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.0-preview.16 | 61 | 6/12/2026 |
| 0.0.0-preview.13 | 42 | 6/11/2026 |
| 0.0.0-preview.12 | 41 | 6/11/2026 |
| 0.0.0-preview.11 | 36 | 6/11/2026 |
| 0.0.0-preview.10 | 38 | 6/11/2026 |
| 0.0.0-preview.9 | 40 | 6/10/2026 |
| 0.0.0-preview.8 | 47 | 6/10/2026 |
| 0.0.0-preview.6 | 43 | 6/10/2026 |