From 074785cea106179cb3305637055ab0a009ca74f2 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:52 -0500 Subject: initial commit --- .../pt-pt/web/javascript/gestao_memoria/index.html | 187 +++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 files/pt-pt/web/javascript/gestao_memoria/index.html (limited to 'files/pt-pt/web/javascript/gestao_memoria') diff --git a/files/pt-pt/web/javascript/gestao_memoria/index.html b/files/pt-pt/web/javascript/gestao_memoria/index.html new file mode 100644 index 0000000000..56bfec0f7f --- /dev/null +++ b/files/pt-pt/web/javascript/gestao_memoria/index.html @@ -0,0 +1,187 @@ +--- +title: Gestão de memória +slug: Web/JavaScript/Gestao_Memoria +tags: + - Desempenho + - JavaScript + - memoria +translation_of: Web/JavaScript/Memory_Management +--- +
{{JsSidebar("Advanced")}}
+ +

Introdução

+ +

Linguagens de baixo nível, como o C, têm funções pimitivas de gestão de memória, como por exemplo, malloc() e free(). Por outro lado, os valores em JavaScript são alocados quando coisas (objetos, variáveis de texto, etc.) são criadas e "automaticamente" libertadas da memória quando deixam de ser utilizadas. O último processo é chamado de coleção do lixo. Este "automatismo" é uma fonte de mal entendidos e transmite aos programadores de JavaScript ( e aos de outras linguagens de alto nível ) a impressão de que podem decidir não se preocupar com a gestão da memória. Isto é uma erro.

+ +

Ciclo da duração da memória

+ +

Independentemente da linguagem de programação, o ciclo da duração da memória é praticamente sempre o mesmo:

+ +
    +
  1. Alocação da memória necessária
  2. +
  3. Utilização da memória alocada ( leitura, escrita )
  4. +
  5. Libertar a memória alocada quando já não é necessária
  6. +
+ +

A segunda etapa é explícita em todas as linguagens. A primeira e a última etapa são explícitas em linguagens de baixo nível mas são, na sua maioria, implícitas em linguagens de alto nível como o JavaScript.

+ +

Alocação no JavaScript

+ +

Inicialização do valor

+ +

Com o intuito de não incomodar o programador com alocações, o JavaScript fá-lo juntamente com a declaração de valores.

+ +
var n = 123; // alocação da memória para um número
+var s = 'azerty'; // alocação de memória para um texto
+
+var o = {
+  a: 1,
+  b: null
+}; // alocação de memória para um objeto e o seu conteúdo
+
+// (similar ao objeto) alocação de memória para a matriz e
+// os seus valores
+var a = [1, null, 'abra'];
+
+function f(a) {
+  return a + 2;
+} // alocação de uma função (que é um objeto que pode ser chamado)
+
+// Expressões de funções também alocam um objeto
+someElement.addEventListener('click', function() {
+  someElement.style.backgroundColor = 'blue';
+}, false);
+
+ +

Alocação através de chamadas de funções

+ +

Algumas chamadas de funções resultam na alocação de um objeto.

+ +
var d = new Date(); // alocação de um objeto Date
+
+var e = document.createElement('div'); // alocação de um elemento DOM
+ +

Alguns métodos alocam novos valores ou objetos:

+ +
var s = 'azerty';
+var s2 = s.substr(0, 3); // s2 é uma nova variável de texto
+// Dado que as variáveis de texto são de valor imutável,
+// o JavaScript pode decidir não alocar memória,
+// mas apenas armazenar o intervalo [0, 3].
+
+var a = ['ouais ouais', 'nan nan'];
+var a2 = ['generation', 'nan nan'];
+var a3 = a.concat(a2);
+// nova matriz de 4 elementos resultando
+// da concatenação dos elementos de a e a2
+
+ +

Utilização de valores

+ +

Basicamente, a utilização de valores significa a leitura e a escrita na memória alocada. Isto pode ser feito através da leitura ou escrita do valor de uma variável ou uma propriedade de um objeto ou até a passagem de um argumento para uma função.

+ +

Remoção quando a memória já não é necessária

+ +

A maioria dos problemas de gestão de memória aparecem nesta fase. A tarefa mais difícil é descobrir quando "a memória alocada já não é necessária". Em geral, requer que o programador determine quando, no seu código, este pedaço de memória já não é necessário e a liberte.

+ +

Linguagens de alto nível têm embutidas um pedaço de código chamado "coleção de lixo", cuja tarefa é rastrear a alocação e uso da memória, para detetar quando um pedaço de memória já não é necessário e neste caso, automaticamente libertá-la. Este processo é uma aproximação dado que o problema geral de se saber quando um pedaço da memória é necessário, é indecisível ( não pode ser solucionado por um algoritmo ).

+ +

Coleção de lixo

+ +

Como mencionado anteriormente, o problema geral de automaticamente descobrir quando alguma ocupação de memória "já não é necessária", é indecisível. Como consequência, as coleções de lixo implementam uma restrição à solução para o problema em geral. Esta seção explicará as noções necessárias para se compreender os principais algoritmos da coleção de lixo e as suas limitações.

+ +

Referências

+ +

A noção principal dos algoritmos de coleção de lixo baseiam-se na noção de referência. Dentro do contexto da gestão de memória, um objeto é dito referenciar outro objeto, se o primeiro tiver acesso ao segundo ( quer implicitamente quer explicitamente ). Por exemplo, um objeto JavaScript tem uma referência ao seu protótipo ( referência implícita )  e aos valores das suas propriedades ( referência explícita ).

