CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyfury

Blazingly fast multi-language serialization framework powered by JIT and zero-copy

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

memory-management.mddocs/

Memory Management

Apache Fury's memory management system provides high-performance binary buffer operations with platform-specific optimizations and efficient memory access patterns.

MemoryBuffer

The core buffer class for efficient binary data operations with both heap and off-heap memory support.

public class MemoryBuffer {
    // Buffer creation
    public static MemoryBuffer newHeapBuffer(int size);
    public static MemoryBuffer newDirectBuffer(int size);
    
    // Basic read/write operations
    public void writeByte(byte value);
    public byte readByte();
    public void writeBoolean(boolean value);
    public boolean readBoolean();
    public void writeChar(char value);
    public char readChar();
    public void writeShort(short value);
    public short readShort();
    public void writeInt(int value);
    public int readInt();
    public void writeLong(long value);
    public long readLong();
    public void writeFloat(float value);
    public float readFloat();
    public void writeDouble(double value);
    public double readDouble();
    
    // Array operations
    public void writeBytes(byte[] bytes);
    public void writeBytes(byte[] bytes, int offset, int length);
    public byte[] readBytes(int length);
    public void readBytes(byte[] bytes, int offset, int length);
    
    // String operations
    public void writeString(String str);
    public String readString();
    
    // Position management
    public int writerIndex();
    public void writerIndex(int writerIndex);
    public int readerIndex();
    public void readerIndex(int readerIndex);
    public void resetWriterIndex();
    public void resetReaderIndex();
    
    // Buffer state
    public int size();
    public int capacity();
    public int remain();
    public boolean isEmpty();
    
    // Buffer operations
    public void clear();
    public void reset();
    public byte[] toByteArray();
    public ByteBuffer asByteBuffer();
}

Memory Utilities

Platform-specific memory operations and utilities.

public class MemoryUtils {
    // Platform detection
    public static boolean isLittleEndian();
    public static boolean isBigEndian();
    
    // Memory allocation utilities
    public static long allocateMemory(long size);
    public static void freeMemory(long address);
    
    // Memory copy operations
    public static void copyMemory(long srcAddress, long destAddress, long length);
    public static void copyMemory(Object src, long srcOffset, Object dest, long destOffset, long length);
    
    // Bounds checking utilities
    public static void checkBounds(int index, int length, int capacity);
    
    // Platform-specific optimizations
    public static boolean isAligned(long address, int alignment);
    public static long alignAddress(long address, int alignment);
}

Platform

Low-level platform operations using Unsafe for maximum performance.

public class Platform {
    // Direct memory access constants
    public static final boolean LITTLE_ENDIAN;
    public static final int BYTE_ARRAY_OFFSET;
    public static final int INT_ARRAY_OFFSET;
    public static final int LONG_ARRAY_OFFSET;
    
    // Memory operations
    public static byte getByte(long address);
    public static void putByte(long address, byte value);
    public static int getInt(long address);
    public static void putInt(long address, int value);
    public static long getLong(long address);
    public static void putLong(long address, long value);
    
    // Array access
    public static byte getByte(Object array, long offset);
    public static void putByte(Object array, long offset, byte value);
    public static int getInt(Object array, long offset);
    public static void putInt(Object array, long offset, int value);
}

Endianness Utilities

Utilities for handling byte order and endianness conversions.

public class LittleEndian {
    public static short getShort(byte[] bytes, int index);
    public static void putShort(byte[] bytes, int index, short value);
    public static int getInt(byte[] bytes, int index);
    public static void putInt(byte[] bytes, int index, int value);
    public static long getLong(byte[] bytes, int index);
    public static void putLong(byte[] bytes, int index, long value);
}

public class BigEndian {
    public static short getShort(byte[] bytes, int index);
    public static void putShort(byte[] bytes, int index, short value);
    public static int getInt(byte[] bytes, int index);
    public static void putInt(byte[] bytes, int index, int value);
    public static long getLong(byte[] bytes, int index);
    public static void putLong(byte[] bytes, int index, long value);
}

Buffer Utilities

Additional utilities for working with ByteBuffer and buffer operations.

public class ByteBufferUtil {
    // ByteBuffer creation
    public static ByteBuffer allocateDirect(int capacity);
    public static ByteBuffer wrap(byte[] array);
    
    // Buffer operations
    public static void clear(ByteBuffer buffer);
    public static byte[] toArray(ByteBuffer buffer);
    public static int remaining(ByteBuffer buffer);
    
    // Endianness handling
    public static ByteOrder getByteOrder(ByteBuffer buffer);
    public static void setByteOrder(ByteBuffer buffer, ByteOrder order);
}

Usage Examples

Basic Buffer Operations

import org.apache.fury.memory.MemoryBuffer;

// Create heap buffer
MemoryBuffer buffer = MemoryBuffer.newHeapBuffer(1024);

// Write primitive values
buffer.writeInt(42);
buffer.writeLong(123456789L);
buffer.writeString("Hello, Fury!");

