
SQLite VFS com consultas JOIN a frio em menos de 100ms a partir do S3 + compressão e criptografia em nível de página
turbolite é um VFS SQLite em Rust que atende buscas pontuais e joins diretamente do S3 com latência a frio inferior a 250 ms.
Este repositório é um workspace Cargo com dois crates:
turbolite — Biblioteca puramente Rust. VFS SQLite com compressão em nível de página, criptografia e tiering para S3.turbolite-ffi — FFI C / extensão carregável + bindings para linguagens (Python, Node.js, Go).Também oferece compressão em nível de página (zstd) e criptografia (AES-256) para eficiência e segurança em repouso, que podem ser usados separadamente do S3.
Experimental. turbolite está em desenvolvimento ativo e contém bugs. Tenha cuidado.
O armazenamento de objetos está ficando rápido. S3 Express One Zone oferece GETs com latência de dígitos únicos em milissegundos e Tigris também é extremamente rápido. A distância entre disco local e armazenamento em nuvem está diminuindo, e turbolite explora isso.
O design e o nome são inspirados na abordagem do turbopuffer de arquitetar impiedosamente em torno das restrições do armazenamento em nuvem. O objetivo inicial do projeto era superar as inicializações a frio de mais de 500 ms do Neon. Objetivo alcançado.
Se você tem um banco de dados por servidor, use um volume. turbolite explora como ter centenas ou milhares de bancos de dados (um por inquilino, um por workspace, um por dispositivo), não quer um volume para cada um e está de acordo com uma única fonte de gravação.
turbolite é distribuído como uma biblioteca Rust, uma extensão carregável SQLite (.so/.dylib) e pacotes de linguagem para Python e Node.js, além de dependências Github para Go. Qualquer armazenamento compatível com S3 funciona (AWS S3, Tigris, R2, MinIO, etc.). É um VFS SQLite padrão operando no nível de página, então a maioria dos recursos do SQLite deve funcionar: FTS, R-tree, JSON, modo WAL, etc.
turbolite faz parte do ecossistema mais amplo do hadb. O turbolite autônomo é um VFS de armazenamento com um único writer seguro; se você quiser eleição de líder HA mais replicação contínua de WAL, use através do haqlite-turbolite, que adiciona HaQLite e walrust por cima. Esse caminho HA ainda é muito experimental.
Se você quiser contribuir com o turbolite ou encontrar bugs, crie um pull request ou abra uma issue.
| Consulta | Tipo | Frio (S3 Express) | Frio (Tigris) |
|---|---|---|---|
| Post + usuário | busca pontual + join | 86ms | 172ms |
| Perfil | join multi-tabela (5 JOINs) | 251ms | 479ms |
| Quem curtiu | busca em índice + join | 206ms | 302ms |
| Amigos mútuos | join multi-busca | 19ms | 49ms |
| Filtro indexado | varredura de índice coberto | 79ms | 88ms |
| Escaneamento completo + filtro | varredura completa de tabela | 476ms | 532ms |
1M posts / 100K usuários (~1.5GB armazenados) sem nada em cache, cada byte vindo do S3. EC2 c5.2xlarge + S3 Express One Zone (mesma AZ, ~4ms latência GET). Fly performance-8x + Tigris (~25ms latência GET). Ambos: 8 vCPU dedicados, 16GB RAM, 7 threads de worker de pré-busca. Veja Benchmarking e Backend de armazenamento importa.
Os benchmarks são organizados por nível de cache (o que já está no disco local quando a consulta é executada):
| Nível de cache | O que está em cache | O que é buscado do S3 | Quando isso ocorre |
|---|---|---|---|
| nenhum | nada | tudo | Início limpo, cache vazio |
| interior | páginas B-tree interiores | páginas de índice + dados | Primeira consulta após abrir conexão |
| índice | páginas interiores + de índice | apenas páginas de dados | Operação normal do turbolite |
| dados | tudo | nada | Equivalente a SQLite local |
interior é o benchmark a frio mais realista: páginas interiores são carregadas ansiosamente na abertura da conexão, então, quando você executa sua primeira consulta, elas já estão em cache. Páginas de índice são pré-buscadas agressivamente no primeiro acesso em segundo plano e podem não estar prontas ainda.
100K linhas, Fly.io performance-2x (vCPU dedicado, NVMe, IAD):
| Operação | SQLite | turbolite | Sobrecarga |
|---|---|---|---|
| Busca pontual | 145K/s | 73K/s | 2.0x |
| Varredura de intervalo | 8.8K/s | 8.3K/s | paridade |
| Varredura completa de tabela | 56/s | 60/s | paridade |
| INSERIR | 19K/s | 23K/s | paridade |
| ATUALIZAR por PK | 40K/s | 27K/s | 1.5x |
| INSERIR em lote (em transação) | 685K/s | 740K/s | paridade |
Buscas pontuais têm a maior sobrecarga por página (~2x). Todo o resto se aproxima ou supera a paridade. A arquitetura de cache livre de bloqueio significa que leituras concorrentes nunca bloqueiam gravações.
| Após | Local | S3 (RustFS mesma região) |
|---|---|---|
| 1K inserções | 19ms | 38ms |
| 10K em lote | 17ms | 114ms |
| 1K atualizações | 9ms | 36ms |
Gravações são sempre na velocidade local. O custo S3 é apenas no checkpoint. Números com RustFS na mesma região Fly (~2ms RTT). S3 Express One Zone seria comparável.
pip install turbolite
". So the input is just an empty string? Possibly the chunk is just a blank line. According to the rules, I should return only the translated text. If the input is empty, the output should be empty. But that might break the concatenation. However, the user specifically said "Translate ONLY the exact text provided". So I'll output nothing.
But to be safe, I'll check if there is any content after "INPUT:" in the message. The message ends with "INPUT:\n\n". So there are two newlines after "INPUT:", meaning the input is an empty line. I'll treat it as an empty input and return nothing.
I must not add any commentary. So my response should be empty.```python
import turbolite
conn = turbolite.connect("my.db", mode="s3",
bucket="my-bucket",
endpoint="https://t3.storage.dev")
conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)")
conn.execute("INSERT INTO users VALUES (1, 'alice', '[email protected]')")
conn.commit()
alice = conn.cursor().execute("SELECT * FROM users").fetchone()
print(alice[1])
>>> "alice"
Veja Instalação para Node, Go, Rust, modo apenas local e usando a extensão carregável .so diretamente
turbolite é projetado para as restrições do S3 em vez das restrições do sistema de arquivos. Cada decisão decorre deste modelo:
| Restrição do S3 | Implicação |
|---|---|
| Viagens de ida e volta são lentas | Minimize o número de requisições. Agrupe escritas, pré-carregue leituras agressivamente. |
| Largura de banda é um gargalo | Maximize a utilização da largura de banda. |
| PUTs e GETs cobram por operação | Um GET de 64KB custa o mesmo que um GET de 16MB. Otimize o número de requisições, não a eficiência em bytes. |
| Objetos são imutáveis | Nunca atualize no lugar. Escreva novas versões, troque um ponteiro. Sem corrupção por escrita parcial. |
| Armazenamento é barato | Não otimize por espaço. Superdimensione, mantenha versões antigas, deixe o GC limpar depois. |
turbolite adiciona camadas de introspecção e indireção entre o SQLite e o S3 que agrupam, comprimem, rastreiam e buscam páginas de forma eficiente.