summaryrefslogtreecommitdiffstats
path: root/pt-br/news/phase4-performance-tuning/index.html
blob: 528224dd5032b7199498e6fdb92af6853b579762 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Fase 4: Tuning de Performance — Tesseras</title>
    <meta name="description" content="SQLite em modo WAL com configuracao centralizada de pragmas, cache LRU de fragmentos, gerenciamento de ciclo de vida do pool de conexoes QUIC e otimizacao do hot path de atestacao.">
    <!-- Open Graph -->
    <meta property="og:type" content="article">
    <meta property="og:title" content="Fase 4: Tuning de Performance">
    <meta property="og:description" content="SQLite em modo WAL com configuracao centralizada de pragmas, cache LRU de fragmentos, gerenciamento de ciclo de vida do pool de conexoes QUIC e otimizacao do hot path de atestacao.">
    <meta property="og:image" content="https://tesseras.net/images/social.jpg">
    <meta property="og:image:width" content="1200">
    <meta property="og:image:height" content="630">
    <meta property="og:site_name" content="Tesseras">
    <!-- Twitter Card -->
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:title" content="Fase 4: Tuning de Performance">
    <meta name="twitter:description" content="SQLite em modo WAL com configuracao centralizada de pragmas, cache LRU de fragmentos, gerenciamento de ciclo de vida do pool de conexoes QUIC e otimizacao do hot path de atestacao.">
    <meta name="twitter:image" content="https://tesseras.net/images/social.jpg">
    <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690">
    
        
            <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml">
        
    
    <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d">
    
</head>
<body>
    <header>
        <h1>
            <a href="https:&#x2F;&#x2F;tesseras.net/pt-br/">
                <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo">
                Tesseras
            </a>
        </h1>
        <nav>
            
                <a href="https://tesseras.net/pt-br/about/">Sobre</a>
                <a href="https://tesseras.net/pt-br/news/">Notícias</a>
                <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a>
                <a href="https://tesseras.net/pt-br/faq/">FAQ</a>
                <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a>
                <a href="https://tesseras.net/pt-br/contact/">Contato</a>
            
        </nav>
        <nav class="lang-switch">
            
                <a href="https:&#x2F;&#x2F;tesseras.net&#x2F;news&#x2F;phase4-performance-tuning&#x2F;">English</a> | <strong>Português</strong>
            
        </nav>
    </header>

    <main>
        
<article>
    <h2>Fase 4: Tuning de Performance</h2>
    <p class="news-date">2026-02-15</p>
    <p>Uma rede P2P que atravessa NATs mas engasga com seu proprio I/O nao serve de
