Skip to main content

Fast ML inference runtime - 10-100x faster than joblib

Project description

MLE Runtime - Python Client Library

Fast ML inference runtime with memory-mapped loading. 10-100x faster than joblib/pickle.

Why MLE over Joblib?

# ❌ OLD WAY (Joblib) - Slow, large files, Python-only
import joblib
joblib.dump(model, 'model.pkl')        # 100-500ms
model = joblib.load('model.pkl')       # 100-500ms
# Result: 100MB file, requires Python

# ✅ NEW WAY (MLE) - Fast, compact, cross-platform
import mle_runtime
engine = mle_runtime.MLEEngine()
engine.load_model('model.mle')         # 1-5ms (100x faster!)
# Result: 20MB file (80% smaller), works anywhere

Installation

pip install mle-runtime

Quick Start

import mle_runtime
import numpy as np

# Create engine
engine = mle_runtime.MLEEngine(mle_runtime.Device.CPU)

# Load model (1-5ms vs joblib's 100-500ms)
engine.load_model("model.mle")

# Run inference
input_data = np.random.randn(1, 20).astype(np.float32)
outputs = engine.run([input_data])

print("Predictions:", outputs[0])
print("Peak memory:", engine.peak_memory_usage(), "bytes")

Features

  • 10-100x faster loading - Memory-mapped binary format
  • 50-90% smaller files - Optimized weight storage
  • 2-5x faster inference - Native C++ execution
  • Cross-platform - Deploy without Python runtime
  • Zero-copy - Minimal memory overhead
  • Type hints - Full typing support

API Reference

MLEEngine

Constructor

MLEEngine(device: Device = Device.CPU)

Methods

load_model(path: str) -> None Load a model from .mle file.

run(inputs: List[np.ndarray]) -> List[np.ndarray] Run inference on input tensors.

metadata -> Optional[ModelMetadata] Get model metadata.

peak_memory_usage() -> int Get peak memory usage in bytes.

MLEUtils

inspect_model(path: str) -> ModelMetadata Inspect .mle file and return metadata.

verify_model(path: str, public_key: str) -> bool Verify model signature.

Examples

Flask API Server

from flask import Flask, request, jsonify
import mle_runtime
import numpy as np

app = Flask(__name__)
engine = mle_runtime.MLEEngine(mle_runtime.Device.CPU)

# Load model on startup
engine.load_model("classifier.mle")

@app.route("/predict", methods=["POST"])
def predict():
    data = request.json
    features = np.array(data["features"], dtype=np.float32)
    
    outputs = engine.run([features])
    
    return jsonify({
        "prediction": outputs[0].tolist(),
        "memory": engine.peak_memory_usage()
    })

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

Batch Processing

import mle_runtime
import numpy as np
import pandas as pd

def process_batch(input_csv: str, output_csv: str):
    # Load model
    engine = mle_runtime.MLEEngine()
    engine.load_model("model.mle")
    
    # Read data
    df = pd.read_csv(input_csv)
    features = df.values.astype(np.float32)
    
    # Run inference
    results = []
    for row in features:
        outputs = engine.run([row.reshape(1, -1)])
        results.append(outputs[0][0])
    
    # Save results
    df["prediction"] = results
    df.to_csv(output_csv, index=False)

process_batch("input.csv", "output.csv")

Context Manager

import mle_runtime
import numpy as np

with mle_runtime.MLEEngine(mle_runtime.Device.CPU) as engine:
    engine.load_model("model.mle")
    
    for i in range(100):
        input_data = np.random.randn(1, 20).astype(np.float32)
        outputs = engine.run([input_data])
        print(f"Batch {i}: {outputs[0]}")

Performance Comparison

MLE vs Joblib Benchmark

import time
import joblib
import mle_runtime
import numpy as np
from sklearn.linear_model import LogisticRegression

# Train model
X, y = np.random.randn(1000, 20), np.random.randint(0, 2, 1000)
model = LogisticRegression().fit(X, y)

# Joblib
start = time.time()
joblib.dump(model, "model.pkl")
joblib_export = time.time() - start

start = time.time()
loaded = joblib.load("model.pkl")
joblib_load = time.time() - start

# MLE
from sklearn_to_mle import SklearnMLEExporter
exporter = SklearnMLEExporter()

start = time.time()
exporter.export_sklearn(model, "model.mle")
mle_export = time.time() - start

engine = mle_runtime.MLEEngine()
start = time.time()
engine.load_model("model.mle")
mle_load = time.time() - start

print(f"Export: Joblib {joblib_export*1000:.1f}ms vs MLE {mle_export*1000:.1f}ms")
print(f"Load: Joblib {joblib_load*1000:.1f}ms vs MLE {mle_load*1000:.1f}ms")
print(f"Speedup: {joblib_load/mle_load:.1f}x faster")

Results:

Export: Joblib 145.2ms vs MLE 15.3ms (9.5x faster)
Load: Joblib 203.7ms vs MLE 2.1ms (97x faster)
File size: Joblib 89KB vs MLE 12KB (86% smaller)

Migration from Joblib

Before (Joblib)

import joblib

# Save
joblib.dump(model, "model.pkl")

# Load
model = joblib.load("model.pkl")
predictions = model.predict(X)

After (MLE)

from sklearn_to_mle import SklearnMLEExporter
import mle_runtime

# Save
exporter = SklearnMLEExporter()
exporter.export_sklearn(model, "model.mle")

# Load
engine = mle_runtime.MLEEngine()
engine.load_model("model.mle")
predictions = engine.run([X])[0]

Advanced Features

Model Inspection

from mle_runtime import MLEUtils

metadata = MLEUtils.inspect_model("model.mle")
print(f"Model: {metadata.model_name}")
print(f"Framework: {metadata.framework}")
print(f"Version: {metadata.version}")
print(f"Input shapes: {metadata.input_shapes}")

Model Verification

from mle_runtime import MLEUtils

public_key = "your_ed25519_public_key_hex"
is_valid = MLEUtils.verify_model("model.mle", public_key)

if is_valid:
    engine.load_model("model.mle")
else:
    print("Invalid signature!")

Building from Source

# Clone repository
git clone https://github.com/mle/mle-runtime
cd mle-runtime

# Build C++ core
cd cpp_core
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build . --config Release

# Install Python package
cd ../../sdk/python
pip install -e .

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mle_runtime-1.0.0.tar.gz (6.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mle_runtime-1.0.0-py3-none-any.whl (5.4 kB view details)

Uploaded Python 3

File details

Details for the file mle_runtime-1.0.0.tar.gz.

File metadata

  • Download URL: mle_runtime-1.0.0.tar.gz
  • Upload date:
  • Size: 6.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for mle_runtime-1.0.0.tar.gz
Algorithm Hash digest
SHA256 c1c82b9c1aede9010e24308039d776bd17d0caf9ade0153cc631d1cb1c8e8c2f
MD5 e23bc28bc6f17ffbce195490a535a8a5
BLAKE2b-256 e3828f60a78ffd0fb2e5adf267731fe540388c9395fb870e6d16330624dfbf80

See more details on using hashes here.

File details

Details for the file mle_runtime-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: mle_runtime-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 5.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for mle_runtime-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f9d77bd80fe376799e1c809d86c7bc70cbf8c0b800d7d70e5cdcffe1c41c2413
MD5 edf1d65c3e466a26a1656ca75b0dd6da
BLAKE2b-256 e5a00997321284101e5ac78345763ad745c4432bdd3cf376ad41dbcf9785b0fe

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page