80 lines
9.4 KiB
Markdown
80 lines
9.4 KiB
Markdown
# Fila de associações — referências, memória e índices isolados
|
||
|
||
Seguimento: [leituras concorrentes e confirmação individual](MODULE_ASSOCIATION_CONCURRENCY_REVIEW.md), com quatro identidades sintéticas e preservação dos dados anteriores da base de provas. A evidência adicional não constitui validação da capacidade de implantação ou revisão visual.
|
||
|
||
02/11/2026. Continuação local da [optimização da fila](MODULE_ASSOCIATION_OPTIMIZATION_DELIVERY.md). Foram tratados dois pontos que permaneciam por avaliar: documentos com **100 linhas** e a contribuição do índice de revisão sozinho versus o par experimental. A avaliação encontrou um custo de memória e originou uma melhoria adicional de código, sem alterar dados do destino.
|
||
|
||
## Alteração funcional
|
||
|
||
A fila passa a seleccionar apenas ID/versão, nome da raiz e referências explícitas. Para rascunhos, o PostgreSQL extrai os IDs de serviços das linhas com `WITH ORDINALITY`, preservando a ordem; descrições, preços e restantes conteúdos documentais não são transferidos para a cache de descrição da página. Dependências de clientes/serviços seleccionam apenas ID/versão.
|
||
|
||
O percurso, a deduplicação, os grupos de até 500 IDs, os filtros, as permissões e a forma da resposta continuam iguais. Os IDs calculados são internos e não acrescentam um campo público à API. Nenhuma associação é inferida ou propagada.
|
||
|
||
**A projecção só se aplica à listagem.** Prévia e confirmação continuam a carregar e a resumir criptograficamente os registos completos, incluindo conteúdo não apresentado na fila. O código desde `preview()` até `confirm()` continua igual ao de `340f3bb`, após normalizar fins de linha. Alterar conteúdo de uma dependência, mantendo as mesmas referências, continua a invalidar uma conferência anterior.
|
||
|
||
## Ensaio novo, sem repetir a comparação anterior
|
||
|
||
Base **sgf_tempo_test**, role **sgf_test_runner**, cluster **sgf_modular_regression_2576427d1939**, porta **55439**, PHP **8.4.27**. Foram reutilizados os resultados válidos anteriores; não se repetiu a matriz de 1 000/5 000/10 000 da primeira optimização, a regressão geral ou o build React.
|
||
|
||
A nova fixture contém **10 000 registos em cada uma das quatro áreas**. As primeiras 100 prestações e os seus 100 rascunhos de facturação têm 100 linhas, com blocos distintos de serviços: uma página de 100 referencia 10 000 serviços. Uma prestação apresenta 101 dependências; um rascunho de facturação, 102. Foram ensaiadas páginas de 25/100 e descrições sintéticas de **128 e 1 000 bytes por linha**.
|
||
|
||
As quatro variantes usam a mesma fixture por perfil: código anterior à projecção sem índices; projecção sem índices; projecção com índice de revisão; projecção com o par. A fonte anterior foi preservada antes da alteração, fora da raiz web, alterando apenas o nome da classe para a prova. O launcher verifica a integridade da cópia; os hashes original/final constam do resumo. Não se trata de um segundo percurso de produção.
|
||
|
||
São três amostras quentes e sequenciais por cenário, com recolha de ciclos PHP antes da medição e os mesmos limites diagnósticos: 3 s por SQL, 15 s observados entre consultas, 250 consultas e 192 MiB de memória PHP usada observada entre consultas. A configuração PHP existente é 512M e não foi alterada. Estes limites não são SLA ou quotas de produção.
|
||
|
||
## Memória incremental por pedido
|
||
|
||
Máximo observado nas três amostras, em **MiB**, excluindo a memória já usada pelo kernel e pela fixture. A comparação abaixo é sem índices, na mesma fixture antes/depois da projecção.
|
||
|
||
| Descrição por linha | Área | Página | Antes | Depois |
|
||
| ---: | --- | ---: | ---: | ---: |
|
||
| 128 bytes | Prestações | 25 | 6,13 | 4,21 |
|
||
| 128 bytes | Prestações | 100 | 24,11 | 16,65 |
|
||
| 128 bytes | Facturação | 25 | 7,34 | 4,85 |
|
||
| 128 bytes | Facturação | 100 | 28,98 | 19,23 |
|
||
| 1 000 bytes | Prestações | 25 | 8,28 | 4,21 |
|
||
| 1 000 bytes | Prestações | 100 | 32,42 | 16,65 |
|
||
| 1 000 bytes | Facturação | 25 | 11,55 | 4,85 |
|
||
| 1 000 bytes | Facturação | 100 | **45,49** | **19,23** |
|
||
|
||
No caso mais pesado, a redução foi de aproximadamente **58%**. A memória após a projecção deixou de crescer com as descrições destes perfis, mas continua a crescer com o número de dependências que a página tem de apresentar. Não se deve aplicar a estimativa anterior de cerca de 1 MiB, obtida com uma linha por rascunho, ao cenário de 100 linhas.
|
||
|
||
As consultas PDO mantiveram-se iguais antes/depois da projecção: prestações **27/57** e facturação **31/61**, para páginas de 25/100. O crescimento em relação à prova de uma linha deve-se aos grupos necessários para 2 500/10 000 serviços distintos, não a uma consulta por linha. As respostas de 100 registos ficaram perto de **0,79–0,80 MB**, sem descrições documentais e sem diferenças de bytes entre as variantes de cada perfil.
|
||
|
||
## Tempos e contribuição dos índices
|
||
|
||
Medianas em ms, descrições de 1 000 bytes por linha:
|
||
|
||
| Área / página | Antes, sem índices | Projecção, sem índices | Só revisão | Par experimental |
|
||
| --- | ---: | ---: | ---: | ---: |
|
||
| Prestações / 25 | 668 | 729 | 97 | 226 |
|
||
| Prestações / 100 | 2 151 | 2 862 | 341 | 408 |
|
||
| Facturação / 25 | 815 | 905 | 112 | 127 |
|
||
| Facturação / 100 | 2 721 | 2 481 | 374 | 368 |
|
||
|
||
O benefício demonstrado da projecção é a memória e o menor conteúdo transportado para o PHP. **Não acelerou todos os casos sem índices**; houve também aumentos de latência, por exemplo nas prestações de 100. As fases têm ordem fixa e o cluster é partilhado com outra base sintética, pelo que três amostras não permitem atribuir toda a variação à alteração de código.
|
||
|
||
Na condição de 128 bytes, os filtros de clientes sem eventos/associados/retirados ficaram em **109/219/262 ms** com o índice de revisão e **117/235/278 ms** com o par. O segundo índice apareceu nos planos de associados/retirados, mas **não mostrou ganho consistente que justifique recomendá-lo por estes dados**. Isso não demonstra que seja inútil em todas as distribuições de histórico.
|
||
|
||
O índice de revisão ocupou **14 401 536 bytes (13,73 MiB)**; o segundo acrescentou **17 580 032 bytes (16,77 MiB)**. O par totalizou cerca de **30,50 MiB**. Na primeira condição, criação + `ANALYZE` demoraram cerca de 1,02 s para revisão e 1,84 s para o par. Não são tempos de implantação real nem incluem criação concorrente, carga de escrita ou recuperação.
|
||
|
||
Para um futuro plano de implantação, o índice de revisão sozinho é o candidato mais parcimonioso a aprofundar. **Não foi aplicado no destino**. Todos os índices desta prova foram criados em savepoints na base sintética e desfeitos por rollback.
|
||
|
||
## Testes e preservação
|
||
|
||
- **21 testes / 322 asserções** afectados, aprovados. O novo caso verifica a ordem das referências, deduplicação, ausência do corpo/alias interno na resposta e recusa de confirmação após alteração apenas do conteúdo de uma dependência. Os casos anteriores continuam a verificar permissões, isolamento, versões, concorrência e recuperação.
|
||
- **1 ensaio / 25 499 asserções**: 44 cenários, **132 pedidos medidos completos**, sem limites atingidos; respostas completas idênticas entre as quatro variantes em cada perfil. As descrições marcadas da fixture não aparecem na resposta administrativa.
|
||
- Impressões digitais das oito tabelas antecedentes e catálogo de índices iguais antes das fixtures/depois do rollback. As sequências não foram repostas. As fixtures do ensaio de 132 pedidos foram desfeitas por rollback, preservando o estado que já existia na base de provas.
|
||
|
||
[Medições finais](proofs/module-association-projection-fanout-20261102.json) · [resumo, hashes e testes](proofs/module-association-projection-summary-20261102.json) · [diagnóstico inicial que revelou o custo de memória](proofs/module-association-fanout-20261102.json).
|
||
|
||
O código, os testes afectados e o novo ensaio são locais. Os seis registos protegidos, a cache bloqueada, as alterações alheias e as demonstrações permanecem intactos. Não houve ligação à instalação local/8039, decisão real, concessão pública, publicação, activação de Compras ou novo checkpoint.
|
||
|
||
## Limitações e repetição
|
||
|
||
Não se declara validada a capacidade de implantação: não foram medidos utilizadores simultâneos, percentis de cauda, saturação, custo de escrita, implantação/recuperação de índices ou todas as distribuições multi-módulo. Os textos são repetitivos e sintéticos, abaixo do limite de 2 000 caracteres por descrição; não representam todos os payloads. A memória reportada não é a memória PostgreSQL nem uma estimativa por utilizador concorrente.
|
||
|
||
A resposta e o número de dependências cresceram: 100 rascunhos podem apresentar mais de 10 000 nós. Não se mediu o custo de renderização desse volume no navegador. **Revisão visual permanece separada**, sem tentativa pela via bloqueada.
|
||
|
||
O launcher fixado aceita `scripts/module-association-compare.mjs fanout`, depois do `sync` da cópia de regressão existente. Requer a fonte anterior e o respectivo hash preservados no directório privado da execução, cuja integridade verifica; não substitui automaticamente essa referência. Não executar `prepare`, reset ou testes na demonstração persistente. Não existe instrução de aplicar índices ao destino. A aceitação deste incremento e um checkpoint continuam a depender de decisão expressa.
|