Desempenho
O que é lento, por quê, e o que fazer a respeito.
O que esperar#
DataForge é um interpretador de árvore escrito em Python, sem otimização. Cada nó da AST é visitado por uma chamada de método. Isso o torna mais lento que Python — que já é lento comparado a linguagens compiladas.
Para scripts, ferramentas de terminal e processamento de alguns milhares de registros, isso não aparece. Para laços de milhões de iterações, aparece.
Meça antes de otimizar#
adopt Arcane.Time as Time
medida := Time.measure(trabalho_pesado)
out $"{medida.result} em {round(medida.ms, 2)} ms"A intuição sobre o que é lento erra com frequência. Uma medição isolada também é ruído — o mínimo de várias execuções é mais informativo que a média.
Escolher o algoritmo certo#
Vale mais que qualquer micro-otimização:
action com_laco(n): # O(n)
total := 0
cycle i from 1 to n:
total += i
yield total
action com_formula(n): # O(1)
yield n * (n + 1) ~/ 2As duas dão o mesmo resultado. Para n = 100000, a segunda é milhares de vezes mais rápida.
Streams para dados grandes#
A diferença não é de velocidade, é de memória — e às vezes de trabalho evitado:
# carrega tudo três vezes
linhas := IO.read("app.log").lines()
registros := linhas >> morph interpretar
erros := registros >> sift e: e["nivel"] is "ERROR"
# lê até o primeiro erro e para
apenas(interpretar(linhas_do_log()), "ERROR").first()Veja Streams.
Índice em vez de busca linear#
# O(n) a cada consulta
achado := pessoas >> sift p: p["id"] is 20
# O(n) uma vez, O(1) depois
por_id := {p["id"]: p cycle p in pessoas}
achado := por_id[20]Banco: execute_many e índices#
DB.execute_many(conn, "INSERT INTO t VALUES (?, ?)", lote) # uma ida
DB.execute(conn, "CREATE INDEX idx_nome ON produtos(nome)")Recursão tem limite#
O interpretador aborta em 1000 quadros com StackOverflowError_. Recursão sobre listas grandes deve virar >> distill ou um laço.
O que está no roadmap#
- Cachear a resolução de nomes por nó da AST
- Uma IR e uma VM de bytecode com máquina de pilha
- Cache de compilação entre execuções
Nada disso é urgente enquanto ninguém tiver um caso real onde o desempenho impede o uso. Se você tiver, abra uma issue com o código — é a melhor forma de priorizar.