Skip to main content

Distributed intelligent compression for long-term data archival

Project description

❄️ Permafrost Framework

PyPI version Tests License Python Docs PyPI Downloads

Plataforma distribuída de compressão inteligente para arquivamento digital de longo prazo.

Comprime dados históricos com até 33× ratio — e deixa você consultar só o que precisa, sem descomprimir tudo.

Documentação · Quick Start · Benchmarks · API · Contribuir


O que é o Permafrost?

Dados corporativos históricos — CSVs, JSONL, dumps de MongoDB — ficam anos em cold storage (S3 Glacier, Azure Archive) pagando caro. O problema: se você precisa buscar os dados de um único mês em um arquivo de 10 GB, é necessário descomprimir tudo.

O Permafrost resolve isso com dois mecanismos:

  1. Preditores colunares — transforma os dados semanticamente antes da compressão (delta, zigzag, timestamps, categorias), atingindo ratios muito superiores ao LZMA2 puro
  2. Sparse index — índice embutido no arquivo que aponta o byte exato de cada chunk, permitindo leitura seletiva via HTTP Range Request sem baixar o arquivo inteiro
CSV bruto:                  5.85 MB
CSV + LZMA2 puro:           0.499 MB  (ratio 5.97×)
CSV + Permafrost + LZMA2:   0.284 MB  (ratio 10.50×)  ← +76% pelos preditores colunares

Funcionalidades

  • Alta compressão — preditores colunares (delta_zigzag, lag1_zigzag, ts_delta_s, category_u8, raw_text) antes de Zstd / LZMA2 / ZPAQ
  • Leitura seletiva — sparse index embutido permite filter={"ano": 2023} sem descomprimir o resto
  • Integridade garantida — SHA-256 por chunk, detectado antes de qualquer decompressão
  • Auto-descritivo — schema Arrow completo embutido no arquivo; legível em 2040 sem documentação externa
  • Cloud-native — suporte nativo a S3, Google Cloud Storage e Azure Blob Storage com HTTP Range Requests
  • Catalog DuckDB — busca em metadados de centenas de arquivos no S3 sem baixar nenhum
  • Streaming — processa datasets maiores que a RAM com freeze_file() e thaw_iter()
  • Cluster distribuído — Master + Workers via FastAPI; processa 1 TB em paralelo com N workers
  • Spark DataSource v2 — integração nativa com PySpark 4.0+ com pushdown via sparse index
  • CLI completapermafrost freeze / thaw / audit / verify / catalog com output rich

Instalação

# Instalação básica
pip install permafrost-framework

# Com suporte a AWS S3
pip install "permafrost-framework[s3]"

# Com suporte a Google Cloud Storage
pip install "permafrost-framework[gcs]"

# Com suporte a Azure Blob Storage
pip install "permafrost-framework[azure]"

# Todos os provedores cloud
pip install "permafrost-framework[all-cloud]"

# Com Apache Spark
pip install "permafrost-framework[spark]"

Requisitos: Python 3.10+


Quick Start

Freeze e Thaw básico

import permafrost as pf
import pandas as pd

df = pd.read_csv("vendas_historico.csv")

# Comprimir — retorna métricas
metrics = pf.freeze(df, "vendas.permafrost", codec=pf.CODEC_LZMA2, partition_by="ano")
print(f"Ratio: {metrics['ratio']:.2f}×  |  {metrics['original_mb']:.1f} MB → {metrics['stored_mb']:.1f} MB")
# Ratio: 8.37×  |  5.85 MB → 0.68 MB

# Descomprimir tudo
df_back = pf.thaw("vendas.permafrost", verify=True)

# Descomprimir só 2023 — lê apenas os chunks daquele ano
df_2023 = pf.thaw("vendas.permafrost", filter={"ano": 2023})

Streaming (datasets maiores que a RAM)

# Freeze de arquivo grande sem carregar na memória
pf.freeze_file("100gb.csv", "saida.permafrost", chunk_rows=50_000)

# Thaw iterativo em batches
for batch_df in pf.thaw_iter("saida.permafrost", batch_size=50_000):
    processar(batch_df)

Cloud (S3, GCS, Azure)

# Upload direto para S3
pf.freeze_to(df, "s3://meu-bucket/dados/vendas.permafrost")

# Leitura seletiva do S3 via HTTP Range Request — não baixa o arquivo inteiro
df_2023 = pf.thaw_from("s3://meu-bucket/dados/vendas.permafrost", filter={"ano": 2023})

