Memória e layout
O que dá para medir: bytes por objeto, slots contra dicionário, o coletor, referências fracas e o que é assunto de linguagem compilada.
Alinhamento, padding, ABI e cache line são assunto de uma linguagem com layout fixo. Aqui o objeto é do interpretador, e a pergunta que muda o desenho de um programa é outra: quanto custa um objeto, e o que fazer a respeito.
slots: a diferença medida#
Sem slots, cada objeto carrega um dicionário próprio. Com slots, os campos viram uma lista indexada — medido neste repositório: 64% menos memória por objeto.
adopt Arcane.Memoria as Mem
blueprint Compacta:
slots x, y
x := 1
y := 2
blueprint Solta:
x := 1
y := 2
com := Mem.layout(Compacta)
sem := Mem.layout(Solta)
assert com["slots"] and not sem["slots"]
assert com["campos"] is ["x", "y"]
assert com["bytes"] smaller sem["bytes"]
comparacao := Mem.comparar_layout(Compacta, Solta)
assert comparacao["menor"] is "Compacta"
assert comparacao["economia_percentual"] bigger 20Quanto ocupa um valor#
adopt Arcane.Memoria as Mem
pequeno := Mem.tamanho([1, 2])
grande := Mem.tamanho([1, 2, "um texto bem maior para ocupar espaco"])
assert grande bigger pequeno
assert Mem.tamanho("x") bigger 0A conta soma o objeto e tudo que só ele alcança, com guarda de ciclo — é a pergunta que interessa antes de guardar um milhão de linhas na memória.
O coletor, e o que ele não promete#
adopt Arcane.Memoria as Mem
blueprint Conexao:
nome := ""
c := spawn Conexao()
assert Mem.vivos(Conexao) is 1
c := void
assert Mem.vivos(Conexao) is 0
estat := Mem.estatisticas()
assert estat["ativo"]
assert len(estat["geracoes"]) is 3O coletor libera quando quiser. Para o recurso que precisa fechar numa hora certa, a resposta é `Arcane.Posse` — soltar() e P.com(…) rodam o finalizador naquele instante.
Referência fraca: observar sem segurar#
adopt Arcane.Memoria as Mem
blueprint Sessao:
id := 0
s := spawn Sessao()
fraca := Mem.fraca(s)
cache := Mem.mapa_fraco()
cache.definir(s, "dados caros")
assert fraca.viva() and cache.tamanho is 1
s := void
assert not fraca.viva()
assert cache.tamanho is 0 // o cache não segurou nadaO que é assunto de linguagem compilada#
| Item | Aqui |
|---|---|
| stack frames | existem como quadros de chamada: o stack trace os mostra, e o teto é de mil (a recursão de cauda não tem teto) |
| heap allocation | toda alocação é do Python; não há escolha entre pilha e heap |
| object layout, struct layout, enum layout | o que existe é slots contra dicionário, e isso é medível (acima) |
| alignment, padding, cache lines | não se aplicam: não há layout fixo para alinhar |
| ABI, representação de ponteiro | não se aplicam: não há binário nem endereço exposto |
| endianness | existe onde importa — em Arcane.Bytes.empacotar/desempacotar, na fronteira do arquivo e da rede |
| nullability | é void, com ?? e ?.; e uma união String | Void diz isso no tipo |
| zero-sized types | não existem: todo valor ocupa alguma coisa |