Pular para o conteúdo principal

Tamanho e alinhamento

Uma coisa que eu gosto bastante no C++ e que poucas vezes é visto com o devido cuidado é a forma como a memória é alocada. Eu ouço constantemente o mantra: Hoje temos muita memória disponível, um pouco a mais não faz diferença.

Opa, perai.

É verdade que é comum encontrarmos máquinas com 16, 32, 48 GB de memória, mas quando se fala de performance é também importante usar o mínimo possível de memória para um melhor aproveitamento do cache do processador.

Vejamos um caso de memória perdida por causa de alinhamento do processador.

Temos a struct:
https://gist.github.com/thiagomg/2da2f7f2d858144c60aa

Temos nela um int de 4 bytes + char de 1 byte = 5 bytes. Ah, quase esqueci, temos mais 3 bytes de alinhamento.
int:0-4, char:4-5 => Total bytes: 8
0 0 0 0 0 ff ff ff  Wasted bytes: 3

Isso acaba não sendo perceptível também nos casos onde a perda ocorre no meio da struct

https://gist.github.com/thiagomg/c2e50921f1682a0198d6
char:0-1, int:4-8 => Total bytes: 8
0 ff ff ff 0 0 0 0  Wasted bytes: 3

Tal qual o exemplo anterior, foram perdidos 3 bytes nesse exemplo, ou seja, 37,5% de espaço perdido. Um descuido no layout de uma struct pode ser até catastrófico!
Vejamos o exemplo:

https://gist.github.com/thiagomg/29ac6a6778af5703a0c8
char:0-1, int:4-8, char:8-9 => Total bytes: 12
0 ff ff ff 0 0 0 0 0 ff ff ff  Wasted bytes: 6

Tivemos no exemplo acima 6 bytes perdidos, 50% do tamanho da struct. Isso pode fazer muita diferença quando um cálculo de uso de memória subir de 2 GB para 4 GB (sem contar fragmentação de memória e custo do alocador new).

A solução para isso é bem simples. Uma melhor disposição da struct resolve o problema.

https://gist.github.com/thiagomg/78141b878f519103b888
int:4-5, char:0-4, char:5-6 => Total bytes: 8
0 0 0 0 0 0 ff ff  Wasted bytes: 2

Veja só ! Metade do tamanho.

Eu poderia ter nesse cálculo também mais 4 ou 8 bytes de um ponteiro para uma vtable, mas esse é assunto para outro post.

Código: https://github.com/SimplyCpp/examples/blob/master/sizes.cpp

Comentários

Postagens mais visitadas deste blog

Mestre Iota

Iota é a nona letra do alfabeto grego, ela é equivalente à letra i do nosso alfabeto. Por convenção ou hábito, utilizamos a letra i na programação para indicar algum tipo de incrementador, como por exemplo, em um for-loop . https://gist.github.com/fabiogaluppo/a23894ae743f7dd29274 Curiosamente, iota , como identificador, também é utilizado na programação para indicar uma sequência finita e consecutiva de números inteiros, como por exemplo, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. Inclusive, originalmente na STL existia a função iota , inspirada pela linguagem de programação APL , você pode conferir neste link: http://www.sgi.com/tech/stl/iota.html

Valores Aleatórios Simplificados

A partir do C++ 11, foi introduzido o header <random>  com diversos facilitadores para suporte de geração de números aleatórios. A produção destes números é feita através da combinação de duas categorias de objetos: os geradores e os distribuidores. Os geradores, são responsáveis pela geração dos números, e os distribuidores são responsáveis pela transformação dos números gerados em algum tipo de distribuição de probabilidade.  Como por exemplo, uma distribuição normal (aquela da Gaussiana) ou uma distribuição de Pareto (aquela do 80-20). As opções não faltam, como você pode ver nas referências, por exemplo:   http://www.cplusplus.com/reference/random/ ou  http://en.cppreference.com/w/cpp/header/random .

Policy-based design: log writer

Policy-based design Vamos neste artigo dar mais uma pincelada no Policy-based design . Vamos fazer como exemplo uma classe de log. Como este é só um exemplo, não vamos considerar múltiplos parâmetros no log, mas somente uma string, assim não fugiremos do assunto. Uma das coisas mais importantes neste tipo de design é o desacoplamento. Ele é uma excelente alternativa ao uso de interfaces por duas razões: Não gera chamadas virtuais (ou um nível de indireção em tempo de execução) Duck typing ( https://pt.wikipedia.org/wiki/Duck_typing ) Eu gosto bastante desse tipo de design, já usado aqui: http://simplycpp.com/2016/02/05/leitura-de-configuracao-em-c/