// Read back values (reset reader index first)
buffer.readerIndex(0);
int intValue = buffer.readInt();
long longValue = buffer.readLong();
String stringValue = buffer.readString();

Working with Byte Arrays

// Write byte arrays
byte[] data = {1, 2, 3, 4, 5};
buffer.writeBytes(data);

// Write partial array
buffer.writeBytes(data, 1, 3); // Write bytes at indices 1, 2, 3

// Read byte arrays
buffer.readerIndex(0);
byte[] readData = buffer.readBytes(5);

// Read into existing array
byte[] targetArray = new byte[3];
buffer.readBytes(targetArray, 0, 3);

Direct Memory Buffers

// Create direct (off-heap) buffer for large data
MemoryBuffer directBuffer = MemoryBuffer.newDirectBuffer(1024 * 1024); // 1MB

// Use for large binary data to avoid GC pressure
directBuffer.writeBytes(largeBinaryData);

// Convert to ByteBuffer for NIO operations
ByteBuffer byteBuffer = directBuffer.asByteBuffer();

Buffer Position Management

// Track positions
int initialWriterPos = buffer.writerIndex();
buffer.writeInt(100);
buffer.writeInt(200);
int finalWriterPos = buffer.writerIndex();

// Reset to read from beginning
buffer.readerIndex(0);
int first = buffer.readInt();
int second = buffer.readInt();

// Jump to specific position
buffer.readerIndex(initialWriterPos);

Memory-Efficient Operations

// Reuse buffers to avoid allocation
MemoryBuffer reusableBuffer = MemoryBuffer.newHeapBuffer(1024);

for (Object obj : objectsToSerialize) {
    reusableBuffer.clear(); // Reset for reuse
    fury.serialize(reusableBuffer, obj);
    
    // Process serialized data
    byte[] serializedData = reusableBuffer.toByteArray();
    // ... send over network, write to file, etc.
}

Platform-Specific Optimizations

import org.apache.fury.memory.Platform;
import org.apache.fury.memory.MemoryUtils;

// Check platform characteristics
if (MemoryUtils.isLittleEndian()) {
    // Optimize for little-endian byte order
}

// Direct memory operations (advanced usage)
long address = MemoryUtils.allocateMemory(1024);
try {
    Platform.putInt(address, 42);
    int value = Platform.getInt(address);
} finally {
    MemoryUtils.freeMemory(address);
}

Integration with Serialization

// Use buffer with Fury serialization
MemoryBuffer buffer = MemoryBuffer.newHeapBuffer(1024);

// Serialize object to buffer
fury.serialize(buffer, myObject);

// Get serialized bytes
byte[] serializedBytes = buffer.toByteArray();

// Create new buffer for deserialization
MemoryBuffer deserializeBuffer = MemoryBuffer.newHeapBuffer(serializedBytes.length);
deserializeBuffer.writeBytes(serializedBytes);
deserializeBuffer.readerIndex(0);

// Deserialize from buffer
Object restored = fury.deserialize(deserializeBuffer);

Working with Large Datasets

// Handle large datasets efficiently
public void processLargeDataset(List<LargeObject> dataset) {
    // Use larger buffer for batch processing
    MemoryBuffer batchBuffer = MemoryBuffer.newDirectBuffer(10 * 1024 * 1024); // 10MB
    
    for (int i = 0; i < dataset.size(); i++) {
        if (batchBuffer.remain() < ESTIMATED_OBJECT_SIZE) {
            // Process current batch
            processBatch(batchBuffer);
            batchBuffer.clear();
        }
        
        fury.serialize(batchBuffer, dataset.get(i));
    }
    
    // Process remaining data
    if (batchBuffer.writerIndex() > 0) {
        processBatch(batchBuffer);
    }
}

Performance Considerations

Buffer Selection

  • Heap Buffers: Better for small-medium data sizes, easier GC management
  • Direct Buffers: Better for large data, reduced GC pressure, but allocation overhead
  • Buffer Reuse: Reuse buffers when possible to avoid allocation overhead

Memory Access Patterns

  • Sequential Access: Most efficient, leverages CPU cache
  • Aligned Access: Better performance on some platforms
  • Batch Operations: Use array operations when possible for better throughput

Platform Optimizations

  • Endianness: Fury automatically handles platform endianness
  • Unsafe Operations: Used internally for maximum performance
  • Memory Alignment: Considered for optimal memory access patterns

Memory Management Best Practices

  1. Reuse Buffers: Create buffer pools for frequently used buffer sizes
  2. Monitor Memory Usage: Track direct memory usage to avoid OutOfMemoryError
  3. Choose Appropriate Buffer Size: Balance between memory usage and allocation frequency
  4. Clean Up Direct Buffers: Ensure proper cleanup of direct memory
  5. Use Appropriate Buffer Type: Heap for small data, direct for large data or when interfacing with NIO

Install with Tessl CLI

npx tessl i tessl/pypi-pyfury

docs

core-serialization.md

custom-serializers.md

index.md

memory-management.md

type-system.md

tile.json