[choi ooplsa99] resume

4

Click here to load reader

Upload: marcio-machado-pereira

Post on 28-Jun-2015

348 views

Category:

Documents


0 download

DESCRIPTION

Escape Analysis for Java

TRANSCRIPT

Page 1: [Choi ooplsa99] resume

nov-2011

I. INTRODUÇÃO

o artigo [1], Choi et al. introduziram um novo framework para realizar a analise de fluxo de dados

(DFA) no contexto de Java denominada Escape analysis. Este framework está baseado em uma abstração do programa chamada de Connection Graph (CG). Em Java, os objetos normalmente são alocados no heap e só podem ser dealocados pelo Garbage Collector (GC). Escape Analysis determina se um objeto pode escapar o método que o criou (i.e., não é local ao método) e se o mesmo pode escapar a thread que o criou (i.e., outras threads podem acessar o objeto). Se o objeto não escapa o método ou a thread, duas otimizações podem ser feitas: (1) O objeto pode ser alocado na pilha (stack frame) do método que o criou. Esta alocação normalmente é mais barata do que a alocação no heap, reduzindo o overhead do GC; (2) pode-se eliminar os mecanismos de sincronização associados ao objeto, uma vez que o objeto é acessado por uma única thread. Além disso, o objeto pode ser alocado na memória do processador onde a thread foi agendada (scheduled) melhorando a localidade do dado. Connection Graph captura a relação de conectividade entre os objetos alocados no heap e as referencias a estes objetos. A DFA simplesmente realiza uma analise de alcance (reachability analysis) no CG para determinar se um objeto é local a um método ou local a uma thread.

N

II. ESCAPE ANALYSIS

No Connection Graph, os objetos, as variáveis de referencia locais e formais, e os campos (fields) estáticos e não estáticos são representados pelos vértices (ou nós) enquanto as arestas representam os diversos tipos de referencias entre variáveis, objetos e campos (fields) estáticos ou não. A figura abaixo ilustra os tipos de nós e arestas:

O trabalho em referência foi apresentado na conferência OOPSLA'99 realizado em novembro de 1999 na cidade de Denver, Colorado, EUA. O resumo é parte do trabalho de pesquisa de doutorado do Instituto de Computação da UNICAMP (IC-Unicamp) e foi elaborado por Pereira, M. M. (e-mail: [email protected] ).

A idéia básica do Escape Analysis consiste no seguinte: Define-se três estados de escape para os objetos – NoEscape, quando o objeto é local ao método (e, consequentemente, à thread); ArgEscape, quando o objeto escapa o método via argumentos, mas não escapa a thread que o criou e GlobalEscape quando o objeto escapa globalmente (i.e., todos os métodos e threads).

Os nós que representam campos estáticos (variáveis globais) são inicializados no estado GlobalEscape. Os demais nós são inicializados como NoEscape. Se um objeto pode ser alcançado no Connection Graph por algum nó cujo estado é diferente de NoEscape então o objeto escapa o Método. Após a DFA, todos os objetos marcados como NoEscape são alocáveis na pilha (stack-allocatable) e todos os objetos marcados como NoEscape ou ArgEscape são locais à thread e, portanto, as operações de sincronização podem ser eliminadas sem violar a semântica do programa.

Dois tipos de analise são realizadas para se construir o CG e identificar os objetos que não escapam seu método ou thread de criação: Intraprocedural e Interprocedural. Dada a representação de um método Java em CFG (Control Flow Graph) usa-se um esquema iterativo, descrito na seção III para a construção do CG intraprocedural. Este CG pode ser sumarizado para cada método de forma que a mesma informação pode ser usada eficientemente em diferentes contextos de chamada (calling contexts). Choi et al. apresentaram um algorítmo interprocedural, descrito na seção IV, que usa a propriedade de sumarização para computar de forma eficiente o CG e identificar objetos que não escapam métodos ou threads.

III.ANALISE INTRAPROCEDURAL

A analise intraprocedural faz uso de uma DFA forward, disjuntiva, onde o CG na saída de um statement é dada pela função de transferencia aplicada ao CG na entrada do mesmo que, por sua vez, é o resultado da união dos CGs na saída dos predecessores do referido statement.

Para a descrição desta análise, algumas definições fazem-se necessárias:

CG = ( No U Nr U Nf U Ng, Er U Ed U Ef ) onde,No – representa o conjunto de objetosNr – variáveis de referência (locais e formais)Nf – fields não estáticosNg – fields estáticos (variáveis globais)Er – arestas “point-to”

1

Escape Analysis for Java

Jong-Deok Choi Manish Gupta Mauricio Serrano Vugranam C. Sreedhar Sam Midkiff IBM T.J. Watson Research Center

{jdchoi, mgupta, mserrano, vugranam, smidkiff} @ us.ibm.com

Resumo realizado por Marcio Machado Pereira – RA 780681

