---
title: "HeliosDB WASM Performance Tuning Guide"
---

# HeliosDB WASM Performance Tuning Guide

:::caution[Planned design: not yet available in the server]
The current `heliosdb-full` server does not run WASM or polyglot (JavaScript,
Python, Rust) stored procedures: the WASM runtime is not wired into the server.
This page describes the design for this upcoming feature, and its SQL (for
example `LANGUAGE wasm`, security profiles and syscall filters) is not accepted
by the current server. Only the
[Go SDK](/docs/full/guides/features/wasm_procedures_language_sdks/#go-sdk) is
published. See the
[WASM Procedures Quick Start](/docs/full/guides/features/wasm_procedures_quick_start/)
for what works today.
:::

## Overview

This guide covers performance optimization techniques for HeliosDB stored procedures, including:
- JIT compilation optimization
- Function result caching
- Parallel execution
- Memory management
- Profiling and benchmarking

## Performance Architecture

### Three-Tier Caching System

```
L1: Instance Pool (Hot instances, <1ms access)
L2: Module Cache (Compiled modules, ~1ms access)
L3: AOT Cache (Persistent disk cache, ~10ms access)
```

### Execution Pipeline

```
Request → Cache Check → Module Load → Instantiation → Execution → Result Cache
   |         |            |              |            |            |
  <1µs      <1ms         ~1ms          ~5ms        varies       <1ms
```

## JIT Compilation Optimization

### Optimization Levels

```sql
-- Fast compilation, less optimization (low latency)
ALTER FUNCTION quick_function
SET jit_mode = 'low_latency';

-- Balanced (default)
ALTER FUNCTION normal_function
SET jit_mode = 'balanced';

-- Aggressive optimization (best performance)
ALTER FUNCTION heavy_compute
SET jit_mode = 'fast';
```

### Performance Impact

| JIT Mode | Compilation Time | Execution Speed | Best For |
|----------|------------------|-----------------|----------|
| low_latency | ~1ms | 1.0x | Short-lived functions |
| balanced | ~5ms | 1.5x | General purpose |
| fast | ~20ms | 2.0-3.0x | Long-running compute |

### When to Use Each Mode

**Low Latency:**
- Functions called frequently with short execution time
- Request/response handlers
- Simple data transformations

**Balanced (Default):**
- General-purpose functions
- Mixed workloads
- Moderate execution time (10-100ms)

**Fast:**
- CPU-intensive algorithms
- Long-running computations (>100ms)
- Batch processing

## Function Result Caching

### Enable Caching

```sql
ALTER FUNCTION expensive_calculation
SET cache_ttl = 300;  -- Cache for 5 minutes

ALTER FUNCTION expensive_calculation
SET cache_size = 1000;  -- Maximum 1000 cached entries
```

### Cache Configuration

```sql
-- Aggressive caching
ALTER FUNCTION lookup_function
SET cache_ttl = 3600,      -- 1 hour
    cache_size = 10000,     -- 10k entries
    cache_strategy = 'lru'; -- Least Recently Used eviction

-- Minimal caching
ALTER FUNCTION volatile_function
SET cache_ttl = 10,         -- 10 seconds
    cache_size = 100,
    cache_strategy = 'lru';
```

### Cache Performance

```javascript
// First call: ~50ms (no cache)
calculate_complex(42);

// Second call: <1ms (cache hit)
calculate_complex(42);
```

### Cache Hit Rate

```sql
SELECT
    function_name,
    cache_hits,
    cache_misses,
    (cache_hits::float / (cache_hits + cache_misses)) * 100 as hit_rate
FROM heliosdb.function_cache_stats
ORDER BY hit_rate DESC;
```

### When to Cache

**Good Candidates:**
- Pure functions (IMMUTABLE)
- Expensive computations
- External API calls
- Database aggregations
- Complex transformations

**Poor Candidates:**
- VOLATILE functions
- Random number generation
- Time-dependent calculations
- User-specific data (unless partitioned)

## Parallel Execution

### Batch Execution

```javascript
// Sequential (slow): ~100ms total
for (let i = 0; i < 10; i++) {
    await db.execute('process_item', [items[i]]);
}

// Parallel (fast): ~10ms total
const results = await db.executeParallel(
    items.map(item => ({
        function: 'process_item',
        args: [item]
    }))
);
```

### Concurrency Control

```sql
-- Set maximum concurrent executions
ALTER FUNCTION cpu_intensive
SET max_concurrency = 4;

-- Set queue size for pending executions
ALTER FUNCTION cpu_intensive
SET queue_size = 100;
```

### Parallel Execution Patterns

**Map-Reduce:**

```javascript
// Map phase (parallel)
const mapped = await db.executeParallel(
    items.map(item => ({
        function: 'map_function',
        args: [item]
    }))
);

// Reduce phase (sequential)
const result = await db.execute('reduce_function', [mapped]);
```

**Pipeline:**

```javascript
// Stage 1: Parallel preprocessing
const preprocessed = await db.executeParallel(
    items.map(item => ({ function: 'preprocess', args: [item] }))
);

// Stage 2: Parallel processing
const processed = await db.executeParallel(
    preprocessed.map(item => ({ function: 'process', args: [item] }))
);

// Stage 3: Parallel postprocessing
const final = await db.executeParallel(
    processed.map(item => ({ function: 'postprocess', args: [item] }))
);
```

## Memory Management

### Memory Optimization

```javascript
// BAD: Creates many intermediate arrays
function process_large_array(items) {
    return items
        .filter(x => x > 0)      // New array
        .map(x => x * 2)         // New array
        .map(x => ({ value: x })) // New array of objects
        .filter(x => x.value < 1000); // New array
}

// GOOD: Single pass, minimal allocations
function process_large_array_optimized(items) {
    const result = [];
    for (let x of items) {
        if (x > 0) {
            const doubled = x * 2;
            if (doubled < 1000) {
                result.push({ value: doubled });
            }
        }
    }
    return result;
}
```

### Memory Limits

```sql
-- Increase memory limit for data-intensive function
ALTER FUNCTION process_large_dataset
SET max_memory_bytes = 67108864;  -- 64MB

-- Decrease for lightweight function
ALTER FUNCTION simple_calc
SET max_memory_bytes = 4194304;   -- 4MB
```

### Streaming Results

```javascript
// BAD: Load entire result set into memory
function get_all_users() {
    const result = heliosdb.query('SELECT * FROM users');
    return result.rows;  // Could be millions of rows
}

// GOOD: Stream results
async function* stream_users() {
    const BATCH_SIZE = 100;
    let offset = 0;

    while (true) {
        const batch = heliosdb.query(
            'SELECT * FROM users LIMIT ? OFFSET ?',
            [BATCH_SIZE, offset]
        );

        if (batch.rows.length === 0) break;

        for (let row of batch.rows) {
            yield row;
        }

        offset += BATCH_SIZE;
    }
}
```

## Profiling and Benchmarking

### Built-in Profiling

```sql
-- Enable profiling
ALTER FUNCTION my_function
SET profiling = true;

-- Execute function
SELECT my_function(args);

-- View profiling results
SELECT * FROM heliosdb.function_profile('my_function');
```

Profiling output:
```
function_name     | my_function
total_time_ms     | 47.3
compilation_time  | 8.2
execution_time    | 35.1
cache_time        | 4.0
memory_peak_mb    | 12.5
instructions      | 45672134
```

### Performance Metrics

```sql
SELECT
    function_name,
    call_count,
    avg_execution_time_ms,
    p50_execution_time_ms,
    p95_execution_time_ms,
    p99_execution_time_ms,
    max_execution_time_ms,
    avg_memory_mb,
    cache_hit_rate
FROM heliosdb.function_stats
WHERE function_name = 'my_function';
```

### Benchmarking

```javascript
// Benchmark helper
function benchmark(fn, iterations = 100) {
    const start = Date.now();

    for (let i = 0; i < iterations; i++) {
        fn();
    }

    const elapsed = Date.now() - start;
    const avg = elapsed / iterations;

    heliosdb.log(`Benchmark: ${iterations} iterations in ${elapsed}ms (avg: ${avg}ms)`);
}

// Usage
benchmark(() => expensive_calculation(42), 1000);
```

## Optimization Techniques

### 1. Minimize Function Calls

```javascript
// BAD: Multiple function calls
function process_items(items) {
    return items.map(item => {
        const validated = validate_item(item);   // Function call
        const transformed = transform_item(validated); // Function call
        return formatted_item(transformed);       // Function call
    });
}

// GOOD: Inline processing
function process_items_optimized(items) {
    return items.map(item => {
        // Inline validation
        if (!item || !item.id) return null;

        // Inline transformation
        const transformed = {
            id: item.id,
            name: item.name.toUpperCase()
        };

        // Inline formatting
        return `${transformed.id}: ${transformed.name}`;
    }).filter(x => x !== null);
}
```

### 2. Use Appropriate Data Structures

```javascript
// BAD: O(n) lookup for each item
function find_users(user_ids) {
    const all_users = heliosdb.query('SELECT * FROM users').rows;

    return user_ids.map(id =>
        all_users.find(u => u.id === id)  // O(n) for each
    );
}

// GOOD: O(1) lookup with Map
function find_users_optimized(user_ids) {
    const all_users = heliosdb.query('SELECT * FROM users').rows;
    const user_map = new Map(all_users.map(u => [u.id, u]));

    return user_ids.map(id => user_map.get(id));
}
```

### 3. Batch Database Operations

```javascript
// BAD: Multiple queries (N+1 problem)
function get_user_orders(user_ids) {
    return user_ids.map(user_id => {
        const orders = heliosdb.query(
            'SELECT * FROM orders WHERE user_id = ?',
            [user_id]
        ).rows;
        return { user_id, orders };
    });
}

// GOOD: Single query
function get_user_orders_optimized(user_ids) {
    const placeholders = user_ids.map(() => '?').join(',');
    const all_orders = heliosdb.query(
        `SELECT * FROM orders WHERE user_id IN (${placeholders})`,
        user_ids
    ).rows;

    // Group by user_id
    const grouped = new Map();
    for (let order of all_orders) {
        if (!grouped.has(order.user_id)) {
            grouped.set(order.user_id, []);
        }
        grouped.get(order.user_id).push(order);
    }

    return user_ids.map(user_id => ({
        user_id,
        orders: grouped.get(user_id) || []
    }));
}
```

### 4. Lazy Evaluation

```javascript
// GOOD: Only compute what's needed
function find_first_match(items, predicate) {
    for (let item of items) {
        if (predicate(item)) {
            return item;  // Stop as soon as match found
        }
    }
    return null;
}

// BAD: Compute everything
function find_first_match_bad(items, predicate) {
    const all_matches = items.filter(predicate);
    return all_matches[0] || null;
}
```

## Performance Checklist

Before deploying to production:

- [ ] JIT mode configured appropriately
- [ ] Caching enabled for expensive functions
- [ ] Cache TTL and size tuned
- [ ] Resource limits configured
- [ ] Parallel execution used for batch operations
- [ ] Memory allocations minimized
- [ ] Database operations batched
- [ ] Appropriate data structures used
- [ ] Profiling data reviewed
- [ ] Benchmarks meet SLA requirements

## Performance Targets

| Function Type | Target Latency | Target Throughput |
|---------------|----------------|-------------------|
| Simple | <1ms | >10,000 req/s |
| Medium | <10ms | >1,000 req/s |
| Complex | <100ms | >100 req/s |
| Batch | <1s | >10 batches/s |

## Troubleshooting

### High Latency

1. Check cache hit rate
2. Review JIT optimization level
3. Profile execution time breakdown
4. Check for N+1 database queries
5. Review memory allocations

### Low Throughput

1. Enable parallel execution
2. Increase max_concurrency
3. Pre-warm instance pool
4. Batch requests
5. Optimize hot paths

### High Memory Usage

1. Check for memory leaks
2. Reduce data structure size
3. Use streaming for large datasets
4. Decrease memory limits
5. Profile memory allocations

## Conclusion

Performance optimization is an iterative process. Start with profiling to identify bottlenecks, apply appropriate optimizations, and measure the results. The three-tier caching system, JIT compilation options, and parallel execution capabilities are the main tools for performance while keeping security and isolation.