# Auditoria remota sem baixar nada
info = pf.audit_remote("s3://meu-bucket/dados/vendas.permafrost")

Catalog — busca em múltiplos arquivos

cat = pf.PermafrostCatalog("catalog.db")
cat.register_dir("s3://meu-bucket/cold/")   # indexa metadados sem baixar

# Busca por nome, codec, lossless
resultados = cat.search(name="vendas", lossless_only=True)

# Relatório de custo estimado no Glacier Deep Archive
cat.cost_report("glacier_deep")

# Verificação de integridade em massa
cat.integrity_check()

Cluster distribuído

from permafrost import PermafrostClient

client = PermafrostClient("http://master:8700")
job_id = client.freeze("dados_grandes.csv", "s3://bucket/saida.permafrost")
status = client.wait(job_id)
print(status)  # {"status": "done", "ratio": 10.2, "workers_used": 4}

Apache Spark

from permafrost.spark import register

register(spark)
df = spark.read.format("permafrost").load("s3://bucket/dados.permafrost")
df.filter(df.ano == 2023).show()   # pushdown via sparse index — não lê chunks desnecessários

CLI

# Comprimir
permafrost freeze vendas.csv vendas.permafrost --codec lzma2 --partition-by ano

# Descomprimir com filtro
permafrost thaw vendas.permafrost --filter '{"ano": 2023}' --output vendas_2023.csv

# Auditoria (sem descomprimir)
permafrost audit vendas.permafrost

# Verificar integridade de todos os chunks
permafrost verify vendas.permafrost

# Catalog
permafrost catalog register s3://bucket/cold/
permafrost catalog search --name vendas
permafrost catalog cost-report --tier glacier_deep

Benchmarks

Medidos em hardware real (não estimativas):

Dataset Original .permafrost Ratio Codec
CSV corporativo (80k linhas × 9 colunas) 5.85 MB 0.678 MB 8.37× LZMA2
JSONL social media (5k posts) 1.44 MB 0.043 MB 33× LZMA2
Streaming 300k linhas ~97 MB est. 1.018 MB 95× LZMA2
CSV numérico (delta_zigzag) 5.85 MB 0.284 MB 10.50× LZMA2

Custo em cloud storage:

Volume S3 Glacier Deep Archive sem Permafrost Com Permafrost Economia
1 TB/mês $0.99 $0.12 -88%
10 TB/mês $9.90 $1.20 -88%
100 TB/mês $99.00 $11.88 -88%

Por que o Permafrost comprime melhor que LZMA2 puro?

Os preditores colunares transformam os dados antes do codec:

  • delta_zigzag — para séries numéricas: guarda a diferença entre valores consecutivos (muito menor e mais compressível)
  • lag1_zigzag — para séries com tendência linear
  • ts_delta_s — para timestamps: guarda o delta em segundos
  • category_u8 — para colunas categóricas: substitui strings por inteiros de 1 byte
  • raw_text — para texto livre: passa direto para o codec

Formato .permafrost v1.2

O formato é auto-descritivo — legível sem documentação externa:

[MAGIC: "PRMS" 4B]              identificação
[VERSION: 1.2 2B]
[FLAGS: bitmask 2B]             delta | quantize | chunked | predictor | index
[CODEC_ID: 1B]                  0x01=Zstd | 0x02=LZMA2 | 0x03=ZPAQ
[QUANT: 1B]                     0x00=lossless | 0x01=high | 0x02=medium | 0x03=low
[N_CHUNKS: 2B]
[SCHEMA ARROW: var]             schema completo embutido
[PREDICTOR MANIFEST: JSON]      preditor e metadados por coluna
[COMMENT: var]
[FREEZE_TIMESTAMP: int64]
[ORIGINAL_ROWS: uint64]
[HEADER SHA-256: 32B]           integridade do header
[CHUNK_0: u32_len + data + sha256] × N
[SPARSE INDEX: JSON]            byte_offset de cada chunk
[INDEX_SHA256: 32B]
[EOF: "SMRP" 4B]                PRMS invertido

API Reference

Core

Função Descrição
pf.freeze(df, path, ...) Comprime um DataFrame para arquivo .permafrost
pf.thaw(path, filter=None, verify=False) Descomprime; filter usa sparse index
pf.audit(path) Retorna metadados sem descomprimir

Streaming

Função Descrição
pf.freeze_file(csv_path, out_path, chunk_rows=50_000) Comprime CSV grande sem carregar na memória
pf.freeze_stream(cursor_gen, out_path) Comprime a partir de um generator
pf.thaw_iter(path, batch_size=50_000) Descomprime em batches iterativos