Page 2: [Choi ooplsa99] resume

nov-2011

x → y ∈ Er ⇒ x ∈ Nr U Nf U Ng & y ∈ No

Ed – arestas deferred (diferidas)x → y ∈ Ed ⇒ x, y ∈ Nr U Nf U Ng

Ef – arestas field

x → y ∈ Ef ⇒ x ∈ No & y ∈ Nf U Ng

representa uma aresta point-to do nó x para o nó y

representa uma aresta diferida no nó x para o nó y

representa uma aresta field do nó x para o nó y

Associa-se ainda a cada field f de um objeto um identificador único fid(f) que corresponde ao offset de f na classe que define o objeto. Isto posto, se O1 e O2, são 2 objetos da mesma classe C, então fid(O1.f) = fid (O2.f). Dado um nó

de referencia m ∈ Nr U Nf U Ng, o conjunto de nós objetos

O ⊆ Νο que m aponta para (point-to) é determinado

percorrendo as arestas diferidas a partir de m até visitarmos a primeira aresta point-to no caminho. Formalmente:

onde é uma sequencia de arestasque termina exatamente em uma aresta point-to.

Para uma analise sensível ao fluxo (flow-sensitive) faz-se necessário também definir uma função ByPass que, quando aplicada ao nó p ∈ Nr U Nf redireciona as arestas diferidas incidentes em p aos nós sucessores de p. Exemplo:

Quatro statements básicos afetam o Escape Analysis. A seguir são apresentadas as funções de transferência para cada um destes statements:

(1) p = new r();• Cria o nó objeto O (se não existir)• (Flow-Sensitive) → aplica ByPass (p)• (Both) → adiciona aresta point-to de p para O

(2) p = q;• (Flow-Sensitive) → aplica ByPass (p)• (Both) → adiciona a aresta

(3) p.f = q;• Faça U = PointsTo (p)• Se U = Ø então ou p = null (null pointer exception) ou o objeto para o qual p aponta foi criado fora do método (p é um parâmetro formal ou alcançável por um parâmetro formal).

Conservativamente, cria-se um objeto fantasma Oph (phantom object node) e insere-se a aresta p Oph

• Faça V = { v | u v, u,v ∈ U & fid(v) = f }

• Se V = Ø cria-se um nó field e adiciona-se a V

• Finalmente, adiciona-se arestas { v q | v ∈ V }

(4) p = q.f;• Faça U = { u | q u },

V = { v | u v, u ∈ U & fid (v) = fid (f) }

• Se U = Ø então cria-se um nó phantom object e adiciona-se a U. Se V = Ø então cria-se um nó field reference e adiciona-se a V.

• (Flow-Sensitive) → aplica ByPass (p)• (Both) → adiciona-se arestas { p v | v ∈ V }

Segue um exemplo ilustrando a computação do CG:

IV.ANALISE INTERPROCEDURAL

Vamos assumir que um método A chama um outro método B. Temos então quatro pontos que são relevantes na análise interprocedural:

• Na entrada do método B;• Na saída do método B;• Em A, imediatamente antes da invocação do método B• Em A, imediatamente após a invocação do método B.

Se método B já foi analisado pelo Escape Analysis então, quando for feito a análise intraprocedural de A, este simplesmente usa a informação sumarizada de B.

Nos exemplos abaixo o método L() (Caller) constrói uma lista ligada e invoca o método T() (Callee) para construir uma estrutura em árvore.

(1) Connection Graph na entrada do método:Para cada parâmetro formal fi, existe um parâmetro real ai no Caller, que produz o valor para fi. No ponto de entrada do Callee cria-se então uma atribuição da forma fi = ai. O argumento fi é tratado como uma variável local dentro do método. Como ela pode ser morta (killed) por outras

2

Page 3: [Choi ooplsa99] resume

nov-2011

atribuições a fi, cria-se então um nó de referência phantom para ai e insere uma aresta diferida de fi para ai. Exemplo:

(2) Connection Graph na saída do método:Modela-se a ação return que retorna uma referência a um objeto como uma atribuição a uma variável especial phantom chamada return. Multiplas ações de retorno são resolvidas no CG executando o “merge” dos respectivos valores return.

Após completar o Escape Analysis intraprocedural para um método usa-se a função ByPass para eliminar todas as arestas diferidas no CG, criando nós phantom onde forem necessários. É o caso do nó R no exemplo abaixo:

Ao final, faz-se a análise de alcançe (reachability analysis) no CG para atualizar os estados de Escape dos objetos. Esta análise particiona o grafo em três subgrafos:

• Subgrafo induzido Sg do conjunto de nós que são “alcançaveis” a partir de um nó GlobalEscape (inicialmente, static fields e objetos runnable).

