Sempre que você tiver um aplicativo que tenha um caminho crítico de alto desempenho, preocupe-se em como trata a memória. A maioria dos aplicativos do lado do cliente do usuário final não se enquadra nessa categoria, pois são orientados a eventos principais e a maioria dos eventos vem de interações com o usuário, e isso não tem muitas restrições de desempenho (se é que existem).
No entanto, muitos softwares de back-end devem se concentrar em como a memória é manipulada, porque muitos deles podem ser dimensionados para lidar com um número maior de clientes, um número maior de transações, mais fontes de dados. empurrando os limites, você pode começar a analisar como os usuários de software armazenam e escrevem esquemas de alocação personalizados, adequados ao seu software, em vez de confiar em um alocador de memória completamente genérico que foi criado para lidar com qualquer caso de uso imaginável.
Para dar alguns exemplos ... na minha primeira empresa, trabalhei em um pacote Historian, software responsável por coletar / armazenar / arquivar dados de controle de processos (pense em uma fábrica, usina nuclear ou refinaria de petróleo com 10 milhões de sensores, armazenaríamos esses dados). Sempre que analisamos qualquer gargalo de desempenho que impedia o Historiador de processar mais dados, na maioria das vezes o problema estava em como a memória era manipulada. Passamos por grandes esforços para garantir que malloc / free não fossem chamados, a menos que fossem absolutamente necessários.
No meu trabalho atual, trabalho no gravador de vídeo digital de vigilância e no pacote de análise. A 30 qps, cada canal recebe um quadro de vídeo a cada 33 milissegundos. No hardware que vendemos, podemos gravar facilmente 100 canais de vídeo. Portanto, esse é outro caso para garantir que no caminho crítico (chamada de rede => componentes de captura => software de gerenciamento de gravadores => componentes de armazenamento => disco) não haja alocações dinâmicas de memória. Temos um alocador de quadro personalizado, que contém depósitos de buffers de tamanho fixo e usa LIFO para reutilizar buffers alocados anteriormente. Se você precisar de 600Kb de armazenamento, poderá acabar com um buffer de 1024Kb, o que desperdiça espaço, mas, como é adaptado especificamente para o nosso uso em que cada alocação é de curta duração, funciona muito bem porque o buffer é usado,
No tipo de aplicativos que descrevi (mover muitos dados de A para B e manipular um grande número de solicitações de clientes), ir para o heap e back é uma das principais fontes de gargalos no desempenho da CPU. Manter a fragmentação de heap no mínimo é um benefício secundário, no entanto, até onde eu sei, os sistemas operacionais modernos já implementam heaps de baixa fragmentação (no mínimo, eu sei que o Windows faz, e espero que outros o façam). Pessoalmente, em mais de 12 anos trabalhando nesses tipos de ambientes, vi problemas de uso da CPU relacionados ao heap com bastante frequência, enquanto nunca vi um sistema que sofria de heap fragmentado.