Platforms ​
Archive.zig is designed to work across all platforms supported by Zig, from desktop operating systems to embedded systems and bare metal targets. This guide covers platform-specific considerations, optimizations, and best practices.
Supported Platforms ​
Desktop Platforms ​
Archive.zig works on all major desktop platforms:
- Windows (x86_64, x86, aarch64)
- Linux (x86_64, x86, aarch64, arm, riscv64)
- macOS (x86_64, aarch64)
- FreeBSD (x86_64, x86, aarch64)
Embedded and Bare Metal ​
Archive.zig supports embedded and bare metal targets:
- ARM Cortex-M (thumbv6m, thumbv7m, thumbv7em, thumbv8m)
- RISC-V (riscv32, riscv64)
- AVR (avr)
- WebAssembly (wasm32, wasm64)
- Bare metal (freestanding)
Platform-Specific Optimizations ​
Windows Optimizations ​
zig
const std = @import("std");
const archive = @import("archive");
pub fn windowsOptimizations(allocator: std.mem.Allocator) !void {
if (std.builtin.os.tag != .windows) return;
// Windows-specific configuration
const config = archive.CompressionConfig.init(.zstd)
.withZstdLevel(10) // Good balance for desktop systems
.withBufferSize(256 * 1024) // Larger buffers work well on Windows
.withMemoryLevel(8); // Higher memory usage acceptable
const input = "Windows-optimized compression data";
const compressed = try archive.compressWithConfig(allocator, input, config);
defer allocator.free(compressed);
std.debug.print("Windows optimization: {d} bytes\n", .{compressed.len});
}
pub fn windowsFileHandling(allocator: std.mem.Allocator) !void {
if (std.builtin.os.tag != .windows) return;
// Windows file path handling
const input_path = "C:\\temp\\input.txt";
const output_path = "C:\\temp\\output.gz";
// Handle Windows-specific file attributes
const input_file = std.fs.cwd().openFile(input_path, .{}) catch |err| switch (err) {
error.FileNotFound => {
std.debug.print("File not found: {s}\n", .{input_path});
return;
},
error.AccessDenied => {
std.debug.print("Access denied - check file permissions\n", .{});
return;
},
else => return err,
};
defer input_file.close();
// Read file with Windows line endings handling
const file_size = try input_file.getEndPos();
const file_data = try allocator.alloc(u8, file_size);
defer allocator.free(file_data);
_ = try input_file.readAll(file_data);
// Compress and write
const compressed = try archive.compress(allocator, file_data, .gzip);
defer allocator.free(compressed);
try std.fs.cwd().writeFile(.{ .sub_path = output_path, .data = compressed });
std.debug.print("Windows file handling completed\n", .{});
}Linux Optimizations ​
zig
pub fn linuxOptimizations(allocator: std.mem.Allocator) !void {
if (std.builtin.os.tag != .linux) return;
// Linux-specific configuration
const config = archive.CompressionConfig.init(.zstd)
.withZstdLevel(15) // Higher compression for server environments
.withBufferSize(512 * 1024) // Large buffers for server workloads
.withMemoryLevel(9); // Maximum memory usage
const input = "Linux server-optimized compression";
const compressed = try archive.compressWithConfig(allocator, input, config);
defer allocator.free(compressed);
std.debug.print("Linux optimization: {d} bytes\n", .{compressed.len});
}
pub fn linuxSystemIntegration(allocator: std.mem.Allocator) !void {
if (std.builtin.os.tag != .linux) return;
// Use Linux-specific features
const page_size = std.mem.page_size;
std.debug.print("System page size: {d} bytes\n", .{page_size});
// Align buffer to page size for better performance
const aligned_size = std.mem.alignForward(usize, 128 * 1024, page_size);
const config = archive.CompressionConfig.init(.lz4)
.withBufferSize(aligned_size);
const input = "Linux system-integrated compression";
const compressed = try archive.compressWithConfig(allocator, input, config);
defer allocator.free(compressed);
std.debug.print("Linux system integration: {d} bytes\n", .{compressed.len});
}macOS Optimizations ​
zig
pub fn macosOptimizations(allocator: std.mem.Allocator) !void {
if (std.builtin.os.tag != .macos) return;
// macOS-specific configuration
const config = archive.CompressionConfig.init(.zstd)
.withZstdLevel(12) // Balanced for macOS systems
.withBufferSize(256 * 1024) // Good for macOS memory management
.withMemoryLevel(7); // Moderate memory usage
const input = "macOS-optimized compression data";
const compressed = try archive.compressWithConfig(allocator, input, config);
defer allocator.free(compressed);
std.debug.print("macOS optimization: {d} bytes\n", .{compressed.len});
}
pub fn macosResourceHandling(allocator: std.mem.Allocator) !void {
if (std.builtin.os.tag != .macos) return;
// Handle macOS resource forks and extended attributes
const input_path = "/tmp/input.txt";
const output_path = "/tmp/output.gz";
// Check for extended attributes (simplified example)
const input_file = try std.fs.cwd().openFile(input_path, .{});
defer input_file.close();
const file_data = try input_file.readToEndAlloc(allocator, 10 * 1024 * 1024);
defer allocator.free(file_data);
const compressed = try archive.compress(allocator, file_data, .gzip);
defer allocator.free(compressed);
try std.fs.cwd().writeFile(.{ .sub_path = output_path, .data = compressed });
std.debug.print("macOS resource handling completed\n", .{});
}Embedded Systems ​
Memory-Constrained Environments ​
zig
pub fn embeddedOptimizations(allocator: std.mem.Allocator) !void {
// Configuration for embedded systems with limited memory
const config = archive.CompressionConfig.init(.lz4) // Fast, low memory
.withLevel(.fastest) // Minimize processing time
.withBufferSize(4 * 1024) // Small 4KB buffer
.withMemoryLevel(1); // Minimal memory usage
const input = "Embedded system data";
const compressed = try archive.compressWithConfig(allocator, input, config);
defer allocator.free(compressed);
std.debug.print("Embedded optimization: {d} bytes (ratio: {d:.1}%)\n",
.{ compressed.len, @as(f64, @floatFromInt(compressed.len)) / @as(f64, @floatFromInt(input.len)) * 100 });
}
pub fn microcontrollerExample() !void {
// Example for microcontroller with very limited resources
comptime {
if (std.builtin.cpu.arch == .thumb) {
// ARM Cortex-M specific optimizations
@compileLog("Compiling for ARM Cortex-M");
}
}
// Use stack allocation for small buffers
var stack_buffer: [1024]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&stack_buffer);
const allocator = fba.allocator();
const input = "MCU data";
// Use fastest algorithm with minimal memory
const compressed = archive.compress(allocator, input, .lz4) catch |err| switch (err) {
error.OutOfMemory => {
std.debug.print("Not enough memory for compression\n", .{});
return;
},
else => return err,
};
defer allocator.free(compressed);
std.debug.print("Microcontroller compression: {d} bytes\n", .{compressed.len});
}Real-Time Systems ​
zig
pub fn realTimeCompression(allocator: std.mem.Allocator) !void {
// Configuration for real-time systems
const config = archive.CompressionConfig.init(.lz4)
.withLevel(.fastest) // Predictable, fast compression
.withBufferSize(8 * 1024); // Small buffer for low latency
// Simulate real-time data processing
var i: u32 = 0;
while (i < 100) {
const start_time = std.time.nanoTimestamp();
const data = try std.fmt.allocPrint(allocator, "Real-time packet {d}", .{i});
defer allocator.free(data);
const compressed = try archive.compressWithConfig(allocator, data, config);
defer allocator.free(compressed);
const end_time = std.time.nanoTimestamp();
const duration_us = @as(f64, @floatFromInt(end_time - start_time)) / 1000.0;
// Check if compression meets real-time constraints (e.g., < 100μs)
if (duration_us > 100.0) {
std.debug.print("Warning: Compression took {d:.2}μs (> 100μs)\n", .{duration_us});
}
i += 1;
// Simulate real-time interval
std.time.sleep(1 * std.time.ns_per_ms);
}
std.debug.print("Real-time compression test completed\n", .{});
}WebAssembly ​
WASM Optimizations ​
zig
pub fn wasmOptimizations(allocator: std.mem.Allocator) !void {
if (std.builtin.cpu.arch != .wasm32 and std.builtin.cpu.arch != .wasm64) return;
// WebAssembly-specific configuration
const config = archive.CompressionConfig.init(.lz4) // Fast for web environments
.withLevel(.fast) // Balance speed and size
.withBufferSize(32 * 1024); // Moderate buffer for web
const input = "WebAssembly compression data";
const compressed = try archive.compressWithConfig(allocator, input, config);
defer allocator.free(compressed);
std.debug.print("WASM optimization: {d} bytes\n", .{compressed.len});
}
// Export functions for JavaScript interop
export fn compress_for_js(data_ptr: [*]const u8, data_len: usize, output_ptr: [*]u8, output_len: *usize) c_int {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const input_data = data_ptr[0..data_len];
const compressed = archive.compress(allocator, input_data, .lz4) catch return -1;
defer allocator.free(compressed);
if (compressed.len > output_len.*) {
output_len.* = compressed.len;
return -2; // Buffer too small
}
@memcpy(output_ptr[0..compressed.len], compressed);
output_len.* = compressed.len;
return 0; // Success
}Cross-Platform Considerations ​
Endianness Handling ​
zig
pub fn crossPlatformEndianness(allocator: std.mem.Allocator) !void {
const input = "Cross-platform data with endianness considerations";
// Compress data
const compressed = try archive.compress(allocator, input, .gzip);
defer allocator.free(compressed);
// Handle endianness for cross-platform compatibility
const native_endian = std.builtin.cpu.arch.endian();
std.debug.print("Native endianness: {}\n", .{native_endian});
// For network protocols or file formats, ensure consistent byte order
if (compressed.len >= 4) {
const header_bytes = compressed[0..4];
std.debug.print("Header bytes: {X:0>2} {X:0>2} {X:0>2} {X:0>2}\n",
.{ header_bytes[0], header_bytes[1], header_bytes[2], header_bytes[3] });
}
std.debug.print("Cross-platform compression: {d} bytes\n", .{compressed.len});
}Path Handling ​
zig
pub fn crossPlatformPaths(allocator: std.mem.Allocator) !void {
// Handle different path separators across platforms
const separator = std.fs.path.sep;
const input_path = try std.fmt.allocPrint(allocator, "data{c}input.txt", .{separator});
defer allocator.free(input_path);
const output_path = try std.fmt.allocPrint(allocator, "data{c}output.gz", .{separator});
defer allocator.free(output_path);
std.debug.print("Platform paths: {s} -> {s}\n", .{ input_path, output_path });
// Normalize paths for cross-platform compatibility
var normalized_input = try allocator.alloc(u8, input_path.len);
defer allocator.free(normalized_input);
_ = std.fs.path.resolve(allocator, &[_][]const u8{input_path}) catch {
std.debug.print("Path resolution failed\n", .{});
return;
};
}Performance Profiling ​
Platform-Specific Benchmarks ​
zig
pub fn platformBenchmarks(allocator: std.mem.Allocator) !void {
const test_data = "Benchmark data for platform performance testing " ** 100;
const algorithms = [_]archive.Algorithm{ .lz4, .gzip, .zstd };
std.debug.print("Platform: {s}\n", .{@tagName(std.builtin.os.tag)});
std.debug.print("Architecture: {s}\n", .{@tagName(std.builtin.cpu.arch)});
std.debug.print("Algorithm | Time (ms) | Size | Ratio\n");
std.debug.print("----------|-----------|------|------\n");
for (algorithms) |algo| {
const start_time = std.time.nanoTimestamp();
const compressed = try archive.compress(allocator, test_data, algo);
defer allocator.free(compressed);
const end_time = std.time.nanoTimestamp();
const duration_ms = @as(f64, @floatFromInt(end_time - start_time)) / 1_000_000.0;
const ratio = @as(f64, @floatFromInt(compressed.len)) / @as(f64, @floatFromInt(test_data.len)) * 100;
std.debug.print("{s:>9} | {d:>9.2} | {d:>4} | {d:>5.1}%\n",
.{ @tagName(algo), duration_ms, compressed.len, ratio });
}
}Memory Usage Profiling ​
zig
pub fn platformMemoryProfile(allocator: std.mem.Allocator) !void {
const initial_memory = getCurrentMemoryUsage();
const test_data = try allocator.alloc(u8, 1024 * 1024); // 1MB
defer allocator.free(test_data);
// Fill with test pattern
for (test_data, 0..) |*byte, i| {
byte.* = @intCast(i % 256);
}
const before_compression = getCurrentMemoryUsage();
const compressed = try archive.compress(allocator, test_data, .zstd);
defer allocator.free(compressed);
const after_compression = getCurrentMemoryUsage();
std.debug.print("Memory usage profile:\n", .{});
std.debug.print(" Initial: {d} KB\n", .{initial_memory / 1024});
std.debug.print(" Before compression: {d} KB\n", .{before_compression / 1024});
std.debug.print(" After compression: {d} KB\n", .{after_compression / 1024});
std.debug.print(" Peak usage: {d} KB\n", .{(after_compression - initial_memory) / 1024});
}
fn getCurrentMemoryUsage() usize {
// Platform-specific memory usage detection
switch (std.builtin.os.tag) {
.linux => {
// Read from /proc/self/status on Linux
const status_file = std.fs.openFileAbsolute("/proc/self/status", .{}) catch return 0;
defer status_file.close();
var buffer: [4096]u8 = undefined;
const bytes_read = status_file.readAll(&buffer) catch return 0;
// Parse VmRSS line (simplified)
var lines = std.mem.split(u8, buffer[0..bytes_read], "\n");
while (lines.next()) |line| {
if (std.mem.startsWith(u8, line, "VmRSS:")) {
// Extract memory value (simplified parsing)
var parts = std.mem.split(u8, line, " ");
_ = parts.next(); // Skip "VmRSS:"
if (parts.next()) |value_str| {
return std.fmt.parseInt(usize, std.mem.trim(u8, value_str, " \t"), 10) catch 0;
}
}
}
return 0;
},
.windows => {
// Windows memory usage would require Win32 API calls
return 0;
},
.macos => {
// macOS memory usage would require system calls
return 0;
},
else => return 0,
}
}Build Configuration ​
Platform-Specific Build Options ​
zig
// In build.zig
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "archive-example",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// Platform-specific optimizations
switch (target.result.os.tag) {
.windows => {
// Windows-specific build options
exe.linkSystemLibrary("kernel32");
exe.addCSourceFile(.{
.file = b.path("src/windows_specific.c"),
.flags = &[_][]const u8{"-DWINDOWS_BUILD"},
});
},
.linux => {
// Linux-specific build options
exe.linkSystemLibrary("c");
exe.addCSourceFile(.{
.file = b.path("src/linux_specific.c"),
.flags = &[_][]const u8{"-DLINUX_BUILD"},
});
},
.macos => {
// macOS-specific build options
exe.linkFramework("Foundation");
exe.addCSourceFile(.{
.file = b.path("src/macos_specific.c"),
.flags = &[_][]const u8{"-DMACOS_BUILD"},
});
},
else => {},
}
// Architecture-specific optimizations
switch (target.result.cpu.arch) {
.x86_64 => {
exe.root_module.addCMacro("ARCH_X86_64", "1");
},
.aarch64 => {
exe.root_module.addCMacro("ARCH_AARCH64", "1");
},
.wasm32, .wasm64 => {
exe.root_module.addCMacro("ARCH_WASM", "1");
},
else => {},
}
b.installArtifact(exe);
}Best Practices ​
Platform-Specific Guidelines ​
- Test on target platforms - Don't assume cross-platform compatibility
- Use appropriate algorithms - Consider platform constraints
- Handle endianness - Ensure consistent byte order for data exchange
- Optimize for platform - Use platform-specific optimizations
- Consider memory constraints - Embedded systems need special attention
- Profile performance - Benchmark on actual target hardware
- Handle platform differences - File systems, paths, line endings
- Use conditional compilation - Platform-specific code paths
Universal Configuration ​
zig
pub fn universalConfig() archive.CompressionConfig {
// Configuration that works well across all platforms
return archive.CompressionConfig.init(.lz4)
.withLevel(.fast) // Good balance everywhere
.withBufferSize(64 * 1024) // Reasonable for most platforms
.withMemoryLevel(6); // Moderate memory usage
}
pub fn platformOptimizedConfig() archive.CompressionConfig {
// Choose configuration based on platform capabilities
switch (std.builtin.os.tag) {
.windows, .macos, .linux => {
// Desktop platforms - can use more resources
return archive.CompressionConfig.init(.zstd)
.withZstdLevel(10)
.withBufferSize(256 * 1024)
.withMemoryLevel(8);
},
.freestanding => {
// Embedded/bare metal - minimal resources
return archive.CompressionConfig.init(.lz4)
.withLevel(.fastest)
.withBufferSize(4 * 1024)
.withMemoryLevel(1);
},
else => {
// Other platforms - conservative settings
return archive.CompressionConfig.init(.gzip)
.withLevel(.default)
.withBufferSize(32 * 1024)
.withMemoryLevel(4);
},
}
}Next Steps ​
- Review Memory Management for platform-specific memory optimization
- Check Threading for platform-specific concurrency
- Explore Error Handling for platform-specific error conditions
- See Examples for platform-specific usage patterns
