How Magnitude's ICN Manages Hardware Profiling and Memory Topology with the icn‑hardware Crate
Magnitude's Inter‑Component Network (ICN) discovers and exposes CPU topology, NUMA node layout, and memory characteristics through the dedicated icn‑hardware Rust crate, which aggregates sysfs data and serves it via type‑safe RPC.
The icn‑hardware crate lives in packages/acn-hardware and forms the bedrock of hardware awareness across the Magnitude platform. It abstracts Linux kernel interfaces into structured data that the Agent Communication Network (ACN) can query, cache, and forward to clients.
Core Data Structures in icn‑hardware
HardwareInfo: The Central Aggregation Point
The HardwareInfo struct is the primary entry point for hardware discovery. Defined in packages/acn-hardware/src/lib.rs, it combines CPU topology and memory topology into a single coherent view.
// Conceptual signature based on crate implementation
pub struct HardwareInfo {
pub topology: Topology,
pub memory: MemoryTopology,
}
impl HardwareInfo {
/// Gathers hardware information from the local system.
/// This walks /sys/devices/system/cpu and /sys/devices/system/node.
pub fn gather() -> Result<Self, HardwareError>;
}
The gather() method is invoked once at daemon startup and its results are cached for subsequent RPC calls. This avoids repeated filesystem traversal during hot‑path operations.
Topology: CPU Hierarchy Discovery
The Topology struct—implemented in packages/acn-hardware/src/topology.rs—represents the hierarchical relationship between sockets, physical cores, and hardware threads.
| Field | Description | Source |
|---|---|---|
sockets |
Vec of Socket structs, each containing cores |
/sys/devices/system/cpu/cpu*/topology/physical_package_id |
cores |
Per‑socket core lists with thread siblings | /sys/devices/system/cpu/cpu*/topology/core_id |
thread_siblings |
Bitmask of threads sharing L1/L2 | /sys/devices/system/cpu/cpu*/topology/thread_siblings_list |
The topology walker parses these sysfs files to build a hwloc‑compatible representation without external C library dependencies.
MemoryTopology: NUMA and Bandwidth Awareness
The MemoryTopology struct—defined in packages/acn-hardware/src/memory.rs—captures NUMA node layout and inter‑node distances.
pub struct NumaNode {
pub id: u32,
pub cpus: Vec<u32>, // CPUs local to this node
pub start_addr: u64, // Start of physical memory range
pub size: u64, // Total node memory in bytes
pub free: u64, // Available memory (from /proc/meminfo)
}
pub struct MemoryTopology {
pub nodes: Vec<NumaNode>,
pub distances: Vec<Vec<u32>>, // NUMA distance matrix
}
The distance matrix is populated from /sys/devices/system/node/node*/distance, which exposes the kernel's relative memory latency estimates. This enables higher‑level scheduling components to make locality‑aware placement decisions.
RPC Integration: From Crate to Client
Protocol Definition in acn‑protocol
The hardware profile is exposed through the HardwareProfile RPC boundary, declared in packages/acn-protocol/src/boundary/hardware.ts:
// Effect‑Schema definition for type‑safe serialization
export const HardwareProfileSchema = Schema.Struct({
topology: TopologySchema,
memoryTopology: MemoryTopologySchema,
gatheredAt: Schema.Number, // Unix timestamp for cache validation
});
export type HardwareProfile = typeof HardwareProfileSchema.Type;
// RPC declaration with replaySafe policy
export const HardwareProfileRpc = Rpc.make("HardwareProfile", {
request: Schema.Void,
response: HardwareProfileSchema,
policy: RpcPolicy.replaySafe, // No side‑effects, safe to retry
});
The replaySafe policy signals that the operation is read‑only and idempotent, allowing the RPC layer to optimize retry behavior.
Daemon Handler in acn
The ACN daemon implements this RPC in packages/acn/src/hardware-handler.ts:
import { HardwareInfo } from "@magnitude/icn-hardware";
export class HardwareHandler implements RpcHandler<typeof HardwareProfileRpc> {
private cachedInfo: HardwareInfo | null = null;
async handle(): Promise<HardwareProfile> {
if (!this.cachedInfo) {
// Delegate to Rust crate via FFI or WASM bridge
this.cachedInfo = await HardwareInfo.gather();
}
return this.toSchema(this.cachedInfo);
}
private toSchema(info: HardwareInfo): HardwareProfile {
// Normalize to Effect‑Schema, ensuring Option types for optional fields
return {
topology: normalizeTopology(info.topology),
memoryTopology: normalizeMemory(info.memory),
gatheredAt: Date.now(),
};
}
}
The handler maintains an in‑memory cache of the HardwareInfo struct, refreshing only on explicit invalidation or daemon restart.
Client Consumption in client‑common
Clients access this data through packages/client-common/src/operations/hardware.ts:
import { sdk } from "@magnitude/sdk";
import { createQuery } from "@effect-rx/rx-query";
export const useHardwareProfile = () => {
return createQuery(
sdk.getHardwareProfile, // SDK method wrapping the RPC
{
staleTime: 5 * 60 * 1000, // 5 minute cache
refetchOnWindowFocus: false,
}
);
};
The query integrates with the reactive cache system, ensuring multiple UI components share the same underlying RPC result.
Practical Usage Examples
TypeScript Client: Rendering Topology
import { useHardwareProfile } from "@magnitude/client-common";
function CpuTopologyView() {
const { data: profile, isLoading } = useHardwareProfile();
if (isLoading) return <Spinner />;
return (
<div>
<h3>CPU Topology</h3>
<p>Total sockets: {profile.topology.sockets.length}</p>
<ul>
{profile.topology.sockets.map((socket, idx) => (
<li key={idx}>
Socket {idx}: {socket.cores.length} cores, {" "}
{socket.cores.reduce((sum, c) => sum + c.threads.length, 0)} threads
</li>
))}
</ul>
<h3>NUMA Layout</h3>
<table>
<thead>
<tr><th>Node</th><th>CPUs</th><th>Memory</th></tr>
</thead>
<tbody>
{profile.memoryTopology.nodes.map(node => (
<tr key={node.id}>
<td>{node.id}</td>
<td>{node.cpus.join(", ")}</td>
<td>{(node.size / 1e9).toFixed(1)} GB</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
Rust: Direct Crate Usage for Custom Tools
use icn_hardware::{HardwareInfo, Topology, MemoryTopology};
fn analyze_numa_locality(pid: u32) -> Result<(), Box<dyn std::error::Error>> {
// Load current hardware configuration
let hw = HardwareInfo::gather()?;
// Find which NUMA node owns the majority of process memory
let node_usage = read_process_numa_pages(pid)?;
let best_node = node_usage
.iter()
.enumerate()
.max_by_key(|(_, &pages)| pages)
.map(|(idx, _)| idx)
.unwrap_or(0);
let target_node = &hw.memory.nodes[best_node];
println!(
"Process {} prefers NUMA node {} with {} local CPUs",
pid, target_node.id, target_node.cpus.len()
);
// Use distance matrix to find failover nodes
let distances = &hw.memory.distances[best_node];
let alternatives: Vec<_> = distances
.iter()
.enumerate()
.filter(|(idx, d)| *idx != best_node && **d < 20) // Local/remote threshold
.map(|(idx, d)| (idx, d))
.collect();
println!("Failover candidates: {:?}", alternatives);
Ok(())
}
Dynamic Refresh and Hot‑Plug Support
While the default cache‑at‑startup pattern covers most deployment scenarios, icn‑hardware supports explicit re‑discovery:
// Force a fresh hardware scan, useful after CPU hot‑plug
pub fn HardwareInfo::gather_fresh() -> Result<Self, HardwareError>;
The RPC handler exposes this through a separate RefreshHardwareProfile RPC (also replaySafe), which invalidates the daemon's cache and triggers gather_fresh() on the next request.
Summary
icn‑hardwareinpackages/acn-hardwareprovides the authoritative hardware discovery implementation for Magnitude's ICN.- Topology (
src/topology.rs) and MemoryTopology (src/memory.rs) parse Linux sysfs to build structured CPU and NUMA representations. - The HardwareInfo::gather() method is the single entry point, caching results for performance.
- Effect‑Schema (
packages/acn-protocol/src/boundary/hardware.ts) ensures type‑safe serialization across the RPC boundary. - The ACN daemon (
packages/acn/src/hardware-handler.ts) serves cached profiles withreplaySafesemantics. - Client SDK utilities (
packages/client-common/src/operations/hardware.ts) integrate hardware data into reactive UI flows.
Frequently Asked Questions
How does icn‑hardware detect CPU topology on non‑Linux platforms?
The crate currently targets Linux exclusively, reading from /sys/devices/system. On unsupported platforms, HardwareInfo::gather() returns a HardwareError::UnsupportedPlatform which the daemon handles by returning a degraded profile with topology fields set to empty defaults.
Can the hardware profile be used for affinity‑aware agent scheduling?
Yes. The NUMA distance matrix exposed in MemoryTopology::distances enables scheduling decisions that minimize cross‑node memory access. Higher‑level Magnitude components consume this data through the SDK's getHardwareProfile() method.
What triggers a cache refresh in the ACN daemon?
By default, the cache is populated once at daemon startup. Explicit refresh requires calling the RefreshHardwareProfile RPC or restarting the daemon. There is no automatic inotify‑based refresh to avoid complexity with CPU hot‑plug edge cases.
Are memory bandwidth estimates available on all systems?
Bandwidth hints depend on kernel configuration. When /sys/devices/system/node/node*/meminfo lacks bandwidth data, icn‑hardware omits the optional field from the schema, and consumers fall back to distance‑based heuristics.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →