# sysinfo: reading processes, disks and CPUs from Rust, with a refresh model you must respect

> A cross-platform Rust crate for system information whose main trap is not portability but statefulness: most values are diffs against a previous reading, so the same System instance has to be reused.

**GuillaumeGomez/sysinfo** — Cross-platform library to fetch system information

- Repository: https://github.com/GuillaumeGomez/sysinfo
- Stars: 2,747 · Forks: 436
- Language: Rust
- License: MIT
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/guillaumegomez-sysinfo

## Eight platforms, and empty values everywhere else

The supported list is alphabetical and short enough to read at a glance: Android, FreeBSD, NetBSD, iOS, Linux, macOS, Raspberry Pi and Windows. The repository topics track the same ground with linux, macos, unix, windows and raspberry among them.

What happens off that list is stated rather than left to be discovered at runtime. You can still use sysinfo on an unsupported OS, and it will simply do nothing and always return empty values. The library exposes an `IS_SUPPORTED_SYSTEM` constant so a program can check at runtime instead of guessing. That design choice, compiling everywhere and degrading quietly, is the right call for a library you might pull into a CLI that also runs on a platform its author does not use.

Version constraints are current. The Cargo.toml declares version 0.39.6, edition 2024, and a rust-version of 1.95, which matches the README's statement that the minimum-supported rustc is 1.95. The description in the manifest is more precise than the README's one-liner, naming the categories: processes, CPUs, disks, components and networks.

There are no GitHub releases for this repository, so there is no version history in the release feed. What there is instead is a CHANGELOG.md and a separate migration_guide.md at the root, both linked from the README for anyone upgrading from an older release.

## The refresh model is the thing to understand first

The README puts a warning before any code sample, and it is the most important paragraph in the document. Before any attempt to read the different structs' information, you need to update them to get up to date information, because for most of them it works on a diff between the current value and the old one.

That has a direct consequence, which the README states next: it is much better to keep the same instance of `System` around instead of recreating it multiple times. A fresh `System` has no previous measurement to diff against, so CPU usage comes back as zero until the second poll, and a throwaway instance can never report usage at all.

The loop for CPU usage shows the intended shape, including the part people forget. You refresh, read, then sleep for `sysinfo::MINIMUM_CPU_UPDATE_INTERVAL` so the system has had time to accumulate a meaningful delta. Polling faster than that minimum gets you the same number repeatedly, not a higher resolution reading.

The same logic applies to networks, where the README distinguishes between the total received and transmitted counters and the per-interval `received` and `transmitted` values that reset on each refresh. Choose deliberately, because mixing them produces graphs that either never move or never accumulate.

## A first program, and the performance advice that follows it

The README's sample program is worth reading in full because it shows which types are independent. `System` covers the whole machine: name, kernel version, OS version, host name, memory, swap, CPU count and the process list. `Disks`, `Networks` and `Components` are separate types you enumerate independently.

Each of those returns a `Result`, which is the practical reminder that this is a cross-platform library where a query can fail. A sensible first program, and the one the repository ships, is run with:

```bash
cargo run --example simple
```

The performance guidance is more specific than generic advice. Most of the time you want a subset of the information, not all of it, and `refresh_specifics(...)` with only what you need gives much better performance than a blanket refresh. Re-instantiating `System` is called out a second time with the reason: listing all running processes means allocating memory for the whole `Process` struct list, which takes some time on the first run.

The Cargo.toml shows how you pay for only what you use. Default features are component, disk, gpu, network, system and user, and each one pulls in its own platform bindings, so the windows crate features for WMI and file system calls and the objc2 CoreFoundation bindings arrive with the features rather than unconditionally.

## Containers, WSL and the Apple sandbox, where it goes quiet

This is the section that decides whether sysinfo works in your environment, and each entry is a documented failure rather than a caveat.

For virtual Linux systems, the ones running through Docker or WSL, the reason is stated precisely: host hardware information does not arrive via `/sys/class/hwmon` or `/sys/class/thermal`. So querying for components may return no results, or unexpected results, on a virtual system. If your monitoring agent runs in a container, temperatures and fans are the values that will be blank, and that is the host boundary rather than a bug.

For Apple platforms the problem is different in kind, a policy rather than a missing file. Apple restricts which APIs can be linked into binaries distributed through the app store, and by default sysinfo is not compatible with those restrictions. The `apple-app-store` feature flag disables the prohibited features, and it also enables `apple-sandbox`. If you are using the sandbox outside the app store, `apple-sandbox` alone avoids the runtime policy violation. A build that ships to the App Store and fails review over a linked API is avoidable, but only if you know about the flag in advance.

