Memory Management
Buffer Allocation
Sia provides three ways to create instances, each with different memory characteristics.
Default Constructor
const sia = new Sia();
Uses a global shared 32 MB buffer (lazy-allocated on first use). This is the fastest option because it avoids per-call allocation, but the buffer is shared across all default-constructed Sia instances. Safe for synchronous serialize-then-extract workflows.
Sia.alloc(size)
const sia = Sia.alloc(1024);
Allocates a new, dedicated Uint8Array of the given size. Use this when you need an isolated buffer that won't be affected by other Sia instances.
Sia.allocUnsafe(size)
const sia = Sia.allocUnsafe(256);
Carves a subarray from the global shared buffer. Faster than alloc (no allocation), but the memory region may contain stale data from previous operations. The offset wraps around when the shared buffer is full.
When to Use What
| Constructor | Allocation | Isolation | Best For |
|---|---|---|---|
new Sia() | None (shared) | None | Quick serialize + extract |
Sia.alloc(n) | New buffer | Full | Long-lived buffers, concurrent use |
Sia.allocUnsafe(n) | Shared slice | Partial | High-throughput, short-lived buffers |
Extracting Data
After writing data, you need to extract the serialized bytes. Sia offers two methods:
toUint8Array(): Safe Copy
const bytes = sia.toUint8Array();
Returns a new Uint8Array containing a copy of the written data. The returned array is independent of the Sia buffer and safe to store, send over the network, or pass to other APIs.
toUint8ArrayReference(): Zero Copy
const ref = sia.toUint8ArrayReference();
Returns a subarray (view) of the internal buffer. No data is copied. This is faster but the returned array shares memory with the Sia instance. If the buffer is reused, the data may be overwritten.
Use toUint8Array() when you need to keep the data around.
Use toUint8ArrayReference() when you'll consume the data immediately (e.g., send it over a WebSocket in the same tick).
Zero-Copy Reads
The readByteArray* methods accept an asReference parameter:
// Copies the bytes out (safe, independent)
const copy = sia.readByteArray32();
// Returns a subarray reference (zero-copy)
const ref = sia.readByteArray32(true);
This also applies to readByteArray8, readByteArray16, and readByteArray64.
The same trade-off applies: references are faster but share memory with the source buffer. Use them for temporary reads in hot loops.
High-Throughput Pattern
For maximum performance in request-response scenarios (e.g., WebSocket RPC), use allocUnsafe with toUint8ArrayReference:
function handleRequest(data: Uint8Array): Uint8Array {
// Read the request (reuse a shared reader)
const reader = new Sia(data);
const method = reader.readAscii8();
const param = reader.readString8();
// Compute response...
const result = processRequest(method, param);
// Write response with zero allocations
const writer = Sia.allocUnsafe(256);
writer.addString8(result);
return writer.toUint8Array(); // copy out before buffer is reused
}
Memory Safety
When using toUint8ArrayReference(), the returned subarray is backed by the same ArrayBuffer. Modifications to the Sia buffer will be visible through the reference:
const sia = new Sia();
sia.addUInt8(42);
const ref = sia.toUint8ArrayReference();
console.log(ref[0]); // 42
sia.seek(0);
sia.addUInt8(99);
console.log(ref[0]); // 99 -- the reference sees the change
Always copy the data with toUint8Array() or slice() if you need it to survive beyond the current operation.