+ +

Neste contexto, a noção de "objeto" é expandida a algo mais abrangente que um objeto JavaScript e também contém âmbitos de funções ( ou âmbito léxico global ).

+ +

Contagem de referências na coleção de lixo

+ +

Este é o algoritmo mais simples da coleção de lixo. Este algoritmo reduz a definição de "um objeto já não é necessário" para "um objeto já não é referenciado por nenhum outro objeto". Um objeto é considerado coletável para a coleção de lixo se tiver nenhuma referenciação por parte de outro objeto.

+ +

Exemplo

+ +
var o = {
+  a: {
+    b: 2
+  }
+};
+// 2 objetos criados. Um é referenciado por outro como sendo suas propriedades
+// O outro é referenciado por virtude ao ser assignado para a variável 'o'
+// Obviamente, nenhum podem ser coletado pela coleção de lixo
+
+
+var o2 = o; // A variável 'o2' é a segunda coisa que
+            // tem uma referência ao objeto
+o = 1;      // agora, o objeto que era originalmente o 'o' tem uma referência única
+            // corporificada pela variável 'o2'
+
+var oa = o2.a; // referência à propriedade 'a' do objeto.
+               // Este objeto tem agora 2 referências: uma como propriedade,
+               // a outra como variável 'oa'
+
+o2 = 'yo'; // O objeto que era o original 'o' tem agora zero
+           // referências a si próprio. Pode ser coletado para a coleção de lixo
+           // No entanto, a propriedade 'a' ainda é referenciada pela
+           // variável 'oa', logo não pode ser libertado
+
+oa = null; // A propriedade 'a' do objeto original 'o'
+           // tem zero referências a si próprio. Pode ser coletado para a  coleção de lixo.
+
+ +

Limitação: ciclos

+ +

Existe uma limitação no que se refere aos ciclos. No exemplo seguinte, dois objetos são criados e referenciam-se mutuamente, criando um ciclo. Estes sairão do âmbito depois de uma chamada a uma função e como tal, são efetivamente inúteis e podem ser libertados. No entanto, o algoritmo de contagem de referências considera que os dois objetos têm pelo menos uma referenciação; nenhum pode ser coletado para a coleção de lixo .

+ +
function f() {
+  var o = {};
+  var o2 = {};
+  o.a = o2; // o referencia o2
+  o2.a = o; // o2 referencia o
+
+  return 'azerty';
+}
+
+f();
+
+ +

Exemplo de aplicação real

+ +

O Internet Explorer 6 e 7 são conhecidos por terem um coletor de contagem de referenciações de coleções de lixo para os objetos DOM. Os ciclos são um erro comum que podem gerar percas de memória:

+ +
var div;
+window.onload = function() {
+  div = document.getElementById('myDivElement');
+  div.circularReference = div;
+  div.lotsOfData = new Array(10000).join('*');
+};
+
+ +

No exemplo acima, o elemento DOM "myDivElement" tem uma referência circular a si próprio na propriedade "circularReference". Se a propriedade não for explicitamente removida ou anulada, o coletor de contagem de referências da coleção de lixo, irá sempre ter uma referenciação intacta e irá manter o elemento DOM na memória mesmo quando for removido da árvore DOM. Se o elemento DOM contém bastante dados ( ilustrado no exemplo acima com a propriedade "lotsOfData" ), a memória consumida por estes dados nunca será libertada.

+ +

Algoritmo de marcação e limpeza

+ +

Este algoritmo reduz a definição de "um objeto já não é necessário" para "um objeto é inalcançável".

+ +

Este algoritmo assume o conhecimento de um conjunto de objetos chamados "roots" ( em JavaScript, a root - raiz - é um objeto global ). Periodicamente, a coleção de lixo começará pela raíz e procurará todos os objetos que são referenciados a partir desta; depois todos os que são referenciados a partir dos seguintes, etc.. Começando pela raiz, o coletor de lixo irá localizar objetos inalcançáveis; coletando-os.

+ +

Este algoritmo é melhor do que o anterior dado que "um objeto tem zero referenciações" leva a um objeto inalcançável. O contrário não é verdade como vimos nos ciclos.

+ +

Desde 2012, todos os modernos navegadores de Internet contêm um coletor de marcação e limpeza. Todos os melhoramentos feitos na área da coleção de lixo no JavaScript ( generalização / incrementação / concorrência / coleção de lixo paralela ) nos últimos anos são implemetações de melhoramento deste algoritmo, mas não melhoramentos do algoritmo de coleção de lixo em si nem a sua redução à definição de que quando "um objeto já não é necessário".

+ +

Os ciclos já não são um problema.

+ +

No primeiro exemplo acima, depois do retorno da chamada à função, 2 objetos já não são referenciados por algo alcançável no objeto global. Consequentemente, irão ser localizados pelo coletor da coleção de lixo.

+ +

Limitações: os objetos necessitam de ser explicitamente inalcançáveis

+ +

Apesar disto estar marcado como uma limitação, é um caso que raramente ocorre na prática pelo que é por isto que ninguém se preocupa muito com a coleção de lixo.

+ +

Ver também

+ + -- cgit v1.2.3-54-g00ecf