• Subgrafo induzido Sa do conjunto de nós “alcançaveis” a partir de um nó ArgEscape (inicialmente, nós de referência phantom que representam os parâmetros reais criados na entrada do método, como a1 e a2 no exemplo.

• Subgrafo induzido Sn do conjunto de nós que não são alcançaveis por nenhum nó GlobalEscape ou ArgEscape. Então: Sg U Sa ≅ NonLocalGraph (representa o CG sumarizado do método); Sn ≅ LocalGraph (todos os objetos são marcados stack-allocatable).

(3) CG imediatamente antes da invocação do método B:No local (A) de invocação do método, cada passagem de parâmetros é tratada como uma atribuição a um parâmetro real no chamador. Considere a chamada u1.foo(u2, …, un) onde u2, …, un são os parametros reais. Modela-se a chamada com as atribuições:

â1 = u1; â2 = u2; …; foo (â1, â2, …, ân)

Cada parâmetro no local da chamada será comparado com o nó de referência phantom do método chamado. No exemplo abaixo, dois nós â1 e â2 são criados como arestas diferidas apontando para o primeiro e segundo parâmetros reais da chamada, u e v, respectivamente.

(4) CG imediatamente após a invocação do método B:Neste momento, essencialmente faz-se o mapeamento das informações contidas no CG sumarizado do método chamado de volta para o CG do chamador. Três tipos de nós desempenham um papel importante na atualização do CG, logo após a invocação do método: âi's do caller's CG, ai's do callee's CG e o nó return. A atualização do CG é feito atualizando-se o conjunto de nós do CG do chamador usando âi's e ai's e o respectivo conjunto de arestas. A atualização do nó return é feito tratando o return como um ai e o nó alvo na invocação do método da mesma forma como âi.

As equações abaixo definem, recursivamente, as relações de mapeamento MapsToObj ( ↦ ) para atualização dos nós:

A atualização das arestas é feita da seguinte maneira:Sejam p e q nós objetos do Callee' CG tal que:

Então, para cada ∈ MapsToObj(p) e ∈ MapsToObj(q)estabelece-se

inserindo arestas point-to para cada nó field

3

Page 4: [Choi ooplsa99] resume

nov-2011

tal que:

V. HISTÓRICO E TRABALHOS RELACIONADOS

Analises do tempo de vida de objetos alocados dinâmicamente tem sido tradicionalmente usadas para gerenciar o espaço de armazenamento em tempo de compilação. Park & Goldeberg[2] introduziram o termo Escape Analysis em linguagens funcionais para determinar estaticamente quais partes de uma lista passada para uma função não escapa a chamada da função (e, portanto, podem ser alocadas na pilha). Outros melhoraram e extenderam o trabalho de Park & Goldeberg. Birkedal et al. Propuseram um modelo de alocação baseado em regiões que são gerenciadas durante a compilação. Tem havido uma série de esforços paralelos em Escape Analysis para Java. Bogda & Holzle [3] usam um conjunto de restrições para computar objetos locais às threads. Blanchet [4] atribui “pesos” a tipos para codificar como um objeto de um tipo pode ter referências a outros objetos ou é um subtipo de outro objeto. Ele propõe uma analise flow-insensitive em duas fases (backward e forward) para computar as informações de Escape.

VI. CONCLUSÃO

Choi et al. apresentaram uma nova abordagem para a Escape Analysis que simplifica a analise de fluxo de dados para um problema de alcance (reachability analysis) sob um grafo de conexão (CG). Os resultados experimentais em um protótipo do “IBM High Performance Compiler for Java” para uma máquina alvo “PowerPC 333Mhz, 128MB” mostraram que:

• Ο no de objetos que puderam ser alocados na pilha excedeu 70% dos objetos criados dinamicamente em 3 de 10 benchmarks (com a mediana em 19%);

• 11% a 92% de todas as operações de lock foram eliminadas nos 10 programas (com a mediana em 51%);

• A redução no tempo de execução foi de 2% a 23% (com a mediana em 7%).

VII. REFERENCIAS

[1] Jong-Deok Choi, M. Gupta, M. Serrano, V.C. Sreedhar and S. Midkiff. Escape Analysis for Java. In Proceedings of ACM SIGPLAN Conference on Object-Oriented Programming Systems, Languages and Applications, Denver, Colorado, November 1999.

[2] Y.G. Park and B. Goldberg. Escape analysis on lists. In Proceedings of. ACM SIGPLAN Conference Programming Language Design and Implementation, pages 117-127, July 1992.

[3] Jeff Bodga and Urs Holzle. Removing unnecessary synchronization in java. In Proceedings of ACM SIGPLAN Conference on Object-Oriented Programming Systems, Languages and Applications, Denver, Colorado, November 1999.

[4] Bruno Blanchet. Escape Analysis for object-oriented languages: Applications to Java. In Proceedings of ACM SIGPLAN Conference on Object-Oriented Programming Systems, Languages and Applications, Denver, Colorado, November 1999.

4