Pretty-Belle comentou:
Olha, eu não sou nenhuma expert, mas eu tenho um pouquiiiinho de experiência nessa área de otimização de código e tals - bem pouco mesmo, foi mais do que eu aprendi com um projeto que eu tenho em Java, tentando encontrar formas de diminuir uso de memória RAM. Acho que a melhor forma de analisar isso mais precisamente é abrir o gerenciador de tarefas e jogar com ele ao lado. Se você prestar atenção, em alguns momentos dão aquele pico de uso na CPU, que teoricamente é o motivo do lag.
Quanto a remover o Scene_Battle, acho bem improvável que faça diferença. Na verdade, remover qualquer coisa que não está sendo utilizada não vai fazer a menor diferença - porque o que faz diferença já é o próprio fato de você não a estar utilizando. A forma mais eficaz de diminuir o lag é reestruturando o código (das coisas que você usa) e dando um jeito de poupar processamento. E isso varia de caso para caso, tem que ver como o seu sistema funciona.
(Alguém me corrija se eu estiver errada, por favor ><)
Retirar scripts não utilizados vai apenas diminuir um pouco o
overhead da aplicação; basicamente, tem o mesmo efeito de compilar um programa juntamente a cabeçalhos/arquivos de código que não são utilizados - não vai melhorar, mas também não vai atrapalhar (ou muito pouco, dependendo da complexidade). No RPG Maker, em especial, como imagino que o arquivo executável seja um interpretador (e aí, talvez eu esteja errado), e não uma compilação, a existência ou não desse código não executado acaba se tornando irrelevante, daí o fato de você não sentir a diferença.
De uma forma geral, o que eu vejo é que muitos desenvolvedores se preocupam desnecessariamente com otimização de sistemas quando ela é simplesmente desnecessária em boa parte dos casos, ou traz benefícios tão irrisórios que não compensa o trabalho.
Permitam-me dar uma breve explicação com o que sei sobre otimização.
Otimizar significa tornar algo ótimo (no sentido de máxima performance), como substituir um algoritmo de
busca linear por um de
busca binária, usar
algoritmos de ordenação eficientes ou mesmo procurar uma forma mais inteligente de achar máximos e mínimos de um determinado conjunto (método de
Monte Carlo? método do
Gradiente?). Os estudos de otimização computacional surgiram a partir da necessidade de fazer aplicações que possam resolver esses tipos de problemas (que envolvem matemática, afinal) de forma mais rápida, eficiente e eficaz.
Certo, e onde quero chegar?
Muito disso era extremamente importante quando os computadores ainda tinham alguns meros kbytes de memória e a frequência dos processadores não ultrapassava meio-gigahertz, onde você era obrigado a economizar bytes no código (alguém se lembra do bug do milênio?) e tentar fazer com que ele fizesse a mesma coisa da forma mais rápida possível - muitos preferiam recorrer a outros mecanismos, como linguagem de máquina e tudo mais. A grande questão aqui é que os computadores evoluiram ao ponto que a quantidade de operações de ponto flutuante por segundo (vulgo FLOPS) e a memória RAM disponível se tornou tão grande que certas coisas são triviais e não se percebe a diferença mesmo que você escreva teu código totalmente em binário.
E é aí que entra a questão dos jogos. Ao contrário do senso comum, vou começar falando dos jogos 3D e depois ir para o 2D, e assim vocês entendem onde quero chegar: pensem que a unidade básica desses jogos é o triângulo - com três vértices e cada um com uma coordenada (x, y, z). Seu cenário será formado pela composição de vários desses triângulos, cada um com sua própria coordenada, e que estarão listadas em uma matriz. Obviamente, quanto maior a quantidade de triângulos, maior será a sua quantidade de detalhes e, por consequência, mais extensa será essa sua matriz - e daí que surge a ideia de que "gráficos 4K são mais pesados que 1080p" e "gráficos 1080p são mais detalhados/pesados 720p", é apenas algo natural que está acontecendo. Agora perceba que todas as operações que você faz com os jogos consiste em mexer com essas matrizes: rotacionar a câmera do jogo pode significa fazer uma transformação linear na matriz; aproximar ela pode significar calcular a inversa, etc. E a cada movimento que você faz, inúmeras operações são executadas e dependendo do seu equipamento, ele pode não dar conta disso tudo - e daí, a sua taxa de FPS começa a cair. Antes que me perguntem, o programador (mesmo que mexa com código puro) raramente se preocupa em fazer esse tipo de operação; existem várias bibliotecas já prontas para isso (o próprio DirectX e OpenGL tem funções de calcular o ortogonal da matriz, por exemplo).
O que eu quero falar é que, para esse nível de necessidade, se preocupar com recursos computacionais se torna realmente importante (
it matters!); ou é isso, ou ninguém vai conseguir jogar teu jogo. Muitas vezes, o que os desenvolvedores fazem não são
otimização no sentido estrito da palavra (ou seja, melhorar a forma de calcular), muitas vezes por falta de conhecimento, mas apenas se utilizar de recursos computacionais mais eficientes. Alguns que posso citar:
- Carregar tudo no cache ou na RAM.
- Jogar todo o trabalho para a GPU ou Coprocessadores.
- Realmente descer a nível de máquina.
O primeiro se trata daquela velha tela de "Loading" (um dos motivos, na verdade). Vamos pensar em termos de console que é mais fácil de analisar: o Xbox One tem 16 gb de RAM e 1 TB de HD. Um dos jogos que tenho, o Tomb Raider, é basicamente um bluray de 50 gb. Dentro de um sistema computacional, temos vários tipos de memória, onde o acesso ao Cache é muito mais rápido que o acesso à RAM que é mais rápida que o acesso ao HD. O mundo ideal seria que tudo pudesse ser acessado direto do cache, mas isso é impossível porque eles tem tamanho em escala de MBs; porém, a RAM é mais versátil. Daí, então, a ideia da tela de Loading é justamente pegarmos tudo que formos utilizar e está no HD (mais lento) e carregar na RAM (mais rápida) de forma que quando estivermos jogando, o tempo de acesso às texturas e afins vai diminuir e nossa vida será um pouco mais feliz. O que for ainda mais utilizado, pode ir pro cache. No fim, quando não precisarmos mais desses arquivos, descarregamos tudo e repetimos o processo.
GPUs são as placas de vídeo - e elas tem esse nome justamente porque permitem
paralelizar as contas - em termos simples, você faz várias operações iguais (e muitas vezes, simples) ao mesmo tempo, ao invés de fazer tudo no "serial" (um por um), como é no seu processador, então seu tempo de processamento de uma determinada região do código naturalmente cai. Isso se dá porque a estrutura da placa é composta de vários núcleos de processamento (muitas vezes, passando de 2000 deles), e como muitas vezes as operações desse tipo são relacionadas a vídeos (somar uma matriz com outra, por exemplo), surgiu esse nome. Em geral, uma GPU processando as coisas em "serial" tende a ser mais devagar que uma CPU comum, mas a vantagem da paralelização permite o ganho e a vantagem de uso. É óbvio que você depende se o seu usuário vai ter ou não esse hardware. Em geral, se você não tem, você acaba fazendo suas continhas de forma mais devagar (porque processadores comuns, em geral, só tem até 8 núcleos virtuais, o que não é tão eficiente para esse tipo de coisa). Existem também o conceito de coprocessadores, que são análogos às GPUs, só que são processadores escravos que ficam esperando comandos da CPU mãe.
O terceiro método é mais complexo porque a linguagem de máquina que você vai utilizar em geral depende do hardware de quem está executando o código - dificilmente o mesmo código Assembly usado em um processador Intel vai ser o mesmo de um processador AMD (existem alternativas para contornar isso, como intrinsics do compilador, mas não vou abordar aqui). Por isso mesmo, somente quem realmente está mexendo com um hardware fraco (como celulares antigos) utiliza isso, visto que é um trabalho de corno. Mas, anyway, essa é a maior vantagem de se programar para consoles: como você sabe a configuração exata e que ela não vai mudar, você pode escrever teu codigozinho sabendo que não vai ter nenhuma dor de cabeça por incompatibilidade. Outras coisas incluem usar linguagens mais próximas de máquina - por exemplo, já cansei de citar, o Java tem uma parte do código denominada JNI (Java Native Interface) que permite você escrever código totalmente em C/C++ e fora do jardim da máquina virtual de forma a atingir performance (e daí tem mais chances de ter incompatibilidade). Jogos como o Minecraft (e, acredito, o Runescape) tem diversas partes escritas em C++ justamente porque a JVM não dá o desempenho que você precisa (e, muitas vezes, é melhor você dar mallocs, callocs e frees na medida que você precisa do que depender do garbage collector alheio).
E, agora, podemos entrar nos jogos 2D: eles não tem nada disso. O sistema de coordenadas é bidimensional, a quantidade de detalhes em geral também tende a ser menor e, por isso mesmo, as operações envolvidas são exponencialmente mais simples, e os computadores hoje em dia já são capazes de lidar com elas sem muitos problemas, mesmo que sejam relativamente mal programadas, e temos uma quantidade relativamente alta de memória RAM - texturas/sprites 2D são também muito menores que as usadas 3D na hora de se carregar, por exemplo. Quando buscamos aumentar a eficiência do nosso programa, temos que observar a forma que ele é estruturado: boas práticas de programação com reuso de código, por exemplo, acaba se tornando essencial. Também tem o fato que jogos em Java sempre vão estar sob uma camada extra - no caso, a JVM (ou Dalvik, no Android) - em comparação com a contrapartida em outras linguagens, de forma que o uso deles é naturalmente maior. A forma que você busca e organiza seus dados no database também é relevante, principalmente se a quantidade de dados for crescente. A ideia de carregar somente o que acharmos necessário na RAM e reusar também é essencial (se seu mapa é todo gramado, carregue apenas UMA vez aquele tile e faça tudo com ele), e a própria classe de renderização (por exemplo, a função de carregar imagens utilizada de forma ineficiente; a JGLW, e a Slick para 2D, se utiliza do OpenGl que está desenvolvido em C, então naturalmente o armazenamento e o acesso tende a ser mais rápido) pode influenciar. Em geral, dado que em jogos 2D existe um limite teórico do número de coisas que devem existir na tela ao mesmo instante, a RAM deve começar a se estabilizar em algum momento. Mas para se fazer uma análise mais complexa disso, é necessário terminar tudo que você quer, analisar o desempenho e fazer modificações para ver se diminui e lentamente ganhar experiência (repare que mesmo o Skype, que é um relativo programa de texto, usa 150mb de RAM).
Óbvio como existem exceções, como jogos que tem quadritrilhões de partículas, onde cada uma se movimenta para um lugar específico a ser calculado, ou jogos que tentam renderizar 3D a partir de ferramentas 2D (existe um projeto famoso que faz isso, se não me engano). Nesses casos, sim, cada detalhe importa, mas se você precisa desse tipo de coisa, muito provavelmente seu jogo está estruturado de forma errônea desde o começo e a complexidade de desenvolvimento só faz crescer.
Onde quis chegar com tudo isso?
Sei lá, estava apenas com vontade de escrever alguma besteira. Obviamente, tudo que escrevi acima pode ter sido alguma lorota que inventei pra distrair vocês.
O texto todo em uma frase: não adianta se preocupar muito com esse tipo de coisa no RPG Maker, a diferença é praticamente irrisória.
Edit: Estive conversando sobre esse texto com uma pessoa que trabalha com otimização e ele me falou algo interessante que eu não lembrei de citar.