Cloud

Função Descrição
pf.freeze_to(df, uri) Comprime e envia direto para S3/GCS/Azure
pf.thaw_from(uri, filter=None) Descomprime do cloud com Range Request
pf.audit_remote(uri) Audita arquivo remoto sem baixar tudo
pf.storage_from_uri(uri) Retorna o adapter de storage adequado para a URI

Catalog

Classe/Método Descrição
PermafrostCatalog(db_path) Cria ou abre um catalog DuckDB
.register_dir(path_or_uri) Indexa todos os .permafrost de um diretório
.search(name, lossless_only, codec) Busca por metadados
.cost_report(tier) Estima custo mensal por tier de storage
.integrity_check() Verifica SHA-256 de todos os arquivos indexados

Cluster

Classe/Método Descrição
PermafrostMaster(host, port) Inicia o nó master do cluster
PermafrostWorker(master_url) Inicia um worker que se registra no master
PermafrostClient(master_url) Cliente para submeter jobs ao cluster
client.freeze(input, output) Submete job de freeze ao cluster
client.wait(job_id) Aguarda conclusão do job

Codecs disponíveis

Constante Descrição
pf.CODEC_ZSTD Zstandard — rápido, bom ratio
pf.CODEC_LZMA2 LZMA2 — maior ratio, mais lento
pf.CODEC_ZPAQ ZPAQ — ratio máximo, muito lento

Testes

A suite cobre 268+ cenários incluindo edge cases, benchmarks mínimos, fidelidade total e tolerância a falhas:

test_freeze_thaw.py              freeze/thaw/audit/integridade/sparse index
test_sparse_index.py             chunked freeze, thaw seletivo, bit-rot detection
test_catalog.py                  register, search, thaw, cost, integrity, SQL
test_cluster.py                  health, lifecycle, concorrência, cancelamento
test_comprehensive.py            edge cases, todos os codecs, benchmarks mínimos
test_fidelidade_total.py         100% linha por linha, distribuições, multi round-trip
test_concorrencia.py             10 threads simultâneas, freeze+thaw paralelos
test_predictor_edge_cases.py     variância zero, 256 cats, timestamps extremos
test_cluster_fault_tolerance.py  retry, sem workers, 10 jobs paralelos
test_formato_binario_spec.py     byte a byte do formato, SHA-256, sparse index
test_schema_detector_stress.py   50% campos ausentes, tipos misturados, 100 campos
test_cli_cobertura.py            todos os comandos CLI
test_performance_regression.py   ratio ≥8×, thaw <2s, audit <50ms

Status atual dos testes: Tests


Docker — Cluster em produção

# Subir cluster com 4 workers
docker-compose up --scale worker=4

# Build local
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up --scale worker=2

Imagens disponíveis no Docker Hub:

  • caua-ferreira/permafrost-master
  • caua-ferreira/permafrost-worker

Contribuindo

Contribuições são bem-vindas! Veja o guia de contribuição.

git clone https://github.com/caua-ferreira/permafrost-framework
cd permafrost-framework
pip install -e ".[dev]"
pytest tests/ -v

Licença

Apache License 2.0 — veja LICENSE.


Feito com ❄️ para dados que precisam durar décadas.

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

permafrost_framework-0.6.1.tar.gz (96.9 kB view details)

Uploaded Source

Built Distribution

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

permafrost_framework-0.6.1-py3-none-any.whl (55.2 kB view details)

Uploaded Python 3

File details

Details for the file permafrost_framework-0.6.1.tar.gz.

File metadata

  • Download URL: permafrost_framework-0.6.1.tar.gz
  • Upload date:
  • Size: 96.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for permafrost_framework-0.6.1.tar.gz
Algorithm Hash digest
SHA256 1f995233d48549675346b32e952d06da251a6ab93d02e2b86d655d0c0887733f
MD5 5187b21af1c38c596c4299136826a09a
BLAKE2b-256 aa7370415b2316817fb044c5f0b925c73d28f4555592897cd5fe4b36012c1f83

See more details on using hashes here.

File details

Details for the file permafrost_framework-0.6.1-py3-none-any.whl.

File metadata

File hashes

Hashes for permafrost_framework-0.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 81a8ddd0029ea3f546e03c175c929cf2a68a8078d8fb2b222ec5c66ad1c2f5fd
MD5 27342c6e7c418adeacd867ce0c94fa2e
BLAKE2b-256 618ccee5c47e1e067343eec8246a33fda308a9006ac56fb01f3554f050f1563f

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