Quickstart¶
1. Start the Resource Manager¶
The resource manager must be running before any other Maru service.
Production — start as a systemd daemon:
# Default (127.0.0.1:9850)
sudo systemctl start maru-resource-manager
# With custom host/port
sudo systemctl edit maru-resource-manager
[Service]
ExecStart=
ExecStart=/usr/local/bin/maru-resource-manager --host <ip> --port <port>
sudo systemctl restart maru-resource-manager
Development/debugging — run directly with custom options:
# Default (127.0.0.1:9850)
sudo maru-resource-manager --log-level debug
# With custom host/port
sudo maru-resource-manager --host <ip> --port <port> --log-level debug
If you change the RM port, pass the same address to
maru-server:maru-server --rm-address 127.0.0.1:9851See MaruResourceManager Architecture for the full list of CLI options.
2. Start the Metadata Server¶
# Default (127.0.0.1:5555, connects to resource manager at 127.0.0.1:9850)
maru-server
# With custom host/port
maru-server --host <ip> --port <port>
# With custom resource manager address (default: 127.0.0.1:9850)
maru-server --rm-address <rm-ip>:<rm-port>
# With debug logging
maru-server --log-level DEBUG
3. Run a Client Example¶
Both
maru-resource-managerandmaru-servermust be running before proceeding.
Zero-Copy Store & Retrieve¶
from maru import MaruConfig, MaruHandler
config = MaruConfig(
server_url="tcp://localhost:5555",
pool_size=1024 * 1024 * 100, # Request 100MB from the CXL memory pool
)
with MaruHandler(config) as handler:
data = b"A" * (1024 * 1024) # 1MB KV chunk
# 1. Allocate a page in CXL shared memory
handle = handler.alloc(size=len(data))
# 2. Write directly to CXL memory (mmap — no intermediate buffer)
handle.buf[:] = data
# 3. Register the key — only metadata (key → region, offset) is sent
handler.store(key=42, handle=handle)
# Retrieve: returns a memoryview pointing into CXL memory
result = handler.retrieve(key=42)
assert result is not None
assert bytes(result.view[:5]) == b"AAAAA"
The three steps — alloc(), write to handle.buf, store(handle=) — make Maru’s control/data plane separation explicit:
Control plane:
alloc()requests a memory region from the Resource Manager;store()registers the key’s location metadata (~tens of bytes) with MaruServer.Data plane:
handle.buf[:]reads/writes directly on mmap’d CXL memory. No server involved.
Full runnable example:
examples/basic/single_instance.py
Cross-Instance Sharing¶
This is the core of Maru — two independent processes sharing KV cache through CXL shared memory with zero data copy. Metadata travels, data doesn’t.
flowchart LR
P[Producer] -->|"alloc + write"| CXL[(CXL Memory)]
P -->|"store(key)"| S[MaruServer]
C[Consumer] -->|"retrieve(key)"| S
S -.->|"location"| C
C -->|"read"| CXL
Terminal 1 — Producer: allocate, write, register metadata:
from maru import MaruConfig, MaruHandler
config = MaruConfig(
server_url="tcp://localhost:5555",
instance_id="producer",
pool_size=1024 * 1024 * 100,
)
with MaruHandler(config) as handler:
for i, key in enumerate([1001, 1002, 1003]):
data = bytes([ord("A") + i]) * (1024 * 1024)
handle = handler.alloc(size=len(data))
handle.buf[:] = data
handler.store(key=key, handle=handle)
input("Press Enter to exit...")
Terminal 2 — Consumer: retrieve from CXL (zero copy):
from maru import MaruConfig, MaruHandler
config = MaruConfig(
server_url="tcp://localhost:5555",
instance_id="consumer",
pool_size=1024 * 1024 * 100,
)
with MaruHandler(config) as handler:
for key in [1001, 1002, 1003]:
result = handler.retrieve(key=key)
# result.view points directly into Producer's CXL region (mapped read-only).
# No data was copied — consumer reads the same physical memory.
assert result is not None
print(f"key={key}: {len(result.view)} bytes, char={chr(result.view[0])!r}")
Full runnable examples:
examples/basic/producer.py+examples/basic/consumer.pySingle-script version:
examples/basic/cross_instance.py
Next Steps¶
Installation — Multi-node configuration
LMCache Examples — Use Maru as a shared KV cache backend for LMCache/vLLM
Architecture Overview — System architecture and component interactions
API Reference — Python API documentation
Configuration — Configuration options