There is also an optional `multithread` feature, off by default, which uses multiple threads at the cost of increased memory usage on some platforms, macOS being named as an example. Turning it on for a desktop utility is reasonable; turning it on for a small daemon is a decision you should measure rather than assume.

## Raspberry Pi, file descriptors and a C interface

Cross-compiling for a Pi is documented as three steps, and the README warns that building directly on the device will be difficult, recommending a cross-build on a desktop followed by copying the executable over.

First, install the ARM toolchain:

```bash
> sudo apt-get install gcc-multilib-arm-linux-gnueabihf
```

Then point cargo at the matching linker through a config file:

```bash
cat << EOF > ~/.cargo/config
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
EOF
```

And finally add the target and build:

```bash
rustup target add armv7-unknown-linux-gnueabihf
cargo build --target=armv7-unknown-linux-gnueabihf
```

The file descriptor note is easy to miss and matters if your program already opens a lot of them. sysinfo keeps some open for better performance when refreshing processes, and `sysinfo::set_open_files_limit(0)` turns that off, at the cost of the performance it was buying.

There is also a C interface, which is why the Makefile is at the root of a Rust project. It exists solely to build the C example: it compiles the crate as a cdylib with the `c-interface` feature and links the result against `simple.o`. The `sysinfo.h` header ships in src/, and examples/simple.c sits next to examples/simple.rs so the two languages can be compared side by side.

## How to read performance, and where the details live

The repository treats performance as something you verify rather than something it promises. There is a benches/ directory, and the README's section on running tests opens by saying that because the subject is system information, some tests have a better chance to succeed when run under particular conditions. A test suite that depends on what the machine is doing at that moment is an unusual and honest admission, and it tells you something about the reliability of the numbers you will read.

For the internals, the README does not explain anything itself. It points to a blog post by the author on how sysinfo extracts information on the different systems. That is a sensible division, because per-platform extraction is exactly the kind of detail that goes stale in a README, and it is also exactly the detail you need when a number looks wrong on one OS.

The rest of the tree is aimed at contributors rather than users. ADDING_NEW_PLATFORMS.md is the interesting one, because adding a platform is the maintenance burden that comes with claiming eight-platform support, and documenting it as a separate guide is how you keep that promise honest as the Rust ecosystem moves. There is also a test-unknown/ directory and a test_bin/, which together suggest CI coverage across targets rather than a single local run.

For a user, the practical reading order is the README's supported list and warning, then the sample program, then the section matching your deployment environment. The rest is for when you are adding a platform yourself.

## Conclusion

sysinfo is the crate to reach for when a Rust program needs to see the machine it runs on, and its portability across Linux, macOS, Windows, the BSDs, Android, iOS and Raspberry Pi is real rather than aspirational. Two constraints decide whether it fits: you must refresh state you intend to read, and you must keep the same System instance across polls because CPU usage and process data are computed as diffs. On virtualised Linux, component temperatures will come back empty, which is a host-level limitation and not something the crate can fix. Start with refresh_specifics rather than refresh_all, and check whether your target platform needs the apple-app-store feature before you discover the problem at submission.

## FAQ

### Why does sysinfo report zero CPU usage on the first call?

Because most of the structs compute their values as a diff between the current and previous reading, so a fresh instance has nothing to compare against. The README advises keeping the same System instance around rather than recreating it, and sleeping for sysinfo::MINIMUM_CPU_UPDATE_INTERVAL between refreshes so the delta is meaningful.

### Does sysinfo work inside a Docker container or WSL?

Partly. The README explains that virtual Linux systems do not receive host hardware information via /sys/class/hwmon or /sys/class/thermal, so querying components may return no results or unexpected results. Process, CPU, disk and network information is unaffected by that particular limitation.

### Can I use sysinfo in an iOS app distributed through the App Store?

Not by default. The README states that sysinfo is not compatible with Apple's restrictions on which APIs can be linked into app store binaries, and that the apple-app-store feature flag disables the prohibited features while also enabling apple-sandbox. For sandbox use outside the app store, the apple-sandbox feature can be enabled on its own.

## Sources

- [GuillaumeGomez/sysinfo on GitHub](https://github.com/GuillaumeGomez/sysinfo)
- [Issues](https://github.com/GuillaumeGomez/sysinfo/issues)
- [License: MIT](https://github.com/GuillaumeGomez/sysinfo/blob/main/LICENSE)
- [README](https://github.com/GuillaumeGomez/sysinfo/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/guillaumegomez-sysinfo
