Eu tenho interesse em criar perfis e manter um pool de memória gerenciada para cada subsistema, para que eu possa obter estatísticas sobre a quantidade de memória que está sendo usada em algo como sons ou gráficos. No entanto, qual seria um design que funcione para fazer isso? Eu estava pensando em usar vários alocadores e apenas usar um por subsistema, no entanto, isso resultaria em variáveis globais para meus alocadores (ou pelo menos me parece). Outra abordagem que vi / foi sugerida é simplesmente sobrecarregar novas e passar um alocador para um parâmetro.
Eu tinha uma pergunta semelhante sobre o stackoverflow aqui com uma recompensa, no entanto, parece que talvez eu fosse muito vaga ou simplesmente não há pessoas suficientes com conhecimento no assunto.
Respostas:
Definitivamente, é uma pergunta que pode parecer vaga para alguns;)
Mas acho que sei de onde você vem.
Você tem um milhão de opções para decidir como implementar isso. Algumas dessas opções devem girar em torno das plataformas de destino e dos objetivos gerais de design. Essas considerações romperão qualquer vínculo, até que você se sinta confortável o suficiente com custos de implementação diferentes o suficiente para aumentar o design da plataforma e as preocupações gerais de design primeiro. Então, até então, aqui estão algumas maneiras que não lhe custarão em termos de complexidade (encargos de gerenciamento) ou de lidar com remoção ou alterações, se você mudar de idéia ...
Se o objetivo é medir e alocar, com a possibilidade de usar pools, é necessário pensar primeiro no conjunto mínimo de código habitável para começar. Por uma questão de explicação, se você é parcial em relação às classes, você pode criar uma classe e deixar que resista a uma pilha, ou então usar um conjunto de funções que usam um identificador ou um nome de pilha. É realmente uma questão de semântica para ser honesto. A próxima decisão é nova ou malloc; Sou parcial com malloc porque muitas vezes estou lidando com construções de baixo nível e sei na maioria das implementações que novas chamadas malloc, e não preciso me preocupar com a complexidade de sobrecarregar novas e com isso em todas as plataformas . No entanto, muitas vezes construí sistemas ou componentes para sobrecarregar ou conectar novos. E, claro, o principal problema ou diferença é que 'novo' deve saber o tipo antes da alocação, onde 'malloc' não se importa e com malloc você decide um tipo após a alocação. Todo esse detalhe é uma ideia e um contexto para a tomada de decisões de design nesses tipos é importante :)
Então, eu vou escolher classe e malloc, porque é mais fácil explicar aqui, mas isso realmente não importa no final. Os internos acabam tendo pouca diferença de material em comparação com o restante do projeto geral.
Portanto, nessa hipótese, eu sei que (ou vou assumir que) eu posso acabar com 7-8 instanciações de classe de subsistema real e antecipar centenas de milhares de chamadas para alocação e livre. Como grande parte da minha curiosidade e força real são tudo sobre o tamanho e o perfil, não quero sobrecarregar o desempenho do aplicativo. Para iniciantes, eu posso decidir deixar a coisa toda aberta e pública até que ela seja acertada, enquanto passo a implementá-la por todo o resto do aplicativo; uma estrutura fará isso muito bem. O 's_' é para mostrar quais vars são claramente destinados a estatísticas.
Isto é extremamenteleve em muitas frentes, e talvez um bom lugar para começar a se desenvolver onde quer que você realmente queira ir com isso. E você imediatamente tem um problema, como você sabe o tamanho do item liberado. (Esse seria um problema a ser resolvido para praticamente qualquer abordagem.) Como este é um fórum de jogos, você pode considerar dopar os primeiros bytes com o tamanho, ou então é necessário agrupar ou lembrar de alguma outra maneira. A maioria das sensibilidades dos desenvolvedores de jogos não deve ser muito contra o doping, e é o exemplo mais simples, considerando que eu já fiz uma parede de texto. Basicamente, é assim: você não quer se pode ser ajudado a destruir o alinhamento inerente, você quer saber, já que quase de graça, se o tamanho é coerente. Então, algo tão simples como "s_allocs ++; s_total + = tamanho; uint64 * p = (uint64 *) malloc / calloc (tamanho + = 8); * p = 0xDEADDAED00000000 | Tamanho; return p + 1; "onde as alocações serão inferiores a 4 GB e uint64 é o que o compilador achar que é um int não assinado de 64 bits e onde você pode verificar o valor da sanidade gratuitamente.
Essa é uma maneira de obter o mínimo necessário a um custo mínimo adequado que atenda aos requisitos. Ele faz nãoendereço que aloca classes que possuem funções virtuais, se houver espaço para criação de perfil ou gerenciamento, já que você não pode prever o tamanho do ambiente c ++ que você está usando precisa para aqueles sem sobrecarregar ou conectar novos, ou se estiver contando com o construtor em um dos maneiras estranhas que não poderiam ser tratadas por alguma outra função 'init'. Caso contrário, uma estrutura é uma classe, é uma alocação arbitrária e é a mesma quando você faz a conversão. Se você é parcial em relação a novas e precisa da semântica inerente de tabela ou construtor virtual, deve vincular uma nova, mas esse é um animal totalmente diferente, que você precisa realmente estudar para se certificar de que está fazendo as novas necessidades e precisa sinalizar seu código está lidando com novo, ao qual isso é aplicado. Mas, caso contrário, o conceito acima é o mesmo.
Mais importante, isso deve estimular o cérebro e, esperançosamente, o que você precisa e quais são suas tolerâncias, agora que você viu um pouco mais a cortina. Não há assistente :)
fonte
Você não precisa implementar nada no seu jogo para esses dados. Ferramentas como o Massif Valgrind podem extrair todos os dados necessários dos símbolos de depuração. Você pode visualizar os despejos do Massif no Massif Visualizer .
fonte
Eu recomendo não escrever seu próprio alocador de memória. Você precisa de um estável, confiável e testado, com boa funcionalidade de depuração, como detecção de corrupção e, o mais importante: com estatísticas confiáveis. Esta não é uma tarefa fácil e tem muitas armadilhas. Existem excelentes e fáceis de utilizar por aí, por exemplo:
Alocador de Doug Lea
Ele vem com o conceito de espaços de memória, você pode usar um por subsistema. É altamente otimizado e oferece ótimas estatísticas e informações de tempo de execução.
fonte