Desenvolvimento - Mobile
HB++: Gerenciamento de Memória no Palm OS
O sistema operacional Palm OS possui basicamente dois tipos de memória utilizados pelos aplicativos: Memória de Alocação Dinâmica e Memória de Armazenamento.
por Caio ProieteIntrodução
O sistema operacional Palm OS possui basicamente dois tipos de memória utilizados pelos aplicativos: Memória de Alocação Dinâmica e Memória de Armazenamento. A Memória de Alocação Dinâmica, conhecida por HEAP, é a memória utilizada para armazenar todas as variáveis criadas pelas aplicações, no momento da execução, enquanto a Memória de Armazenamento, conhecida por STORAGE, é a memória onde estão gravados todos os programas e bancos de dados do Palm OS.
O tamanho dessas duas memórias não é padrão, e varia em cada PDA/SmartPhone, por exemplo, o Palm T|X possui aproximadamente 6 Mb de memória de alocação dinâmica (heap) e 64 Mb de memória de armazenamento (storage), enquanto o Treo 650 possui aproximadamente 5 Mb de memória de alocação dinâmica (heap) e 22 Mb de memória de armazenamento (storage).
Conceito
O Handheld Basic possui uma função interna chamada MemInfo, que nos permite obter informações sobre as duas memórias (heap e storage), de acordo com o parâmetro informado, que pode ser um destes:
- hbMemHeapSize - Corresponde ao tamanho total da memória de alocação dinâmica (heap) em bytes;
- hbMemHeapFree - Corresponde a quantidade livre na memória de alocação dinâmica (heap);
- hbMemHeapMax - Corresponde ao maior bloco de memória livre na memória de alocação dinêmica (heap)* em bytes;
- hbMemStorageSize - Corresponde ao tamanho total da memória de armazenamento (storage) em bytes;
- hbMemStorageFree - Corresponde a quantidade livre na memória de armazenamento (storage) em bytes.
* O Palm OS automaticamente efetua a desfragmentação da memória de alocação dinâmica quando necessário. Ao criarmos uma variável que ocupe um tamanho maior que o maior bloco de memória disponível, o Palm OS efetua a desfragmentação, na tentativa de conseguir um bloco de memória com o tamanho necessário para a variável.
Exemplo de utilização:
Private Sub Button1_Click() "Mostra a quantidade de memória heap disponível MsgBox Format(MemInfo(hbMemHeapFree), "#.00") & " bytes livres." End SubGarbage Collector
Enquanto a desfragmentação da memória é de responsabilidade do sistema operacional, a liberação de memória das variáveis que não estão mais sendo utilizadas na aplicação, é uma tarefa realizada por um serviço do Handheld Basic chamado Garbage Collector (ou Coletor de Lixo). O Garbage Collector, assim como em outras plataformas como Java e .NET Framework, é um serviço responsável em monitorar as variáveis criadas pela aplicação que não estão sendo utilizadas e efetuar a liberação de memória.
No caso do HB++, o Garbage Collector é uma rotina incorporada em cada arquivo .prc, que é executada de tempos em tempos, de acordo com um algoritmo interno do Handheld Basic. O Garbage Collector não é executado muitas vezes, para não prejudicar a performance da aplicação, mas normalmente é executado vezes suficientes para que as aplicações tenham sempre memória disponível. Dessa forma, não podemos prever exatamente quando o Garbage Collector será executado.
Como o sistema operacional Palm OS não é multi-tarefa, este serviço não é executado em paralelo, como acontece em Java e .NET Framework, então nossa aplicação deixa de funcionar por alguns milissegundos, até que o Garbage Collector termine sua execução. Entretanto, esta pausa na aplicação normalmente é imperceptível, pois para não prejudicar a performance da aplicação, o Garbage Collector normalmente é executado por apenas 10 milissegundos, liberando a memória que conseguir, neste tempo.
Embora não seja possível prever exatamente todas as vezes que o Garbage Collector será executado, existe uma regra no algoritmo em que a cada 64 alocações de memória, o Garbage Collector é executado. Antes disso ocorrer, existem três situações que podem causar a execução do Garbage Collector:
- Quando existem blocos de memória que não estão sendo utilizados, e o usuário não efetuou nenhuma ação na aplicação por mais de 2 (dois) segundos (Idle time);
- Quando o espaço disponível no heap é insuficiente para satisfazer uma nova alocação de memória;
- Quando o Garbage Collector é executado explicitamente, através da função MemCompact.
A função MemCompact só deve ser utilizada em casos extremos, onde seja necessário alocar e liberar uma grande quantidade de memória, e o tamanho do heap seja limitado. Na maioria dos casos, não é necessário executar o Garbage Collector explicitamente, e devemos deixar o algoritmo decidir o melhor momento, para garantir a melhor performance possível para as aplicações.
A função MemCompact recebe dois parâmetros do tipo Boolean, que são, respectivamente:
- bGarbageCollector - Define se o Garbage Collector deve ser executado (True ou False);
- bCompact - Define se a memória deve ser Desfragmentada pelo sistema operacional (True ou False).
Exemplo de utilização:
Private Sub Button1_Click() "Executa o Garbage Collector e Desfragmenta a Memória MemCompact True, Tue End SubEscopo de Variáveis
Toda variável possui um escopo que define onde ela pode ser utilizada, e qual seu tempo de vida. Variáveis criadas dentro de uma Function ou Sub, por exemplo, são válidas apenas dentro deste bloco, enquanto variáveis criadas dentro de classe, são válidas enquanto a instância da classe existir.
"Variavel criada no escopo da classe Private m_VariavelDaClasse As String Private Sub Button1_Click() "Variável criada no escopo do método Dim variavelDoMetodo As String "Acesso à variavel local (do método) "OK variavelDoMetodo = "Botão 1" "Acesso à variavel da classe "OK m_VariavelDaClasse = "Botão 1" End Sub Private Sub Button2_Click() variavelDoMetodo = "Botão 2" "ERRO DE COMPILAÇÃO m_VariavelDaClasse = "Botão 2" "OK End SubNo exemplo acima, ocorre o erro de compilação error #2201 : identifier "variavelDoMetodo" is not defined, indicando que a variável variavelDoMetodo não existe no método Button2_Click, e deveria ser declarada, assim como no método acima, utilizando a instrução Dim. Já o acesso à variavel m_VariavelDaClasse é garantido, pois todos os métodos de uma classe podem acessar as variáveis que estão no escopo da classe.
Escopo de Variáveis e o Garbage Collector
O Garbage Collector só libera a memória de variáveis que não estão sendo mais utilizadas pelas aplicações, e para fazer este controle, ele cria uma lista com todas as variáveis utilizadas, mapeadas aos endereços de memória onde estão alocados os objetos.
"Variavel criada no escopo da classe Private m_minhaTabela As tblMinhaTabela Private Sub Button1_Click() Dim Empresa As String Empresa = "PDAExpert Tecnologia em Software" Dim Website As String WebSite = "http://www.pdaexpert.net" Dim Telefone As String Telefone = "+55 11 3374-3321" Set m_minhaTabela = New tblMinhaTabela m_minhaTabela.OpenTable hbModeReadWrite "(...) m_minhaTabela.Close End SubNo exemplo acima, quando a função Button1_Click termina a execução, todas as variáveis criadas dentro deste método deixam de existir, e a única variável que continua a existir é a m_minhaTabela, por estar no escopo da classe.
Embora as variáveis que pertenciam ao método deixaram de existir, todos os objetos instanciados continuam a existir, e continuam a ocupar espaço em memória, até que o Garbage Collector seja executado e possa liberar a memória utilizada por estes objetos. No momento em que o Garbage Collector for executado, perceberá que os três primeiros objetos não possuem variáveis referenciando-os, e os removerá da memória.
A importância de atribuir "Nothing" às variáveis
No exemplo acima, podemos notar que a variável m_minhaTabela continua a existir, por estar dentro do escopo da classe, mas podemos notar também que a tabela foi fechada, e que o objeto alocado na memória não será utilizado novamente na aplicação. Mesmo assim, a tabela continuará ocupando memória até que este formulário seja fechado, que será quando a variável m_minhaTabela deixará de existir e somente assim o Garbage Collector poderá liberar a memória ocupada pelo objeto.
Nestas situações, devemos atribuir Nothing à variável, para eliminarmos a referência que ela faz ao objeto, na tabela do Garbage Collector:
"Variavel criada no escopo da classe Private m_minhaTabela As tblMinhaTabela Private Sub Button1_Click() "(...) Set m_minhaTabela = New tblMinhaTabela m_minhaTabela.OpenTable hbModeReadWrite "(...) m_minhaTabela.Close Set m_minhaTabela = Nothing End SubDessa forma, a variável m_minhaTabela continuará a existir, pois ainda está no escopo da classe, mas já não referencia o objeto alocado em memória, e assim permitirá que o Garbage Collector libere este bloco de memória, quando for executado.
Memória de Armazenamento
Diferentemente da memória de alocação dinâmica, a memória de armazenamento não possui um serviço como o Garbage Collector para liberação de memória. O funcionamento dessa memória é parecido com o funcionamento de um disco rígido de um computador, ou um pen drive, por exemplo. Quando instalamos aplicações e/ou inserimos registros em bancos de dados, o espaço vai sendo ocupado, e quando desejarmos liberar espaço, temos de apagar arquivos e/ou registros dos bancos de dados.
Histórico
- 08/06/2007 - Primeira versão deste artigo.
- Como criar um player de audio para Windows PhoneDisp. móveis
- Windows Phone: Criando e lendo arquivos de textoDisp. móveis
- Inserindo, editando e lendo dados no Windows Phone com IsolatedStorageSettingsDisp. móveis
- Introdução ao jQuery MobileJavascript
- Entendendo a navegação entre páginas no Windows Phone 7Disp. móveis