muito. A Fase 4 continua com tuning de performance: centralizacao da
configuracao do banco de dados, cache de blobs de fragmentos em memoria,
gerenciamento de ciclo de vida de conexoes QUIC e eliminacao de leituras
desnecessarias de disco no hot path de atestacao.</p>
<p>O principio orientador foi o mesmo do resto do Tesseras: fazer a coisa mais
simples que realmente funciona. Sem alocadores customizados, sem estruturas de
dados lock-free, sem complexidade prematura. Um <code>StorageConfig</code> centralizado, um
cache LRU, um reaper de conexoes e uma correcao pontual para evitar reler blobs
que ja tinham checksum calculado.</p>
<h2 id="o-que-foi-construido">O que foi construido</h2>
<p><strong>Configuracao SQLite centralizada</strong> (<code>tesseras-storage/src/database.rs</code>) — Um
novo struct <code>StorageConfig</code> e funcoes <code>open_database()</code> / <code>open_in_memory()</code> que
aplicam todos os pragmas SQLite em um unico lugar: journal mode WAL, foreign
keys, modo synchronous (NORMAL por padrao, FULL para hardware instavel como
RPi + cartao SD), busy timeout, tamanho do cache de paginas e intervalo de
autocheckpoint WAL. Anteriormente, cada ponto de chamada abria uma conexao e
aplicava pragmas ad hoc. Agora o daemon, CLI e testes passam todos pelo mesmo
caminho. 7 testes cobrindo foreign keys, busy timeout, journal mode, migracoes,
modos synchronous e criacao de arquivos WAL em disco.</p>
<p><strong>Cache LRU de fragmentos</strong> (<code>tesseras-storage/src/cache.rs</code>) — Um
<code>CachedFragmentStore</code> que envolve qualquer <code>FragmentStore</code> com um cache LRU
ciente de bytes. Blobs de fragmentos sao cacheados na leitura e invalidados na
escrita ou exclusao. Quando o cache excede seu limite de bytes configurado, as
entradas menos recentemente usadas sao removidas. O cache e transparente: ele
proprio implementa <code>FragmentStore</code>, entao o resto da pilha nao sabe que esta la.
Metricas Prometheus opcionais rastreiam hits, misses e uso atual de bytes. 3
testes: hit no cache evita leitura interna, store invalida cache, remocao quando
excede bytes maximos.</p>
<p><strong>Metricas Prometheus de storage</strong> (<code>tesseras-storage/src/metrics.rs</code>) — Um
struct <code>StorageMetrics</code> com tres contadores/gauges: <code>fragment_cache_hits</code>,
<code>fragment_cache_misses</code> e <code>fragment_cache_bytes</code>. Registrado no registry
Prometheus e conectado ao cache de fragmentos via <code>with_metrics()</code>.</p>
<p><strong>Correcao do hot path de atestacao</strong> (<code>tesseras-replication/src/service.rs</code>) —
O fluxo de atestacao anteriormente lia cada blob de fragmento do disco e
recalculava seu checksum BLAKE3. Como <code>list_fragments()</code> ja retorna <code>FragmentId</code>
com um checksum armazenado, a correcao e trivial: usar <code>frag.checksum</code> ao inves
de <code>blake3::hash(&amp;data)</code>. Isso elimina uma leitura de disco por fragmento
durante atestacao — para uma tessera com 100 fragmentos, sao 100 leituras a
menos. Um teste com <code>expect_read_fragment().never()</code> verifica que nenhuma
leitura de blob acontece durante atestacao.</p>
<p><strong>Ciclo de vida do pool de conexoes QUIC</strong>
(<code>tesseras-net/src/quinn_transport.rs</code>) — Um struct <code>PoolConfig</code> controlando
maximo de conexoes, timeout de inatividade e intervalo do reaper.
<code>PooledConnection</code> envolve cada <code>quinn::Connection</code> com um timestamp
<code>last_used</code>. Quando o pool atinge capacidade maxima, a conexao inativa mais
antiga e removida antes de abrir uma nova. Uma tarefa reaper em background
(Tokio spawn) periodicamente fecha conexoes que ficaram inativas alem do
timeout. 4 novas metricas de pool: <code>tesseras_conn_pool_size</code>, <code>pool_hits_total</code>,
<code>pool_misses_total</code>, <code>pool_evictions_total</code>.</p>
<p><strong>Integracao no daemon</strong> (<code>tesd/src/config.rs</code>, <code>main.rs</code>) — Uma nova secao
<code>[performance]</code> na configuracao TOML com campos para tamanho de cache SQLite,
modo synchronous, busy timeout, tamanho de cache de fragmentos, maximo de
conexoes, timeout de inatividade e intervalo do reaper. O <code>main()</code> do daemon
agora chama <code>open_database()</code> com o <code>StorageConfig</code> configurado, envolve
<code>FsFragmentStore</code> com <code>CachedFragmentStore</code> e vincula QUIC com o <code>PoolConfig</code>
configurado. A dependencia direta de <code>rusqlite</code> foi removida do crate do daemon.</p>
<p><strong>Migracao do CLI</strong> (<code>tesseras-cli/src/commands/init.rs</code>, <code>create.rs</code>) — Ambos
os comandos <code>init</code> e <code>create</code> agora usam <code>tesseras_storage::open_database()</code> com
o <code>StorageConfig</code> padrao ao inves de abrir conexoes <code>rusqlite</code> diretamente. A
dependencia de <code>rusqlite</code> foi removida do crate do CLI.</p>
<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2>
<ul>
<li><strong>Padrao decorator para cache</strong>: <code>CachedFragmentStore</code> envolve
<code>Box&lt;dyn FragmentStore&gt;</code> e implementa <code>FragmentStore</code> ele proprio. Isso
significa que cache e opt-in, composavel e invisivel para consumidores. O
daemon habilita; testes podem pular.</li>
<li><strong>Remocao ciente de bytes</strong>: o cache LRU rastreia bytes totais, nao contagem
de entradas. Blobs de fragmentos variam muito em tamanho (um fragmento de
texto de 4KB vs um shard de foto de 2MB), entao contar entradas daria uma
visao enganosa do uso de memoria.</li>
<li><strong>Sem crate de pool de conexoes</strong>: ao inves de trazer uma biblioteca generica
de pool, o pool de conexoes e um wrapper fino sobre
<code>DashMap&lt;SocketAddr, PooledConnection&gt;</code> com um reaper Tokio. Conexoes QUIC sao
multiplexadas, entao o "pool" e realmente sobre gerenciamento de ciclo de vida
(limpeza de inativos, maximo de conexoes) e nao sobre emprestar/devolver.</li>
<li><strong>Checksums armazenados ao inves de releituras</strong>: a correcao de atestacao e
intencionalmente minima — uma linha alterada, uma leitura de disco removida
por fragmento. Os checksums ja estavam armazenados no SQLite por
<code>store_fragment()</code>, apenas nao estavam sendo usados.</li>
<li><strong>Configuracao centralizada de pragmas</strong>: um unico struct <code>StorageConfig</code>
substitui chamadas <code>PRAGMA</code> espalhadas. O flag <code>sqlite_synchronous_full</code>
existe especificamente para implantacoes em Raspberry Pi onde o kernel pode
crashar e perder transacoes WAL nao checkpointadas.</li>
</ul>
<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2>
<ul>
<li><strong>Fase 4 continuacao</strong> — Shamir's Secret Sharing para herdeiros, tesseras
seladas (criptografia time-lock), auditorias de seguranca, onboarding de nos
institucionais, deduplicacao de storage, empacotamento para OS</li>
<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por
era/localizacao/tema/idioma, curadoria institucional, integracao genealogica,
exportacao para midia fisica (M-DISC, microfilme, papel livre de acido com QR)</li>
</ul>
<p>Com tuning de performance implementado, Tesseras lida com o caso comum de forma
eficiente: leituras de fragmentos acertam o cache LRU, atestacao pula I/O de
disco, conexoes QUIC inativas sao removidas automaticamente e o SQLite e
configurado consistentemente em toda a pilha. Os proximos passos focam em
funcionalidades criptograficas (Shamir, time-lock) e hardening para implantacao
em producao.</p>

</article>

    </main>

    <footer>
        <p>&copy; 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p>
    </footer>
</body>
</html>