a nova gerac¸˜ao do yap prolog: um ambiente experimental de...

161
UNIVERSIDADE ESTADUAL DE MARING ´ A CENTRO DE TECNOLOGIA DEPARTAMENTO DE INFORM ´ ATICA PROGRAMA DE P ´ OS-GRADUAC ¸ ˜ AO EM CI ˆ ENCIA DA COMPUTAC ¸ ˜ AO GEORGE SOUZA OLIVEIRA A Nova Gera¸ c˜ao do YAP Prolog: Um ambiente experimental de compila¸c˜ao just-in-time baseadaemtra¸cosdeexecu¸c˜ao Maring´ a 2013

Upload: others

Post on 25-Apr-2021

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

UNIVERSIDADE ESTADUAL DE MARINGA

CENTRO DE TECNOLOGIA

DEPARTAMENTO DE INFORMATICA

PROGRAMA DE POS-GRADUACAO EM CIENCIA DA COMPUTACAO

GEORGE SOUZA OLIVEIRA

A Nova Geracao do YAP Prolog: Um ambiente experimental decompilacao just-in-time baseada em tracos de execucao

Maringa

2013

Page 2: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

GEORGE SOUZA OLIVEIRA

A Nova Geracao do YAP Prolog: Um ambiente experimental decompilacao just-in-time baseada em tracos de execucao

Dissertacao apresentada ao Programa dePos-Graduacao em Ciencia da Computacaodo Departamento de Informatica, Centrode Tecnologia da Universidade Estadualde Maringa, como requisito parcial paraobtencao do tıtulo de Mestre em Ciencia daComputacao.

Orientador: Prof. Dr. Anderson Faustinoda Silva

Maringa2013

Page 3: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

Dados Internacionais de Catalogação na Publicação (CIP)

(Biblioteca Central - UEM, Maringá, PR, Brasil) Oliveira, George Souza O48n A nova geração do YAP Prolog : um ambien te

experimental de compilação just-in-time baseada em traços de execução / George Souza Oliveira. -- Maringá, 2013.

159 f. : figs., tabs. Orientador: Prof. Dr. Anderson Faustino da Silva. Dissertação (mestrado) - Universidade Es tadual de

Maringá, Centro de Tecnologia, Departamento de Informática, Programa de Pós-Graduação em Ciência d a Computação, 2013.

1. YAP Prolog (Interpretador de linguage ns

lógicas). 2. Compilação just-in-time (Computação). 3. Compilação baseada em traços de execução (Computação). I. Silva, Anderson Faustino da, orient. II. Universidade Estadual de Maringá. Centr o de Tecnologia. Departamento de Informática. Program a de Pós-Graduação em Ciência da Computação. III. Título.

CDD 21.ed. 005.115

GVS-000693

Page 4: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,
Page 5: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

Ao meu Deus, Jesus Cristo, Criador dos ceus e da terra.

Page 6: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

AGRADECIMENTOS

Primeiramente, gostaria de agradecer a todos da minha famılia, que apesar de terem

sido privados da minha presenca, me compreenderam, dedicaram carinho e atencao a

todo o momento. Agradeco tambem ao meu orientador, Anderson Faustino da Silva, pela

dedicacao e exemplo prestados. Anderson, voce e um brilhante orientador e amigo de

verdade.

Agradeco tambem, a todos os meus amigos, aqueles presentes pelos momentos de

descontracao e trocas de ideias, e aqueles distantes que sempre estiveram torcendo

pelo meu sucesso. Dentre eles, agradeco especialmente ao Juliano, que por ser mais

experimente, foi capaz de me dar ideias brilhantes para que eu pudesse utilizar no meu

trabalho.

Por fim, e nao menos importante, agradeco a Coordenacao de Aperfeicoamento de

Pessoal de Nıvel Superior (CAPES) pelo apoio financeiro concedido a este trabalho.

Page 7: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

A Nova Geracao do YAP Prolog: Um ambiente experimental de compilacaojust-in-time baseada em tracos de execucao

RESUMO

As pesquisas voltadas para a implementacao eficiente da linguagem Java apostaram no

uso de um sistema de compilacao just-in-time para otimizar codigo em tempo de execucao.

Alem disso, pesquisas mais recentes tem demonstrado que, ao inves de compilar unidades

de codigo limitados a um unico escopo, compilar os tracos de execucao mais frequentes

acarreta um melhor ganho de desempenho. Baseado neste contexto, este trabalho descreve

uma nova arquitetura para o sistema YAP Prolog, que e capaz de construir tracos de

execucao e entao, gerar codigo nativo para eles. Os resultados obtidos indicaram que a

compilacao just-in-time baseada nessa estrategia alcanca um ganho de desempenho de

25, 2%, variando entre 1, 006% e 134, 4%.

Palavras-chave: YAP Prolog. Compilacao just-in-time. Compilacao baseada em tracos

de execucao.

Page 8: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

New Generation of YAP Prolog: An experimental environment of trace-basedjust-in-time compilation

ABSTRACT

Researches directed to efficient implementation of Java relied on a just-in-time (JIT)

system to optimize code at runtime. Furthermore, recent researches has shown that

compiling common execution traces, instead of code units limited to a single scope, leads to

a better performance gain. Based on this context, this work introduces a new architecture

for the YAP Prolog, which is able to build traces and then generate native code from

them. The results indicated trace-based JIT compilation reaches 25.2% of performance

gain, ranging from 1.006% to 134.4%.

Keywords: YAP Prolog. Just-in-time compilation. Trace-based compilation.

Page 9: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

LISTA DE FIGURAS

Figura - 2.1 Arquitetura generica de um sistema JIT. . . . . . . . . . . . . . . 24

Figura - 3.1 Organizacao da Memoria na WAM. . . . . . . . . . . . . . . . . . 57

Figura - 4.1 Estrutura interna da versao atual do sistema YAP (adaptado de

Costa et al. (2012)). . . . . . . . . . . . . . . . . . . . . . . . . . 78

Figura - 4.2 Estrutura interna do sistema proposto. . . . . . . . . . . . . . . . 79

Figura - 4.3 Fases do Compilador JIT. . . . . . . . . . . . . . . . . . . . . . . 86

Figura - 4.4 Exemplo de um traco gerado para uma clausula com 3 instrucoes. 89

Figura - 4.5 Trecho de um traco com caracterıstica linear em (b) que repre-

senta o fluxo de execucao (marcado em vermelho) em (a). . . . . . 91

Figura - 4.6 Trecho do traco representado na Figura - 4.5, apos o fluxo de

execucao (marcado em vermelho) mudar apos o teste condicional. 91

Figura - 4.7 Trecho de um traco em uma instrucao YAAM que causa uma

excecao para coleta de lixo. Isso implica que, em codigo nativo,

as condicoes para esse tipo de excecao sao as mesmas para codigo

interpretado. O efeito e que, mesmo executando codigo nativo, a

coleta de lixo sempre ocorre em codigo interpretado. . . . . . . . . 92

Figura - 4.8 Trecho do traco representado na Figura - 4.6, mas usando um

bloco elementar para suportar instrucoes condicionais onde um

dos blocos de destino causam backtrack. . . . . . . . . . . . . . . . 93

Figura - 4.9 Exemplo de traco que contem uma instrucao de indexacao. . . . . 95

Figura - 4.10 Traco da Figura - 4.9-(b) apos ser reconstruıdo e recompilado. . . 96

Figura - 4.11 Organizacao do sistema com suporte aos novos predicados. . . . . 97

Figura - 5.1 Impacto do Interpretador Instrumentado no ambiente de execucao.

Quanto menor a barra, maior a desaceleracao. . . . . . . . . . . . 115

Figura - 5.2 Aceleracao/desaceleracao dos programas teste no modo smart

JIT (com e sem recompilacao) sobre o modo somente interpretar.

Valores menores que 1 indicam desaceleracao. . . . . . . . . . . . 117

Figura - 5.3 Percentuais do fluxo de execucao nos componentes ativos no modo

smart JIT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

Figura - 5.4 Aceleracao/desaceleracao dos programas teste no modo compilac~ao

contınua (com e sem recompilacao) sobre o modo somente interpretar.

Valores menores que 1 indicam desaceleracao. . . . . . . . . . . . 121

Page 10: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

Figura - 5.5 Percentuais do fluxo de execucao nos componentes ativos no modo

compilac~ao contınua. . . . . . . . . . . . . . . . . . . . . . . . . 122

Figura - 5.6 Aceleracao/desaceleracao dos programas teste no modo somente

compilar sobre o modo somente interpretar. Valores menores

que 1 indicam desaceleracao. . . . . . . . . . . . . . . . . . . . . . 124

Figura - 5.7 Percentuais do fluxo de execucao nos componentes ativos no

modo somente compilar. O grafico esta representado em escala

logaritmica para destacar os tempos do Compilador JIT. . . . . . . 124

Figura - 5.8 Tempos de construcao, compilacao e execucao dos tracos na

configuracao smart JIT sem recompilacao. Ti representa o traco

de numero i. Valores em vermelho indicam tracos nao uteis. . . . 126

Figura - 5.9 Tempos de construcao, compilacao e execucao dos tracos na

configuracao smart JIT com recompilacao. Ti representa o traco

de numero i. Valores em vermelho indicam tracos nao uteis. . . . 127

Figura - 5.10 Taxas do fluxo de execucao na manutencao das areas de memoria

do sistema sobre o tempo total de execucao de cada programa

avaliado. Os valores sao praticamente os mesmos em todos os

modos de execucao. . . . . . . . . . . . . . . . . . . . . . . . . . . 130

Figura - 6.1 Arquitetura proposta para trabalhos futuros. . . . . . . . . . . . . 137

Page 11: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

LISTA DE TABELAS

Tabela - 2.1 Comparacao entre os sistemas JIT. . . . . . . . . . . . . . . . . . 49

Tabela - 5.1 Programas-teste habitualmente utilizados pela comunidade ci-

entıfica de Prolog. . . . . . . . . . . . . . . . . . . . . . . . . . . 112

Tabela - 5.2 Programas-teste do benchmark shootout. . . . . . . . . . . . . . . 113

Page 12: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

SUMARIO

1 Introducao 12

2 Compilacao JIT 17

2.1 Historico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.2 Arquitetura de Sistemas com Compilacao JIT . . . . . . . . . . . . . . . . 23

2.2.1 Compilador Base e Compilador Otimizador . . . . . . . . . . . . . . 25

2.2.2 Offline Profiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

2.2.3 Online Profiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

2.2.4 Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

2.2.5 Gerente de Codigo . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

2.2.6 Gerente de Compilacao . . . . . . . . . . . . . . . . . . . . . . . . . 28

2.2.7 Repositorio de Codigo . . . . . . . . . . . . . . . . . . . . . . . . . 28

2.2.8 Motor de Execucao . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

2.3 Princıpios de Compilacao JIT . . . . . . . . . . . . . . . . . . . . . . . . . 29

2.3.1 Manutencao dos Sistemas de Compilacao e Execucao . . . . . . . . 30

2.3.2 Acionamento do Sistema de Compilacao . . . . . . . . . . . . . . . 31

2.3.3 Selecao de Unidades de Compilacao . . . . . . . . . . . . . . . . . . 33

2.3.4 Geracao de Versoes Especializadas . . . . . . . . . . . . . . . . . . . 36

2.3.5 Implementacao e Desempenho . . . . . . . . . . . . . . . . . . . . . 39

2.4 Sistemas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

2.5 Consideracoes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

3 Prolog 53

3.1 Controle da Linguagem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

3.2 Maquina Abstrata de Warren . . . . . . . . . . . . . . . . . . . . . . . . . 54

3.2.1 O Estado Interno da WAM e a Organizacao da Memoria . . . . . . 55

3.2.2 Conjunto de Instrucoes . . . . . . . . . . . . . . . . . . . . . . . . . 57

3.3 Melhorando o Desempenho da WAM . . . . . . . . . . . . . . . . . . . . . 62

3.3.1 Especializar a Unificacao . . . . . . . . . . . . . . . . . . . . . . . . 62

3.3.2 Otimizar Selecao de Clausulas . . . . . . . . . . . . . . . . . . . . . 63

3.3.3 Gerar Codigo Nativo . . . . . . . . . . . . . . . . . . . . . . . . . . 64

3.3.4 Utilizar Analise Global . . . . . . . . . . . . . . . . . . . . . . . . . 65

3.3.5 Utilizar Memoizacao . . . . . . . . . . . . . . . . . . . . . . . . . . 66

3.4 Implementacoes Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

3.5 Consideracoes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

Page 13: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

4 O Ambiente Experimental de Compilacao Just-in-Time Baseada em

Tracos de Execucao 73

4.1 Yet Another Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

4.1.1 Estruturas de Dados e Organizacao da Memoria . . . . . . . . . . . 74

4.1.2 Principais Diferencas com a WAM . . . . . . . . . . . . . . . . . . . 75

4.1.3 Estrutura das Clausulas . . . . . . . . . . . . . . . . . . . . . . . . 77

4.1.4 Organizacao do Sistema . . . . . . . . . . . . . . . . . . . . . . . . 77

4.2 A Nova Geracao do YAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

4.3 Os Modulos da Nova Geracao do YAP . . . . . . . . . . . . . . . . . . . . 81

4.3.1 Motor de Execucao . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

4.3.2 Compilador JIT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

4.3.3 Gerente de Codigo . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

4.3.4 Construtor de Tracos . . . . . . . . . . . . . . . . . . . . . . . . . . 88

4.3.5 Modulo de Recompilacao . . . . . . . . . . . . . . . . . . . . . . . . 95

4.4 Os Predicados Suportados na Nova Geracao do YAP . . . . . . . . . . . . 96

4.4.1 Predicados para Analises de Codigo . . . . . . . . . . . . . . . . . . 98

4.4.2 Predicados para Transformacoes de Codigo . . . . . . . . . . . . . . 99

4.4.3 Predicados para Geracao de Codigo . . . . . . . . . . . . . . . . . . 100

4.4.4 Predicados para Configuracao Geral . . . . . . . . . . . . . . . . . . 101

4.4.5 Predicados para Depuracao . . . . . . . . . . . . . . . . . . . . . . 104

4.4.6 Predicados para Coleta de Perfil de Execucao . . . . . . . . . . . . 109

4.5 Consideracoes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

5 Avaliacao Experimental 111

5.1 Metodologia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

5.2 Impacto do Interpretador Instrumentado . . . . . . . . . . . . . . . . . . . 113

5.3 Desempenho dos Diferentes Modos de Execucao . . . . . . . . . . . . . . . 115

5.3.1 O Desempenho de Smart JIT . . . . . . . . . . . . . . . . . . . . . 117

5.3.2 O Desempenho de Compilacao Contınua . . . . . . . . . . . . . . . 121

5.3.3 O Desempenho de Somente Compilar . . . . . . . . . . . . . . . . . 123

5.4 Desempenho na Construcao dos Tracos . . . . . . . . . . . . . . . . . . . . 125

5.5 Consideracoes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

6 Conclusoes e Trabalhos Futuros 133

6.1 Motivacoes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

6.2 A Nova Geracao do YAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

Page 14: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

6.3 Resultados Alcancados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

6.4 Trabalhos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

6.4.1 Gerente de Codigo . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

6.4.2 Compilador JIT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

6.4.3 Motor de Execucao . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

6.4.4 Offline Profiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

6.4.5 Online Profiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140

6.4.6 Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

6.5 Consideracoes Finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

REFERENCIAS 144

Page 15: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

12

1

Introducao

Linguagens que implementam programacao logica (Colmerauer, 1990; Henderson e So-

mogyi, 2002) possuem uma clara correspondencia a logica matematica e expressam a

computacao sem descrever o seu fluxo de controle. Em outras palavras, a descricao do

programa e baseada em “o que” realizar, em vez de “como” realizar, ao contrario do que

ocorre na programacao imperativa (Sebesta, 2009). Isso e baseado na premissa de que

qualquer algoritmo consiste de uma especificacao logica (a descricao das propriedades do

resultado esperado) e um controle (a forma de executar esta especificacao). De posse da

especificacao logica, o proprio sistema e encarregado de prover o controle e encontrar a

solucao do problema (caso esta exista). Esse estilo de programacao torna as linguagens

logicas tanto mais faceis quanto mais difıceis se comparadas a outras estrategias de

programacao. Facil porque a forma de encontrar a solucao fica a cargo do ambiente

de execucao da propria linguagem e difıcil porque esquemas de programacao mais comuns

nao sao suportados.

A primeira linguagem de programacao logica surgiu no inıcio dos anos 70 (Kowalski,

1988) como um provador de teoremas especializado, que eventualmente evoluiu para uma

linguagem mais poderosa chamada Prolog (Colmerauer, 1990; Sterling e Shapiro, 1994).

Esta ultima descreve a programacao como um subconjunto de logica de primeira ordem,

as clausulas de Horn (Horn, 1951), sendo portanto, uma linguagem declarativa (Lloyd,

1994). Essa caracterıstica torna Prolog uma linguagem de programacao simples e eficiente

na implementacao dos conceitos de unificacao e busca.

A implementacao de linguagens declarativas, de Prolog em particular, e uma tarefa

difıcil, visto que as maquinas tradicionais sao sequenciais, uma caracterıstica nao existente

neste tipo de linguagem (pelo menos nao de forma explıcita). Alem disso, como o

Page 16: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

13

controle de execucao fica a cargo da propria linguagem, o desenvolvedor se ve obrigado

a considera-lo e projeta-lo. Isso significa que as estrategias empregadas para criacao

de compiladores ou interpretadores para linguagens imperativas nao sao suficientes para

a criacao de compiladores ou interpretadores para linguagens declarativas, e portanto,

logicas.

Uma alternativa para implementacao de Prolog surgiu com a Maquina Abstrata

de Warren (WAM) (Aıt-Kaci, 1991; Warren, 1983), um modelo que permite compilar

codigo Prolog para uma representacao intermediaria sequencial. Com esse modelo, um

ambiente Prolog pode ser implementado tanto por hardware (Van Roy e Despain, 1992)

quanto por software (Carlsson e Mildner, 2012; Costa et al., 2012; Diaz et al., 2012;

Hermenegildo et al., 2012; Swift e Warren, 2012; Taylor, 1996; Van Roy, 1990; Wielemaker

et al., 2012). Na verdade, a implementacao por hardware consiste apenas de um conceito

teorico, visto que e uma implementacao difıcil devido a alta granularidade das instrucoes

WAM. Alem disso, o desenvolvimento do hardware ao longo dos anos e o aumento

do numero de instrucoes com baixa granularidade para as arquiteturas atuais mostrou

que o uso desse tipo de abordagem e inviavel. Mesmo que um hardware especializado

fosse criado, seria difıcil, mesmo para os mais adeptos, adquirir uma maquina que so

executasse Prolog. Por fim, a dificuldade em obter bom desempenho em hardware

tradicional somado ao custo de implementacao de hardware exclusivo justificam que

ambientes Prolog tenham sido essencialmente projetados por software.

Por outro lado, a implementacao por software acarreta um alto overhead proveniente

da interpretacao de codigo WAM para codigo de maquina equivalente. Alem disso, a

alta granularidade das instrucoes WAM impedem a aplicacao de diversas otimizacoes de

codigo (Muchnick, 1997). Uma alternativa e implementar Prolog para a geracao de codigo

nativo. Os primeiros sistemas a utilizarem essa alternativa foram Aquarius (Van Roy,

1990) e Parma (Taylor, 1996), que utilizavam analise global (Warren et al., 1988) para

especializar a unificacao e otimizar a selecao de clausulas. Embora essas implementacoes

tenham demonstrado que a execucao de Prolog e comparavel a das linguagens imperativas

em alguns casos, as mesmas foram abandonadas por serem muito difıceis de manter.

Dessa forma, os sistemas Prolog mais comuns sao atualmente implementados como

interpretadores (Carlsson e Mildner, 2012; Costa et al., 2012; Diaz et al., 2012; Her-

menegildo et al., 2012; Swift e Warren, 2012; Tarau, 1991; Wielemaker et al., 2012).

Como alternativa, alguns deles tambem oferecem execucao de codigo nativo, como

GNU-Prolog (Diaz et al., 2012), SICStus Prolog (Carlsson e Mildner, 2012), CIAO

(Hermenegildo et al., 2012) BinProlog (Tarau, 1991) e XSB Prolog (Swift e Warren,

2012). Dentre as implementacoes existentes, YAPc (Silva e Costa, 2007) se destaca por

Page 17: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

14

empregar uma abordagem diferente, que consiste em gerar codigo em tempo de execucao

para as regioes executadas com mais frequencia. YAPc foi projetado para ser utilizado

com o interpretador YAP (Costa et al., 2012), a fim de torna-lo um ambiente de modo

misto de execucao. Um sistema deste porte possui a vantagem de utilizar informacoes

coletadas em tempo de execucao para especializar o codigo nativo a ser gerado, sem a

necessidade de implementar um analisador global (Warren et al., 1988).

Em sıntese, o princıpio basico de YAPc e o mesmo dos compiladores just-in-time

(JIT) desenvolvidos para sistemas Java, como Jikes (Arnold et al., 2000; Burke et al.,

1999), JUDO (Cierniak et al., 2000) e Sun Hotspot (Kotzmann et al., 2008; Paleczny et

al., 2001): em primeiro lugar, cada unidade de codigo (que no contexto de YAPc, se trata

de uma clausula) e instrumentada com contadores e entao interpretada. Cada contador

e incrementado na medida em que as unidades associadas sao invocadas. Durante este

processo, um profiler coleta informacoes sobre o programa em execucao e, ao atingir um

certo limite de invocacao, a unidade e selecionada para compilacao. Por fim, o compilador

JIT e acionado a fim de gerar codigo especializado baseado nas informacoes anteriormente

coletadas.

Silva e Costa (2007) mostraram que YAP obtem ganho de desempenho na execucao de

programas com longas entradas quando o YAPc e acionado. Apesar de suas vantagens,

YAPc possui algumas restricoes de implementacao que o impede de gerar resultados

melhores, principalmente para programas com pouco tempo de execucao (Silva, 2006),

que sao:

1. Uma quantidade limitada de otimizacoes (transformacoes) de codigo. Geralmente,

a escolha das otimizacoes para determinadas unidades de codigo influenciam o

desempenho geral do sistema e o numero reduzido delas limita a variedade de

escolhas.

2. Um alocador de registradores baseado em um algoritmo de coloracao de grafo

(Muchnick, 1997), que e capaz de gerar bons resultados, mas que possui um custo

que nao compensa ser aplicado em ambientes de compilacao JIT. O fato e que

compiladores JIT compilam codigo em tempo de execucao e, por esta razao, devem

ser leves e eficientes de tal modo que gerem codigo aceitavel no menor tempo possıvel.

3. O compilador mostrou ser apenas uma prova de conceito. Embora o trabalho com

o YAPc tenha demonstrado ser uma boa alternativa de implementacao de Prolog,

este nao se tornou uma implementacao disponibilizada nas versoes do YAP.

Page 18: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

15

Em vista disso, o principal objetivo deste trabalho e projetar e implementar uma

nova arquitetura de compilacao JIT para o YAP, mais precisamente, um modulo de

compilacao JIT baseada em tracos de execucao. O esquema de compilacao baseada em

tracos de execucao difere da estrategia adotada em YAPc, bem como da maioria dos

sistemas JIT atuais, por nao se limitar ao escopo de uma unidade de codigo tradicional,

como um metodo, funcao ou clausula.

Um objetivo secundario deste trabalho e fornecer ao YAP a capacidade de ser um

ambiente experimental de compilacao JIT para Prolog. Esta ultima proposta pode ser

concretizada pelo desenvolvimento de predicados nativos, que auxiliam na configuracao

do sistema quanto a forma que o mesmo executa, compila e gerencia o codigo. Em

especıfico, tais predicados podem: (1) modificar os modos de execucao de codigo, (2)

aplicar transformacoes de codigo na variedade e ordem que o usuario desejar, (3) habilitar

analises de codigo, tais como o tempo gasto para compilar e executar codigo nativo e (4)

realizar tarefas de depuracao quando determinada condicao for satisfeita.

Este trabalho pretende conciliar os objetivos estabelecidos com o padrao de funcio-

namento que tem sido considerado desde a implementacao do YAPc, que consiste em

preservar a ilusao de que o sistema executa diretamente o programa na forma que o

programador escreveu, invocando o ambiente de compilacao e otimizando codigo de forma

transparente. Esse padrao traz alguns pontos a serem considerados (Silva, 2006):

1. O programador deve ser livre para editar qualquer clausula do sistema;

2. O programador deve ser capaz de entender a execucao do programa e qualquer erro

que ocorra no programa em termos do codigo fonte e construcoes da linguagem; e

3. O programador deve se isolar do fato dos programas serem compilados.

Portanto, a proposta deste trabalho busca alcancar dois resultados finais:

1. Tornar Prolog mais proximo das linguagens tradicionais, como C e Java, ou que,

no mınimo, a arquitetura proposta seja capaz de executar codigo mais rapidamente

que a versao atual do sistema.

2. Flexibilidade dos parametros e novos modos de execucao, para que o usuario realize

diversos experimentos;

Os resultados obtidos na avaliacao deste trabalho mostraram ganho de desempenho

para a maioria dos programas, que variou de 1, 006% a 134, 4%, com uma media de

25, 2% sobre a versao atual do sistema. Esses valores foram obtidos a partir da execucao

Page 19: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

16

do sistema em diversas configuracoes diferentes, com o uso de predicados que modificam

os parametros e modos de execucao.

Isso mostra, portanto, que os resultados buscados neste trabalho foram alcancados.

Alem disso, os resultados obtidos apontaram diversos trabalhos futuros, com o objetivo

de diminuir custos e aperfeicoar os tracos construıdos para cada programa.

A fim de apresentar os conceitos iniciais, a nova arquitetura, resultados e trabalhos

futuros, esta dissertacao esta organizada da seguinte forma: O Capıtulo 2 contem a

teoria relacionada a compilacao just-in-time, seus conceitos, historico e princıpios, alem

de exemplos de alguns sistemas. O Capıtulo 3 contem os fundamentos de Prolog, com

o foco na WAM e suas formas de implementacao. O Capıtulo 4 apresenta a arquitetura

do novo sistema como uma extensao da arquitetura atual, apresentada por Costa et al.

(2012). O Capıtulo 5 apresenta os resultados obtidos e, por fim, o Capıtulo 6 apresenta

as conclusoes e trabalhos futuros.

Page 20: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

17

2

Compilacao JIT

As implementacoes originais de linguagens de programacao interativas e de alto-nıvel

(Scott, 2009; Sebesta, 2009) focavam no desenvolvimento de maquinas virtuais eficientes

que provessem portabilidade aos programas desenvolvidos nessas linguagens. Mais re-

centemente diversas pesquisas tem focado nao apenas no desenvolvimento de maquinas

virtuais que proveem portabilidade, mas tambem de maquinas virtuais cuja execucao

seja eficiente, em termos de uso de recursos e tempo de execucao. Para alcancar

este objetivo, as maquinas virtuais atuais incluem em sua arquitetura um sistema de

compilacao just-in-time (JIT).

Em contraste com compiladores tradicionais, em uma maquina virtual com compilacao

JIT o tempo de compilacao esta incluıdo no tempo total de execucao, pois a compilacao

ocorre durante a execucao do programa. Portanto, e uma questao crıtica decidir quando,

o que e como compilar os programas. Mais especificamente, o sistema de compilacao deve

apenas compilar codigos se o tempo gasto na compilacao for amortizado pelo desempenho

ganho pelo codigo compilado. O custo de compilacao e o desempenho obtido e uma

questao crucial em ambientes com compilacao JIT. Porem, tais ambientes possuem um

grande benefıcio: eles podem explorar informacoes obtidas em tempo de execucao para

decidir quais otimizacoes aplicar, alem de quais porcoes de codigo compilar (Santos et al.,

2013).

As primeiras maquinas virtuais com compilacao JIT utilizavam estrategias estaticas

simples para escolher as porcoes de codigo que seriam compiladas. Tipicamente, tais

maquinas compilavam cada porcao de codigo com um conjunto fixo de otimizacoes durante

a primeira invocacao destas. Estas maquinas incluem os trabalhos com Smalltalk-80

Page 21: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

18

(Deutsch e Schiffman, 1984), SELF-91 (Chambers e Ungar, 1989, 1990; Chambers, 1992),

e Kaffe (Wilkinson e Mehlitz, ????).

Maquinas virtuais mais sofisticadas, em vez de utilizarem estrategias estaticas simples,

selecionam dinamicamente subconjuntos de codigos para otimizar. Esses subconjuntos

sao as regioes quentes do programa, isto e, porcoes de codigo executadas com alta

frequencia. Exemplos de maquinas virtuais desta categoria incluem SELF-93 (Holzle,

1995; Holzle e Ungar, 1994) e a primeira versao da Maquina Virtual Java (JVM - do

ingles Java Virtual Machine) da IBM (Suganuma et al., 2000). Embora, estas maquinas

virtuais tambem incluam formas limitadas de otimizacoes baseadas em informacoes

obtidas em tempo de execucao, estes trabalhos nao desenvolveram mecanismos gerais

para otimizacoes baseadas em tais informacoes.

Recentemente diversos trabalhos tem explorado formas mais agressivas de compilacao

JIT (Burke et al., 1999; Silva e Costa, 2007; Suganuma et al., 2004), utilizando informacoes

obtidas em tempo de compilacao e/ou execucao, para adaptar o ambiente as caracterısticas

do programa. Contudo, alguns destes trabalhos nao sao totalmente automaticos, desta

forma, nao aparecendo em maquinas virtuais populares. Porem, estes tem demonstrado

que otimizacoes baseadas em tais informacoes melhoram substancialmente o desempenho

da maquina virtual.

Isto mostra que o componente principal desta nova geracao de maquinas virtuais e um

mecanismo sofisticado de otimizacao baseado em informacoes coletadas dinamicamente.

Contudo, tais tecnicas nao sao aplicaveis em todos os programas. De fato, em alguns casos

(por exemplo, programas com curto tempo de execucao), o alto custo de tais estrategias

geralmente ocasionam uma perda de desempenho (Silva e Costa, 2006).

Tecnicas de compilacao JIT existem desde 1960 com LISP (McCarthy, 1960) e se

propagaram por diversas linguagens de programacao ao longo dos anos. Contudo, somente

com o advento da JVM (Lindholm e Yellin, 1999) e que o termo JIT ficou realmente

conhecido pela comunidade cientıfica (Aycock, 2003).

Portanto, seguindo este contexto, o objetivo deste capıtulo e abordar questoes relativas

a essa tecnica. A Secao 2.1 apresenta um historico e como essa tecnica evoluiu ao longo

dos anos. A Secao 2.2 apresenta uma arquitetura generica de um sistema de compilacao

JIT e como seus componentes se inter-relacionam. A Secao 2.3 descreve os princıpios

de compilacao just-in-time, em especıfico os tipos de abordagens empregados e a forma

com que as regioes quentes de codigo sao detectadas e tratadas. A tecnica de compilacao

baseada em tracos de execucao, que e a motivacao deste trabalho, tambem e discutida

nessa secao. A Secao 2.4 apresenta as principais caracterısticas de sistemas atuais de

compilacao JIT e, por fim, o capıtulo finaliza com algumas consideracoes (Secao 2.5).

Page 22: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

19

2.1 Historico

O primeiro trabalho relacionado a compilacao JIT data de 1960 e trata sobre a linguagem

LISP (McCarthy, 1960). Neste trabalho, McCarthy menciona a compilacao de funcoes

para uma linguagem de maquina rapida o suficiente para que a saıda do compilador

nao necessitasse ser salva. Em 1968, os desenvolvedores da linguagem LC2 (ou LCC)

observaram que o codigo compilado pode ser gerado em tempo de execucao a partir

de um interpretador, simplesmente anotando as acoes realizadas (Mitchell et al., 1968).

Dois anos depois, APL (Abrams, 1970) incorporou duas tecnicas que se relacionam

com compilacao JIT. Drag-along, que consistia em adiar a avaliacao de expressoes ate que

informacoes de contexto fossem reunidas e beating, que transformava codigo para reduzir

a quantidade de manipulacao de dados envolvidos durante a avaliacao das expressoes.

Em APL, os tipos dos dados nao sao conhecidos ate o tempo de execucao, o que forcava o

ambiente adiar a aplicacao dessas tecnicas.

Em 1971, Knuth, por meio de dados de estudos empıricos, observou que a maior

quantidade de tempo de execucao gasto em um programa decorre de pequenas porcoes

de codigo. Esta base serviu para que um trabalho posterior, realizado por Dakin e

Poole (1973), investisse em tecnicas que permitissem um balanceamento entre tempo de

execucao e espaco, os quais fundamentavam o argumento para compilacao JIT na epoca.

Dentre as tecnicas desenvolvidas, uma tinha como objetivo executar os programas em duas

versoes de codigo: a nativa, para as regioes quentes, e a interpretada, para as demais. Essa

tecnica foi denominada codigo misto e ainda e aplicavel em alguns sistemas JIT atuais.

Por volta do ano de 1976, Brown desenvolveu a tecnica throw-away (Brown, 1976), que

buscava otimizar o espaco compilando partes do programa sob-demanda, em vez de aplicar

compilacao estatica. Assim, esgotando a memoria, todo o codigo ja compilado (ou partes

dele) seria descartado e recompilado posteriormente, caso necessario.

No trabalho de Hansen com Adaptive Fortran, de 1974, foi apresentada uma visao

fundamental para sistemas JIT em geral (Hansen, 1974). Esta visao agregava tres

princıpios basicos sobre a forma com que o codigo deveria ser tratado pelos sistemas

JIT. Hansen descreveu a importancia de qual codigo compilar, alem de quando e como

compila-los. Ao mesmo tempo, Hansen procurou satisfazer tais fundamentos, utilizando

e mantendo contadores vinculados a cada regiao de codigo para identificar aquelas que

sao quentes, embora ainda aplicasse otimizacoes de codigo (o como) de forma muito

conservativa sobre tais regioes.

Por outro lado, no desenvolvimento de Smalltalk-80 em 1984 (Deutsch e Schiffman,

1984), Deutsch e Schiffman optaram por gerar codigo nativo em tempo de execucao na

Page 23: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

20

medida em os metodos eram invocados, em vez de compilar somente os metodos quentes,

como fez Hansen. O codigo nativo era entao armazenado em uma cache, para serem

recuperados posteriormente. Mais tarde, Smalltalk-80 serviu de influencia para uma

implementacao de SELF-91 (Chambers e Ungar, 1989, 1990; Chambers, 1992).

SELF-91 possui caracterısticas bem peculiares, quando comparada com trabalhos

anteriores. Nesta linguagem toda acao e dinamica, os tipos nao sao conhecidos ate

o momento da execucao e o uso de classes e substituıda a favor de prototipos. Essas

caracterısticas levaram ao desenvolvimento de tecnicas de compilacao e otimizacao JIT

mais agressivas ate aquele momento. Uma delas foi a tecnica de customizacao de metodos

desenvolvida por Chambers e Ungar em 1989, cuja funcionalidade era especializar codigo

para um tipo de dado especıfico coletado no tempo de execucao (Chambers e Ungar, 1989).

O sistema desenvolvido ainda introduziu o conceito de compilacao adiantada para casos

incomuns: eventos como overflow aritmetico nao teriam, a princıpio, codigo compilado.

Em vez disso, uma informacao seria vinculada para que codigo fosse gerado somente se

tais eventos ocorressem.

Em 1995 o trabalho de Holzle, com a terceira geracao de SELF (SELF-93) (Holzle,

1995; Holzle e Ungar, 1994), inovou com a implementacao da tecnica de otimizacao

adaptativa: primeiramente, todo metodo invocado era compilado por um compilador nao

otimizador rapido e somente as regioes quentes, detectados por meio de contadores, eram

recompiladas por um compilador otimizador. Quatro anos antes, a linguagem Java surgiu

para ser puramente interpretada. As JVMs iniciais, entretanto, eram interpretadores

puros e resultavam em execucoes muito lentas (Cramer et al., 1997; Tyma, 1998), o que

obrigou os seus desenvolvedores a buscarem nos conceitos de compilacao JIT a solucao

para resolver tal problema.

A visao inicial de compilacao JIT para Java foi dada por Cramer et al. (1997). Neste

trabalho, os autores observaram que somente a traducao de codigo Java para codigo

nativo nao era suficiente e alem disso, a otimizacao de codigo era tambem necessaria.

Seguindo essa visao, em 1997, Plezbert e Cytron apresentaram diferentes modelos teoricos

de sistemas JIT, dentre eles, um que compila e executa codigo de forma concorrente. Dois

destes modelos interpretavam as regioes nao quentes e compilavam aquelas que sao quentes

apos um certo tempo.

Porem, contrario as versoes apresentadas por Plezbert e Cytron, Burke et al. (1999)

apresentaram a maquina virtual Jalapeno, que somente compilava codigo, embora ainda

incorporasse um compilador JIT na sua estrutura. A mesma ideia foi seguida um ano

depois por Cierniak et al. (2000) no desenvolvimento de JUDO.

Page 24: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

21

No mesmo ano do surgimento de JUDO, o trabalho teorico de Reinholtz relatou

a possibilidade de Java se tornar mais rapida que C++ (Reinholtz, 2000). O autor se

baseou nos compiladores JIT para Java na epoca que eram auxiliados por informacoes

coletadas dinamicamente, alem do surgimento de sistemas embarcados que, segundo

o autor, forcariam a necessidade para o desenvolvimento de tecnicas mais agressivas

e eficientes de otimizacao de codigo, visto que tais sistemas possuem recursos muito

limitados de hardware. Contudo, em 2010, Foleiss e Silva demonstraram que Java nao e

mais rapida que C++.

Na verdade, as JVMs atuais obtem melhor desempenho de execucao dos programas em

comparacao as JVMs primitivas, e uma parcela significativa desse ganho foi obtido pela

selecao correta de regioes quentes dos programas, ao contrario do que previa Reinholtz.

Embora otimizacoes de codigo sejam importantes, como descrito por Cramer et al., a sua

aplicacao nao e suficiente. Tal afirmacao foi justificada anos mais tarde, quando a maioria

dos trabalhos focaram na precisao da obtencao de regioes quentes, obtendo resultados

satisfatorios. O trabalho de Krintz, de 2003, empregou offline e online profiling para

detectar tais regioes e alcancou melhorias de desempenho de 9%, em media (Krintz, 2003).

No mesmo ano, Suganuma et al. (2003) adotaram o modelo de compilacao baseada em

regiao e obtiveram codigo 5% melhor, em termos de execucao, alem de reduzir o overhead

de compilacao entre 20 a 30% em comparacao aos compiladores baseados em sub-rotinas

(que eram os modelos mais comuns da epoca). Um ano depois, Kumar empregou no

seu trabalho uma tecnica denominada estimacao relativa que, em tempo de execucao

determinava a criticidade dos metodos. Essa abordagem garantiu melhorias de 4% nos

programas avaliados (Kumar, 2004).

Em 2006, Agosta et al. propuseram uma heurıstica estatica para identificar blocos

basicos e estimar o numero de lacos do programas. Algumas metricas foram elaboradas

para fornecer estimativas da complexidade de um metodo. Essas estimativas acom-

panhavam o uso de contadores de frequencia para detectar regioes quentes de forma

mais precisa. Mais tarde, Lee at al. (2008) propuseram um trabalho similar, com a

caracterıstica adicional de prever a contagem de frequencia dos metodos menos comuns,

tomando por base a frequencia dos metodos ja compilados. Esta abordagem reduziu o

custo de manutencao dos contadores dos metodos e alcancou bom desempenho.

Outra abordagem foi utilizada por Gal et al. (2006) na implementacao de Hot-

pathVM. Neste trabalho, os autores utilizaram o recurso de compilacao baseada em

tracos de execucao, anteriormente apresentado em Dynamo (Bala et al., 2000). O

desempenho obtido nao foi comparavel aquele obtido por Lee et al. (2008), mas mostrou

ser uma tecnica vantajosa na aplicacao de diversas otimizacoes de codigo (Zhao et al.,

Page 25: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

22

2008). Cinco anos depois, Hayashizaki et al. (2011) propuseram uma tecnica para

deteccao e remocao de falso laco dentro de um traco de execucao e conseguiram uma

melhoria de desempenho de 37% na execucao dos programas avaliados.

Por outro lado, no que tange as otimizacoes de codigo, ha ainda poucas contribuicoes.

Na verdade o estado-da-arte de compilacao JIT consiste da otimizacao adaptativa, ja

presente em Jikes RVM (antes chamada Jalapeno) desde 1999 (Burke et al., 1999).

Este sistema implementa diferentes nıveis de otimizacao, que consistem de um conjunto

restrito de otimizacoes atribuıdas manualmente. Recentemente, um trabalho atribuıdo a

Hoste et al. (2010) tem procurado utilizar busca evolucionaria para atribuir otimizacoes

para cada nıvel de forma automatica, evitando assim o esforco manual.

Outro sistema que tambem implementa otimizacao adaptativa e aMaquina Virtual

da IBM (Suganuma et al., 2004), porem, os conjuntos de otimizacoes atribuıdas sao

baseados em resultados de estudos empıricos realizados por Ishizaki et al. (2003). Embora

a contribuicao de Hoste et al. tenha sido focada em Jikes RVM, sua contribuicao pode

ser empregada em qualquer sistema que implementa otimizacoes em nıveis.

As pesquisas voltadas a compilacao JIT, no entanto, nao se limitam somente na

precisao na deteccao de regioes quentes ou nas otimizacoes de codigo. Trabalhos mais

recentes tem focado na descoberta de boas polıticas de compilacao JIT em maquinas

multi-core (Stallings, 2005). Em 2007, Kulkarni et al. abordaram questoes sobre o

escalonamento da thread de compilacao e descobriu que o desempenho de execucao dos

sistemas JIT e proporcional ao aumento de sua prioridade. Quatro anos depois, Kulkarni

(2011) procurou alcancar, de forma experimental, a melhor polıtica de compilacao para

maquinas multi-core, e descobriu que o aumento do numero de threads de compilacao,

juntamente com a aceleracao na deteccao de regioes quentes e uma boa estrategia para

obter bons resultados. Sistemas JIT, como Jikes RVM (Arnold et al., 2000; Burke et

al., 1999), Hotspot Server (Paleczny et al., 2001), ILDJIT (Campanoni et al., 2008,

2010) e a Maquina Virtual da IBM (Suganuma et al., 2004) nao seguem a melhor

polıtica descoberta nesses trabalhos, mas usufruem do real paralelismo oferecido pelas

arquiteturas atuais.

De fato, a pressao sobre uma JVM rapida impulsionou diversas pesquisas voltadas a

compilacao JIT para a linguagem Java (Aycock, 2003), que resultou em diversas tecnicas

e princıpios que foram gradualmente inseridos e aperfeicoados para a construcao dos

diversos sistemas que surgiram. Atualmente sao conhecidas diversas JVMs, tais como

Sun HotSpot (Kotzmann et al., 2008; Paleczny et al., 2001), JUDO (Cierniak et

al., 2000) e Jikes RVM (Arnold et al., 2000; Burke et al., 1999) que empregam um

conjunto de otimizacoes sobre os programas. Nao obstante, os mesmos princıpios foram

Page 26: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

23

tambem empregados na construcao de diversos outros sistemas para outras linguagens,

como Erlang (Pettersson et al., 2002), Lua (Pall, ????), Prolog (Silva e Costa, 2007),

JavaScript (Chang et al., 2009) e PHP (Homescu e Suhan, 2011).

2.2 Arquitetura de Sistemas com Compilacao JIT

No decorrer da evolucao de sistemas JIT, diversas tecnicas e princıpios foram elaborados

e incorporados na medida em que vinham sendo criados. Atualmente, alguns sistemas

apostam na deteccao de regioes quentes viaveis para otimizacao/compilacao (Gal et al.,

2009; Pall, ????; Pettersson et al., 2002) e outros sistematizam o emprego de otimizacoes

de codigo (Arnold et al., 2000; Suganuma et al., 2004). Contudo, mesmo que o objetivo de

tais sistemas seja compilar e executar codigo nativo sem gerar degradacao no desempenho,

os meios empregados para alcancar esse objetivo podem ser bastante diversificados.

Um sistema JIT e projetado para funcionar em uma das seguintes formas: inter-

pretacao mais compilacao ou compilacao mais recompilacao. Sistemas baseados na

primeira forma interpretam todas as unidades de codigo do programa (funcao, metodo

ou clausula, dependendo das caracterısticas da linguagem de programacao para a qual

o sistema foi desenvolvido) e geram codigo nativo para as regioes quentes com um

compilador otimizador. Por outro lado, sistemas que compilam e recompilam sempre

executam codigo nativo. Nestes, toda unidade de codigo invocada e compilada por um

compilador base rapido e as regioes quentes sao:

• Recompiladas apenas uma vez por um compilador otimizador; ou

• Recompiladas varias vezes, caso o sistema verifique que as unidades ja compiladas

se tornaram invalidas (como no caso de um ou mais de seus dados terem o conteudo

modificado para outro tipo) ou se o gerente de compilacao julgar que uma unidade

ja otimizada necessita ser reotimizada com tecnicas mais agressivas.

A arquitetura padrao de um sistema JIT e como apresentado na Figura - 2.11. Dentre

os componentes do sistema de compilacao, o principal e o compilador otimizador. As

otimizacoes aplicadas por ele e o modo como elas sao aplicadas satisfazem a decisao

de projeto de cada desenvolvedor. Tais otimizacoes sao adicionalmente guiadas por in-

formacoes de perfil (como tipos de dados), coletadas em tempo de compilacao (pelo offline

profiler) ou execucao (pelo online profiler), para especializar o codigo e consequentemente

torna-lo mais eficiente. Adicionalmente, tais informacoes podem ser enviadas ao gerente

1Essa organizacao foi proposta neste trabalho.

Page 27: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

24

de compilacao, caso existir, para que este crie um plano de compilacao que sera enviado

ao compilador otimizador para auxilia-lo na otimizacao e geracao de codigo.

Monitor

Repositório (Áreas)de código

Fila de (re)compilação

PerfiladorOnline

CompiladorBase

PerfiladorOnline

CompiladorOtimizador

PerfiladorOnline

Gerente deCompilação

PerfiladorOnline

Gerente deCódigo

PerfiladorOnline

Motor deExecução

PerfiladorOnlineOfflineProfiler

Informações coletadas em tempo de execução

Informações coletadasem tempo de execução

Versão correta decódigo para executar

Gerenciamento das

versões de código

Parâmetros para contarfrequência das unidades

Informações coletadas em tempo de compilação ou carga

Alerta gerente decódigo queuma unidadese tornou crítica

Código (re

)compilado

Requisição de (re)compilação(uma região crítica)

Região crítica

Plano de compilação Códigocompilado

Informações coletadasem tempo de compilaçãoou carga

Versãointerpretada

Versãocompilada

Sistema de Compilação Sistema de Execução

PerfiladorOnlineOnlineProfiler

Região quente

Monitor

CompiladorBase

CompiladorOtimizador

Gerente deCompilação

Gerente deCódigo

OfflineProfiler

OnlineProfiler

Motor deExecução

Figura 2.1: Arquitetura generica de um sistema JIT.

Independente da forma de funcionamento, o sistema implementa um componente,

chamado monitor, cuja finalidade e instrumentar cada unidade de codigo e medir a

frequencia de execucao destas. Este monitoramento pode ser feito por meio de contadores

ou tempo. Contadores sao incrementados a cada invocacao/termino de execucao da

unidade de compilacao (Plezbert e Cytron, 1997) e fracoes de tempo sao verificadas

durante a execucao. Em outras palavras, a funcao do monitor e detectar regioes quentes,

isto e, regioes de codigo cujo contador (ou tempo) excedeu um limite e emitir um alerta

ao gerente de codigo para que o mesmo envie a regiao quente recem detectada para

(re)compilacao. Existem ainda outros sistemas que geram codigo com um compilador

otimizador no momento em que as unidades sao invocadas porem, para tais sistemas, o

monitor nao e utilizado.

Dessa forma, na medida em que as regioes quentes sao detectadas, estas sao encami-

nhados do gerente de codigo para o gerente de compilacao e inseridas na fila de compilacao.

A partir de entao, o compilador otimizador compila a regiao quente do inıcio da fila e

encaminha o codigo gerado para o gerente de codigo.

Por sua vez, o gerente de codigo gerencia as versoes de codigo para cada unidade de

codigo existente no ambiente. Embora este componente possa nao estar enquadrado como

um componente particular de alguns sistema JIT, suas funcionalidades subsistem, sendo

elas:

Page 28: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

25

• Enviar a versao correta de codigo para ser executada pelo motor de execucao. Em

sistemas que interpretam e compilam, se uma unidade esta disponıvel nas duas

versoes, a prioridade de execucao e da versao compilada, pois esta e mais rapida.

Por outro lado, em sistemas que compilam e recompilam, a prioridade e da versao

mais recente. O ultimo caso prevalece em sistemas que recompilam varias vezes,

pois nestes, o codigo tende a ser mais eficiente a cada recompilacao.

• Enviar codigo para o gerente de compilacao, que por sua vez, solicita (re)compilacao.

• Receber codigo provido pelo compilador base ou otimizador apos uma unidade (ou

regiao quente) ser compilada e armazena-la no repositorio de codigo.

O repositorio de codigo consiste de estruturas que armazenam as versoes do codigo:

versao interpretada e versao nativa. A versao interpretada e padrao dos sistemas de modo

misto e pode ser gerada estaticamente, como os bytecodes das JVMs, ou no tempo de carga

do sistema, como o codigo YAAM (Costa, 1999; Lopes, 1996) do YAP com compilacao

JIT (Silva e Costa, 2007). A versao nativa, por sua vez, consiste de codigo de maquina

gerado pelo compilador base ou ainda das regioes quentes que foram geradas em tempo de

execucao. Embora o repositorio de codigo tenha tanto codigo intepretado quanto nativo,

apenas os sistemas de modo misto executam ambas as versoes.

O motor de execucao e responsavel por executar o codigo recebido do gerente de codigo,

independente de sua versao. Este componente pode variar entre varios modos de execucao

para partes especıficas do programa. Sistemas que interpretam unidades nao frequentes e

compilam as demais funcionam em um modo misto de execucao. Analogamente, sistemas

que (re)compilam codigo funcionam apenas no modo de execucao de codigo nativo.

As proximas subsecoes fornecem mais detalhes sobre os possıveis componentes da

arquitetura de um sistema JIT.

2.2.1 Compilador Base e Compilador Otimizador

O compilador base gera codigo nativo em tempo de execucao para todas as unidades de

codigo invocadas pelo sistema, imediatamente antes da primeira invocacao. O objetivo

deste compilador e ser um gerador rapido de codigo nativo. Desta forma, o compilador

base nao aplica as unidades compiladas um conjunto de otimizacoes.

Com uma abordagem diferente do compilador base, o compilador otimizador gera

codigo nativo em tempo de execucao para as regioes quentes. Por padrao, todo codigo

compilado e otimizado com um conjunto de otimizacoes pre-definido, independente do

programa em execucao. Contudo, o sistema pode ajustar automaticamente o compilador

Page 29: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

26

para que este altere o nıvel de otimizacao que sera aplicado em uma determinada regiao

quente. Isto possibilita que o sistema recompile unidades de codigo buscando melhorar

o desempenho, como tambem proporciona que o sistema se ajuste automaticamente as

caracterısticas do programa em execucao.

2.2.2 Offline Profiler

O offline profiler e utilizado para derivar informacoes em tempo de compilacao ou

carregamento do programa, que possam guiar a geracao de codigo especializado. Desta

forma, o objetivo do uso de tais informacoes e melhorar o desempenho do codigo

compilado, aumentando a velocidade de execucao e/ou reduzindo o tamanho do codigo.

A ideia geral e executar o programa sobre um domınio conservativo, a fim de satisfazer

um conjunto de restricoes. No termino da execucao, os resultados encontrados fornecem

uma aproximacao das informacoes sobre o programa analisado2. Tais informacoes incluem

tipos de dados (no caso de sistemas para linguagens com tipagem dinamica), tamanho

das unidades de codigo (metodo, funcao ou clausula), existencia de chamadas aninhadas,

quantidade e tipos dos parametros, existencia de recursividade ou mesmo regioes quentes

de codigo.

2.2.3 Online Profiler

O online profiler permite que o sistema JIT se adapte as caracterısticas do programa

em execucao. Para alcancar tal objetivo, o online profiler monitora a execucao dos

programas e coleta informacoes que possibilitam a geracao de codigo especializado. Isto e

independente da forma que o sistema foi projetado, ou seja, e independente do uso de um

modo de interpretacao mais compilacao ou compilacao mais recompilacao. Nesse sentido,

o online profiler pode coletar as seguintes informacoes:

Tipos de variaveis Sistemas JIT empregados em linguagens com tipos dinamicos po-

dem se beneficiar da coleta do tipo das variaveis. Neste caso especıfico, o sistema

e tradicionalmente implementado de forma generica para todos tipos de dados

possıveis, o que reflete em instrucoes de checagem de tipos durante a execucao.

Portanto, o uso de informacoes desse tipo permite que tais checagens sejam remo-

vidas.

2As aproximacoes resultantes do processo podem ser corretas, mas ainda existem casos extremosem que o profiler nao visita regioes de codigo visitados pelo programa executado com entradas reais.Portanto, em casos extremos, nao e possıvel definir a corretude das aproximacoes coletadas.

Page 30: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

27

Tempo de interpretacao Essa informacao e util dependendo da metrica utilizada para

determinar se uma unidade e quente ou nao e consequentemente acionar o sistema

de compilacao. As metricas utilizadas pelos sistemas JIT serao descritas na Secao

2.3.2.

Tempo de compilacao Assim como o tempo de interpretacao, o tempo de compilacao

e outra informacao necessaria ao sistema, dependendo da metrica utilizada, porque

permite definir um tempo ideal de interpretacao para que as unidades de codigo se

tornem regioes quentes. O uso de tal informacao tambem sera descrito na Secao

2.3.2.

E importante observar que as informacoes coletadas podem ser facilmente modificadas

durante a execucao, dependendo das caracterısticas da linguagem de programacao para a

qual o sistema foi desenvolvido.

2.2.4 Monitor

O sistema JIT instrumenta as unidades de codigo do programa com parametros de

frequencia a fim de medir a frequencia de execucao de tais unidades. Esta instrumentacao

pode ser feita com o uso de contadores ou fracao de tempo. Desta forma, e papel do

monitor atualizar o parametro de frequencia e, na medida em que tal parametro atinja

um limite pre-definido, alertar ao gerente de codigo que tal unidade se tornou frequente.

2.2.5 Gerente de Codigo

O gerente de codigo gerencia as areas de codigo do sistema. Suas tarefas consistem

basicamente em:

1. Enviar a versao correta da unidade acionada para execucao, priorizando o envio do

codigo nativo mais atual (ou seja, mais especializado);

2. Enviar uma unidade para compilacao.

A interacao do gerente de codigo com os demais componentes, bem como o seu compor-

tamento com uma unidade de codigo e definido pelo estado atual da unidade em questao.

Em modo de execucao interpretacao mais compilacao, cada unidade do programa pode

assumir um dos seguintes estados: interpretado nao-frequente, interpretado frequente ou

nativo. No modo compilacao mais recompilacao, os estados de uma unidade sao: nativo

nao-frequente, nativo frequente ou nativo recompilado.

Page 31: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

28

Durante a execucao do programa, o gerente de codigo interage com o monitor para

identificar quais unidades sao frequentes. Desta forma, assim que uma determinada

unidade e detectada, o gerente de codigo a envia para o gerente de compilacao para

que este providencie uma nova versao da unidade. Apos o processo de especializacao (seja

ele compilar ou recompilar, dependendo da forma de implementacao do sistema JIT) de

uma unidade e papel do gerente fornecer ao motor de execucao a nova versao da unidade.

Normalmente, o gerente de codigo verifica a existencia de codigo especializado e

o envia para execucao, permanecendo nesse processo ate nao encontrar mais codigo

especializado para executar ou ate finalizar o programa. Adicionalmente, a execucao

de codigo especializado pode ser interrompida no caso de ocorrer alguma excecao. Nesse

caso, o gerente de codigo precisa restaurar o estado do sistema ate um ponto anterior ao

qual ocorreu a excecao e enviar ao motor de execucao uma versao nao especializada da

unidade.

2.2.6 Gerente de Compilacao

O gerente de compilacao e responsavel por criar um plano de (re)compilacao para o

(re)compilador otimizador utilizar durante a geracao de codigo. Basicamente, as in-

formacoes coletadas pelo offline e/ou online profilers sao inferidas para uma regiao quente

especıfica e enviadas ao gerente de compilacao para que este crie o plano de compilacao

adequado. Em geral, este plano define um conjunto de otimizacoes pre-determinado

pelo desenvolvedor do sistema, que e o mais adequado aquela regiao quente (Ishizaki et

al., 2003). Alem disto, tal plano pode definir um conjunto de otimizacoes mediante a

analise do proprio programa em execucao. Portanto, neste ultimo caso as otimizacoes

serao habilitadas durante a execucao do programa, bem como a ordem em que elas serao

aplicadas (Cavazos e O’Boyle, 2005; Hoste et al., 2010; Triantafyllis et al., 2003).

2.2.7 Repositorio de Codigo

O repositorio de codigo consiste de estruturas que armazenam versoes de codigo interpre-

tado e/ou compilado. Em sistemas que interpretam e compilam, o codigo interpretado e o

padrao na execucao. Este pode ser criado a partir de uma representacao de mais alto nıvel

e entao simplesmente carregado na inicializacao do sistema ou criado durante o tempo de

carregamento do programa. Por outro lado, sistemas que compilam e recompilam mantem

somente a area de codigo nativo.

A area de codigo nativo se expande na medida em que regioes quentes sao compiladas.

Nesse sentido, sistemas de compilacao JIT podem implementar polıticas para garantir que

Page 32: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

29

tal regiao nao cresca mais que um limite determinado, descartando codigo pouco invocado

e recompilando-o quando necessario, como acontece em Smalltalk (Deutsch e Schiffman,

1984).

Alem disso, sistemas que empregam online e/ou offline profiler podem construir

versoes de codigo especializadas para cada tipo de informacao coletada. Portanto, nestes

sistemas a prioridade de execucao e sempre do codigo especializado para o comportamento

ativo. Porem, e sempre importante manter uma versao generica para garantir estabilidade

caso o comportamento de uma regiao de codigo altere, por exemplo, caso uma variavel

mude de tipo. Outra consideracao importante e a construcao de um coletor de lixo (Aho

et al., 1986) associado a sistemas desse tipo. Visto que varias versoes de codigo nativo

induzem a uma expansao contınua da area de codigo nativo, e importante conter essa

expansao. Geralmente, isto consiste em eliminar codigo inutilizavel (nao executado por

um longo perıodo de tempo) ou invalido (especializado para uma informacao que nao e

equivalente ao comportamento atual do programa).

2.2.8 Motor de Execucao

O motor de execucao e o componente que executa as unidades de codigo, independente

do seu estado. Em sistemas que empregam interpretacao mais compilacao, o motor de

execucao e capaz de interpretar codigo como tambem invocar codigo nativo. Isto indica

que para esta forma de implementacao do sistema, o motor de execucao e um interpretador

que possui um mecanismo de invocacao de codigo nativo. Para sistemas que empregam

compilacao mais recompilacao, o motor de execucao e um modulo composto apenas de

um mecanismo de invocacao de codigo nativo.

2.3 Princıpios de Compilacao JIT

Visto que em sistemas JIT os compiladores compilam e otimizam codigo em tempo de

execucao e necessario que estes sejam rapidos, efetivos, leves e capazes de gerar codigo

nativo de alta qualidade. Entre essas necessidades, entretanto, existe um tradeoff entre

o tempo de compilacao e eficiencia do codigo gerado, que forma a base desses sistemas.

Em outras palavras, um compilador JIT deve ser sensıvel a eficiencia de tempo e espaco

dos seus algoritmos de otimizacao, pois uma compilacao lenta pode desacelerar o tempo

de resposta do programa. Alem disso, e preciso saber o que compilar, pois devido ao fato

da compilacao JIT ocorrer em tempo de execucao, nem todo trecho de codigo deve ser

Page 33: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

30

compilado. Na verdade, gerar codigo nativo para uma unidade especıfica, cuja execucao

nao compense o overhead de compilacao geralmente nao trara resultados satisfatorios.

Alem de ser importante conhecer quando compilar, o que compilar e como compilar, e

necessario considerar de forma precisa o mecanismo utilizado na manutencao dos sistemas

de compilacao e execucao, como tambem as questoes referentes aos atrasos que podem

ocorrer, pois se considerados de forma ingenua, podem ocasionar uma degradacao no

desempenho. Por essa razao, as seguintes questoes devem ser analisadas:

1. O atraso decorrente da espera da unidade de codigo para que se torne uma regiao

quente; e

2. O atraso decorrente da espera da regiao quente na fila de atendimento de compilacao.

Formas de tratar estes atrasos sao difıceis de projetar ou implementar, pois uma

configuracao negligente nas formas de deteccao de regioes quentes podem ocasionar um

alto overhead ao sistema como um todo. Pesquisadores tem tentado contornar o atraso

decorrente da unidade a espera para se tornar regiao quente, como e o caso dos trabalhos

de Krintz (2003), Namjoshi e Kulkarni (2010) e Campanoni et al. (2009), porem com o

custo de requerer execucao previa do sistema ou um processador adicional. Com respeito

ao atraso decorrente da espera na fila de compilacao, diversos trabalhos procuram utilizar

prioridades nas threads (Tanenbaum, 2007) do compilador (Arnold et al., 2000; Kulkarni,

2011; Kulkarni et al., 2007; Suganuma et al., 2004).

2.3.1 Manutencao dos Sistemas de Compilacao e Execucao

Plezbert e Cytron (1997) classificaram as possıveis abordagens para o gerenciamento entre

a compilacao e a execucao em um sistema JIT da seguinte maneira:

JIT Neste tipo de sistema, a unidade de codigo e compilada imediatamente antes de sua

execucao e uma unica thread e utilizada para alternar entre compilacao e execucao.

Isso significa que o motor de execucao e suspenso durante a atividade do compilador.

Como essa abordagem traduz codigo sob-demanda, ela evita que o sistema compile

inutilmente alguns trechos de codigo, devido ao fato de grandes programas possuirem

porcoes de codigo que as vezes nao sao executados. Um sistema que segue essa

abordagem e a JVM Kaffe (Wilkinson e Mehlitz, ????).

Smart JIT Apesar da vantagem inerente aos sistemas que utilizam a abordagem ante-

rior, esta pode acarretar perda de desempenho para uma situacao na qual o sistema

Page 34: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

31

compile todas as unidades de codigo invocadas. Como a maior parte do tempo de

execucao da maioria dos programas esta relacionado a execucao de uma pequena

faixa de codigo (Arnold et al., 2004; Bruening e Duesterwald, 2000), pode nao ser

viavel compilar faixas se elas nao forem executadas com frequencia. Em outras

palavras, uma compilacao eficiente deve saber escolher o que compilar. Smart JIT

emprega tecnicas que visam detectar unidades de codigo frequentes e entao, compilar

somente estas. Em tais sistemas tambem e utilizado somente uma thread, o que torna

obrigatorio suspender para compilacao a execucao de codigo. Sistemas smart JIT

sao: SELF-93 (Holzle, 1995; Holzle e Ungar, 1994), JUDO (Cierniak et al., 2000),

Jikes RVM (Arnold et al., 2000), YAPc (Silva e Costa, 2007), LuaJIT (Pall,

????) e HiPE (Pettersson et al., 2002).

Compilacao Contınua A compilac~ao contınua foi inicialmente apresentada como um

modelo teorico e tem sido empregada em alguns sistemas atuais (Arnold et al., 2000;

Paleczny et al., 2001; Suganuma et al., 2004), principalmente apos o surgimento (e

expansao) de arquiteturas multi-core. A explicacao para a implantacao de com-

pilacao contınua apos o surgimento dessas arquiteturas e que tal abordagem utiliza,

mais de uma thread : uma para execucao e as demais para compilacao. Embora,

ainda detecte regioes quentes, assim como smart JIT, a vantagem intrınseca e que

o ambiente nao precisa suspender a execucao para gerar codigo nativo. Entretanto,

o custo de implementacao e maior: as threads precisam ser gerenciadas, bem como

o acesso aos modulos/estruturas compartilhados(as), tais como o gerente de codigo

e a fila de regioes quentes escalonadas para compilacao (esta ultima se houver mais

de uma thread de compilacao).

2.3.2 Acionamento do Sistema de Compilacao

Basicamente, um sistema de compilacao JIT funciona da seguinte forma: em primeiro

lugar, ele instrumenta cada unidade de codigo com informacoes que medem a frequencia

de sua execucao. Em seguida, o programa e interpretado (Chang et al., 2009; Gal et al.,

2006; Kotzmann et al., 2008; Paleczny et al., 2001; Suganuma et al., 2004) ou compilado

com um compilador rapido (Arnold et al., 2000; Cierniak et al., 2000; Holzle e Ungar,

1994) e entao executado. Durante a execucao do programa, o sistema monitora as

unidades de codigo com o objetivo de detectar unidades quentes, isto e, unidades de

codigo mais frequentes. Este monitoramento e realizado verificando a informacao que

mede a frequencia de execucao de cada unidade. Desta forma, uma unidade de codigo

Page 35: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

32

e entao dita quente se sua informacao de frequencia atinge o limite pre-definido pelo

sistema.

Para deteccao das regioes quentes, sistemas JIT atuais empregam contadores (Chang

et al., 2009; Hansen, 1974; Holzle e Ungar, 1994; Kotzmann et al., 2008; Pall, ????;

Pettersson et al., 2002; Silva e Costa, 2007), amostras de tempo (Arnold et al., 2000)

ou uma combinacao entre contadores e amostras de tempo (Cierniak et al., 2000). O

uso de contadores requer que o sistema conte o numero de invocacoes de cada unidade,

enquanto a amostragem de tempo precisa interromper a execucao periodicamente para

atualizar o tempo da unidade. De qualquer forma, independente da abordagem utilizada,

a unidade e enviada para compilacao quando a respectiva metrica alcancar um limite

pre-definido.

A escolha de um limite correto e crucial para alcancar um bom desempenho de

execucao. Um limite muito baixo pode compilar codigo em demasia, o que aumenta o

overhead de compilacao e gera muito codigo nativo, que provavelmente nao proporcionara

ganhos de desempenho em execucoes posteriores (se ocorrer). Por outro lado, um limite

muito alto pode tornar o sistema muito conservativo que impede que regioes quentes ideais

sejam compiladas.

Uma base teorica para ajustar a metrica utilizada pelo compilador foi dada por Karp

(1992). Tal base afirma que o ideal e a unidade ser interpretada um numero de vezes

suficiente para compensar o overhead de compilacao. O trabalho de Plezbert e Cytron

(1997) explora outras metricas, a saber: crossover e balance. Crossover utiliza o tempo de

compilacao da unidade, juntamente com um parametro chamado ponto de crossover para

encontrar um limite ideal para a amostra de tempo. Enquanto isso, balance envia para

compilacao as unidades cujo tempo de interpretacao ultrapassa seu tempo de compilacao.

Tais abordagens, entretanto, sao difıceis de implementar porque na pratica, encontrar o

tempo de compilacao das unidades requer uma estimativa (que nao e precisa) ou uma

passagem adicional pelo programa (que pode nao ser desejavel em alguns casos).

No entanto, alguns trabalhos recentes tem buscado formas de enviar as unidades de

codigo o mais rapido possıvel para compilacao. O trabalho de Krintz (2003) explora

um mecanismo em tempo de compilacao para detectar previamente as regioes quentes,

enquanto que Namjoshi e Kulkarni (2010) propuseram uma tecnica de predicao utilizando

um processador adicional. Outra tecnica de predicao, implementada no trabalho de

Campanoni et al. (2009), procura dar enfase as unidades mais proximas da unidade

em execucao atual, julgando-as possuırem maior probabilidade de serem invocados fu-

turamente. Alem disso, as arquiteturas multi-core tem sido exploradas ultimamente

para manter threads especıficas somente para compilar ou executar codigo. Sistemas

Page 36: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

33

que utilizam esta abordagem sao: Sun HotSpot (Kotzmann et al., 2008; Paleczny et

al., 2001), Jikes RVM (Arnold et al., 2000) e ILDJIT (Campanoni et al., 2008, 2010).

2.3.3 Selecao de Unidades de Compilacao

Um fundamento importante relacionado as questoes abordadas por Hansen (1974), coube

a Holzle no seu trabalho com SELF-93 (Holzle, 1995; Holzle e Ungar, 1994). Holze

observou que o mecanismo de selecao das unidades que serao efetivamente compiladas (o

que compilar) e mais importante que o mecanismo para disparo de compilacao (quando

compilar). O mecanismo de selecao de unidades e uma forma de “previsao” de frequencia

de execucao das unidades de codigo, pois, como nao e possıvel identificar o numero de vezes

que uma unidade sera executada no futuro, e considerado que sua frequencia de execucao

a partir de um determinado ponto seja proporcional a sua frequencia de execucoes antes

deste ponto. Desde os primeiros trabalhos relacionados a compilacao JIT ate os mais

recentes, tres estrategias de selecao de unidades viaveis para compilacao foram propostas,

sao eles: (1) selecao baseada em sub-rotinas; (2) selecao baseada em regioes; e (3) selecao

baseada em tracos de execucao.

Selecao Baseada em Sub-rotinas

Compiladores JIT possuem, em muitos casos, uma estrutura similar a dos compiladores

estaticos e como os tais, herdam os mesmos fundamentos. Basicamente, um compilador

estatico constroi, para cada sub-rotina, um grafo de fluxo de controle e aplica uma serie

de otimizacoes sobre ele. A sub-rotina completa, bem como todas as demais alcancadas

a partir desta sao compiladas e otimizadas sem qualquer preocupacao quanto ao tempo,

pois neste caso, esse e um parametro irrelevante. Como mencionado, compiladores JIT

funcionam de forma similar, mas com a unica diferenca de que compilam as sub-rotinas sob

demanda, ou na primeira invocacao ou apenas aquelas que sao consideradas importantes

para o desempenho, sejam elas funcoes (Pall, ????; Pettersson et al., 2002), metodos

(Cierniak et al., 2000; Deutsch e Schiffman, 1984; Wilkinson e Mehlitz, ????) ou clausulas

(Silva e Costa, 2007).

No entanto, regioes quentes possuem trechos de codigo que sao pouco ou nunca

executados (Bruening e Duesterwald, 2000; Whaley, 2001), o que pode causar efeitos

adversos e reduzir a efetividade das otimizacoes (Suganuma et al., 2006). Um exemplo

tıpico e a aplicacao de inline que e muitas vezes restringida a sub-rotinas cujo tamanho

do codigo ultrapasse um limite pre-estabelecido, para evitar possıveis explosoes de codigo

(Serrano, 1997). Consequentemente, uma sub-rotina ja integrada, porem com muito

Page 37: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

34

codigo infrequente, pode impedir que sub-rotinas frequentes sejam tambem integradas

a sub-rotina principal na medida que inline se expande.

A escolha de sub-rotinas como a unidade basica de compilacao em sistema JIT e, de

fato, uma escolha conveniente (facil de manter), mas se for assumido o fato de que a

maioria das sub-rotinas sao compostas por porcoes de codigo nao frequentes, o ideal seria

detectar e eliminar estas porcoes, a fim de reduzir o esforco das otimizacoes e gerar um

codigo mais eficiente.

Selecao Baseada em Regioes

No contexto de compilacao JIT, esta tecnica procura por porcoes de codigo pouco frequen-

tes dentro de uma unidade e as eliminam do mecanismo de selecao. Portanto, as regioes

quentes sao os trechos de codigo frequentes dentro das unidades e nao necessariamente

uma sub-rotina.

Essa estrategia foi inicialmente baseada em informacoes coletadas estaticamente e

explorada por um framework de compilacao para um ambiente estatico (Hank et al., 1995).

Basicamente, estrategias para formacao de regioes sao dependentes da classe do sistema

que a implementa. Por outro lado, compiladores JIT nao sao beneficiados no todo por

informacoes coletadas estaticamente. Alem disso, utilizar apenas contadores ou amostras

de tempo pode ocasionar a exclusao de blocos quentes nao dominantes na formacao de

uma regiao. Um exemplo e um bloco if-then-else, no qual, tanto then quanto else sao

executados frequentemente. Neste caso, informacoes coletadas dinamicamente auxiliariam

na escolha de apenas um destes blocos (aquele com uma frequencia levemente superior)

para a formacao da regiao de compilacao. Se isso nao ocorrer, ha grandes chances de que

o bloco ignorado leve a degradacao o desempenho do sistema (Suganuma et al., 2006).

O trabalho de Suganuma et al. (2006) foi o primeiro a abordar a tecnica para deteccao

de regioes para compiladores JIT, em sistemas Java. A ideia basica e inicialmente

assumir que cada metodo seja representado como um grafo de fluxo de controle com

apenas uma entrada e uma saıda. Em seguida, os blocos basicos (que consistem nos

nos do grafo) sao marcados como frequentes ou nao frequentes com base em algumas

heurısticas. Normalmente, blocos que contem classes nao referenciadas, que terminam

com uma instrucao de excecao ou que manipulam excecoes sao considerados nao frequentes

e blocos que finalizam com instrucoes de retorno normais sao marcados como frequentes.

Adicionalmente, informacoes coletadas em tempo de execucao podem ajudar a detectar

blocos nunca executados, marcando-os tambem como nao frequentes. Finalmente, uma

passagem pelo grafo de fluxo analisa cada bloco basico, marcando-o como nao frequente

Page 38: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

35

na sua saıda somente se a entrada de todos os seus sucessores definirem este como nao

frequente. Desta forma, e definido como nao frequente todo bloco basico definido como

nao frequente na sua entrada e sua saıda. Tais blocos, enfim, podem ser desconsiderados

dentro do metodo e nao terao codigo final gerado.

Selecao Baseada em Tracos de Execucao

Sistemas baseados em selecao por tracos de execucao (Chang et al., 2009; Gal et al., 2009,

2006) procuram definir como regioes quentes os tracos de execucao frequentes que podem

ultrapassar os limites de uma sub-rotina. O primeiro trabalho a explorar os conceitos

desta tecnica foi um sistema para traducao binaria, chamado Dynamo (Bala et al., 2000).

Este sistema utiliza informacoes coletadas em tempo de execucao para detectar e otimizar

tracos quentes de execucao. Contudo, foi somente com o HotpathVM (Gal et al., 2006)

que essa tecnica foi utilizada em compilacao JIT.

Basicamente, a deteccao de tracos quentes de execucao funciona da seguinte maneira:

um contador e mantido no inıcio de cada backward branch (desvios cujo endereco alvo e

menor que o endereco da instrucao de desvio), que e incrementado toda vez que o desvio

e executado. Quando o valor de um contador de destino excede um limite, o traco de

execucao e gravado, compilado, armazenado em uma cache especıfica e invocado pelo

interpretador ou pelo ponto de saıda de outro traco de execucao compilado.

Dessa forma, as partes constituintes de um traco de execucao sao o inıcio dele (a

cabeca), que e uma instrucao ou unidade executada frequentemente, e um corpo que e

estendido ao longo do codigo, a partir da cabeca ate um ponto onde uma das seguintes

condicoes ocorrem:

• Um ciclo de instrucoes e detectado;

• O traco gravado excede um tamanho pre-definido;

• Uma instrucao incomum, como um manipulador de excecoes, e encontrada; ou

• Uma instrucao que forma a cabeca de um traco de execucao e encontrada.

Desde HotpathVM, muitos compiladores JIT baseados em selecao de tracos foram

implementados, dentre eles, TraceMonkey (Gal et al., 2009), LuaJIT (Pall, ????),

Tamarin-Trace (Chang et al., 2009) e HappyJIT (Homescu e Suhan, 2011).

Provavelmente a proxima tendencia na construcao de compiladores JIT utilizara

selecao por tracos de execucao para detectar regioes quentes mais eficientes. Hayashizaki

et al. (2011) demonstraram que a remocao de falsos lacos dos tracos detectados e uma

Page 39: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

36

boa estrategia para melhorar o desempenho, embora outro trabalho, atribuıdo a Inoue

et al. (2011), tenha demonstrado que detectar grandes tracos de execucao e escalona-los

para compilacao e tambem uma boa estrategia. Adicionalmente, a vantagem em manter

grandes tracos de execucao e que, quanto maior for, maior as oportunidades de otimizacao

(Zhao et al., 2008), que convergem em codigo mais eficiente.

2.3.4 Geracao de Versoes Especializadas

Com a ocorrencia de varias pesquisas, tecnicas que auxiliam compilacao JIT foram

criadas e aperfeicoadas, como drag-along (Abrams, 1970), comumente conhecida como

avaliacao tardia e codigo misto (Dakin e Poole, 1973) e ainda empregada em sistemas

que interpretam e compilam. No contexto de linguagens orientadas a objetos, SELF

(Chambers e Ungar, 1989, 1990; Chambers, 1992; Holzle, 1995; Holzle e Ungar, 1994)

inovou no desenvolvimento de otimizacoes mais agressivas, como a customizacao de codigo

que e utilizada para criar metodos especializados por tipo de dado e type feedback, que

extrai informacoes de tipos de execucoes previas para auxiliar no processo de compilacao.

O processo de otimizacao visa transformar unidades de codigo para torna-los mais

eficientes em termos de tempo, espaco e/ou consumo de energia. Diversas tecnicas que

integram esse processo sao especializadas para um conjunto de tarefas, como simplificar

expressoes constantes (Aho et al., 1986), eliminar expressoes comuns (Aho et al., 1977)

ou simplificar lacos dos programas (Bacon et al., 1994). A saıda da unidade otimizada

deve ser mantida e a unica diferenca notada pelo usuario final e o benefıcio gerado por

tais tecnicas, como a execucao rapida de codigo e reducoes do espaco ocupado e energia

consumida. No que se refere a compilacao JIT, e esperado que o processo de otimizacao

consuma pouco tempo de compilacao.

A aplicacao de tecnicas de otimizacao (Muchnick, 1997), em compiladores JIT em

particular, gera um tradeoff entre o tempo de compilacao e a eficiencia do codigo final. Em

compiladores estaticos, o overhead inerente pode ser ignorado, portanto tais tecnicas sao

aplicadas em tempo de compilacao. Como resultado, otimizacoes mais agressivas podem

ser aplicadas arbitrariamente. Por outro lado, ambientes de compilacao JIT precisam

ser criteriosos, uma vez que o tempo de compilacao (e otimizacao) integra o tempo total

de execucao. Por esta razao, uma decisao negligente pode resultar em uma degradacao

no desempenho do sistema como um todo. Nesse sentido diversos sistemas tem adotado

diferentes abordagens.

Adaptive Fortran (Hansen, 1974) escolhe e aplica tecnicas diferentes a cada in-

vocacao de uma unidade codigo. Por outro lado, os compiladores de SELF-93 (Holzle,

Page 40: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

37

1995; Holzle e Ungar, 1994), JUDO (Cierniak et al., 2000), SUN HotSpot (Kotzmann

et al., 2008; Paleczny et al., 2001) apostam em um conjunto de otimizacoes pre-definidas e

pre-ordenadas aplicadas uma unica vez por unidade de codigo. Embora, apenas SELF e

Sun HotSpot Client evitem otimizacoes mais agressivas. Jikes RVM (Arnold et al.,

2000; Burke et al., 1999) implementa um sistema de otimizacao adaptativa. Geralmente,

o sistema utiliza um calculo de custo-benefıcio para julgar o nıvel de otimizacao que uma

unidade prestes a ser compilada recebera. Outro sistema que implementa otimizacoes em

nıvel e a Maquina Virtual da IBM (Suganuma et al., 2004). Contudo, as otimizacoes

aplicadas em cada nıvel sao tecnicas atribuıdas manualmente pelos desenvolvedores e

consomem um tempo dispendioso para avaliacao. Nesse sentido, um trabalho recente,

realizado por Hoste et al. (2010), tem buscado aplicar busca evolucionaria para encontrar

planos de otimizacao que regulam o tradeoff existente entre o tempo de compilacao e a

eficiencia do codigo.

Em geral, as otimizacoes aplicadas pelo sistema de compilacao JIT utilizam analises de

fluxo de dados que precisam encontrar os usos de cada definicao de variavel ou a definicao

de cada uso em cada expressao. O canal def-uso e uma estrutura de dados que torna este

acesso mais eficiente: para cada declaracao no grafo de fluxo, o compilador mantem uma

lista de ponteiros para todos os usos da variavel definida nesta declaracao, e para cada

instrucao uma lista de ponteiros para todas as definicoes das variaveis usadas nela. Desta

maneira, o compilador pode rapidamente saltar da definicao para o uso ou vice-versa.

Uma melhoria nesta ideia e o uso da representacao Static Single-Assignment (SSA)

(Brandis e Mossenbock, 1994; Sreedhar et al., 1999), uma representacao intermediaria

na qual cada variavel possui apenas uma definicao no programa. A unica (estatica)

definicao pode estar em um laco que e executado diversas (dinamicas) vezes, logo o nome

representacao static single-assignment ao inves de representacao single assignment (onde

variaveis nunca sao redefinidas). A representacao SSA e popular em sistemas JIT por

diversas razoes:

1. Analises de fluxo de dados e algoritmos de otimizacao podem ser implementados de

maneira simples quando cada variavel possui apenas uma definicao.

2. Se a variavel possui N usos e M definicoes, o espaco necessario para representar as

estruturas def-uso e proporcional a N ×M . Para a maioria dos programas reais, o

tamanho da representacao SSA e linear no tamanho do programa original.

3. Usos e definicoes das variaveis na representacao SSA simplificam algoritmos como

construcao de um grafo de interferencia, que e utilizado por alocadores de registrado-

Page 41: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

38

res baseados em coloracao de grafo, como o empregado pelo sistema Sun HotSpot

Server.

4. Usos nao relacionados da mesma variavel em um programa tornam-se diferentes

variaveis na representacao SSA, eliminando relacionamentos desnecessarios.

A escolha por esta representacao esta baseada nas razoes descritas acima. Contudo,

entender o comportamento do programa e crucial para obter um bom desempenho.

Embora o uso de uma representacao SSA torne os algoritmos de otimizacoes mais leves

e simples, ela possui o problema de aumentar o tamanho do codigo gerado e a pressao

por registradores. O tamanho do codigo aumenta devido ao uso de uma unica definicao

para cada variavel, acarretando o aumento dos acessos a memoria. Consequentemente,

o aumento da quantidade de variaveis aumenta a pressao por registradores. Em uma

arquitetura com poucos registradores isto pode acarretar uma quantidade expressiva de

spills, isto e, uma expressiva representacao de variaveis na memoria, ocorrida pela falta

de registradores.

Alem do uso de uma representacao SSA, sistemas modernos utilizam diferentes

profilers para tambem auxiliar o processo de geracao de versoes especializadas. Profilers

(Krintz, 2003; Namjoshi e Kulkarni, 2010) sao projetados para coletar informacoes sobre os

programas, como tipos de dados, modos de execucao e backward branches, estaticamente

e/ou dinamicamente. Type feedback profiler foi implementado pela primeira vez no

compilador SELF-93 (Holzle, 1995; Holzle e Ungar, 1994) de modo a extrair informacoes

de tipo de execucoes previas e retorna-las ao compilador. Este retorno poderia acontecer

dinamicamente ou estaticamente. Para tal, o sistema instrumentava o codigo para gravar

os tipos coletados e propaga-los ao sistema de compilacao na medida em que a execucao

prosseguia. Dessa forma, baseado nas informacoes coletadas, o compilador poderia prever

provaveis classes receptoras (no contexto de SELF), ou tipos de dados (em um contexto

geral) e gerar codigo mais eficiente. Em uma situacao onde type feedback indicar que uma

determinada variavel sempre assumira um valor inteiro, o compilador podera gerar codigo

especializado para esta situacao.

Alem das questoes ja abordadas, um fato que deve ser observado no desenvolvimento

de sistemas de compilacao JIT e o fato de algumas otimizacoes altamente efetivas serem

complicadas por causa da flexibilidade de determinadas linguagens de programacao. No

contexto de Java, por exemplo, metodos virtuais limitam a aplicacao de inline. Aplicar

esta tecnica e difıcil para metodos virtuais porque nao se sabe estaticamente que metodo

sera invocado.

Page 42: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

39

Remover o codigo compilado resulta em um retorno ao interpretador. Uma solucao

para este caso e substituir o codigo compilado pelo interpretado. Esta situacao mostra

uma vantagem de ter simultaneamente codigo compilado e interpretado. A transicao entre

codigo compilado e interpretado e chamada de desotimizacao. Para tal, o compilador deve

gerar uma estrutura de dados que permita a reconstrucao do estado do interpretador ate

o ponto de chamada do codigo compilado.

Desotimizacao e fundamental para que o compilador possa realizar otimizacoes agres-

sivas que aceleram a execucao normal enquanto seja capaz de gerenciar situacoes onde

uma determinada otimizacao deva ser desfeita. Existem casos crıticos onde o metodo

compilado e desotimizado, por exemplo, quando ocorrem excecoes. Com desotimizacao,

o codigo compilado nao precisa gerenciar tais situacoes, que em geral sao casos incomuns.

Sistemas que utilizam este recurso sao SELF (Chambers e Ungar, 1989, 1990; Chambers,

1992; Holzle, 1995; Holzle e Ungar, 1994), Sun HotSpot Client (Kotzmann et al.,

2008) e Sun HotSpot Server (Paleczny et al., 2001).

2.3.5 Implementacao e Desempenho

Uma questao importante no tocante a implementacao de um sistema JIT e a escolha

adequada dos princıpios que nortearao tal implementacao. As escolhas de projeto devem

balancear o tradeoff existente entre tempo de compilacao e a eficiencia do codigo gerado.

De fato, implementacao e desempenho sao duas questoes que estao relacionadas. Portanto,

o projeto de um sistema deste porte deve considerar as seguintes questoes:

Modo de implementacao A escolha entre um sistema misto ou um com compilacao

e recompilacao possui vantagens e desvantagens. Sistemas que utilizam um

interpretador proveem um ambiente portavel, seguro e de facil implementacao, mas

incorrem no overhead de interpretacao. Por outro lado, embora o overhead nao

ocorra em sistemas que utilizam apenas compilacao, estes sao mais complexos para

manter. Alem disso, a tendencia e que sistemas que utilizam apenas compilacao

tenham um desempenho superior aqueles que ainda interpretam codigo (isto em

relacao a sistemas que utilizam as mesmas abordagens para implementar/solucionar

as demais questoes), pelo fato, do tempo gasto em interpretacao ser geralmente uma

ordem de grandeza maior que a execucao de codigo compilado.

Sistemas de Compilacao e Execucao A abordagem ideal utilizada no mecanismo

de compilacao e execucao deve aproveitar ao maximo a capacidade das arquiteturas

de hardware atuais. Com a limitacao no aumento gradual do clock do processador

Page 43: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

40

(Patterson e Hennessy, 2005), as arquiteturas modernas tem investido em maquinas

multi-core. Tais maquinas proveem diversos nucleos de processamento, que sao

utilizados para executar diversas tarefas simultaneamente, sendo, portanto, ideais

para serem exploradas em um sistema de compilac~ao contınua. De fato, a

abordagem JIT incorre em pelo menos dois problemas. Primeiro, ela nao utiliza

a deteccao de regioes quentes e consequentemente pode incorrer em overhead de

compilacao de unidades que nao amortizaram o tempo gasto pelo compilador.

Segundo, ela nao utiliza informacoes coletadas em tempo de execucao e, como cada

unidade e compilada imediatamente antes de sua invocacao, nao existe no sistema

informacoes sobre a unidade, ja que esta nao foi ainda executada. Porem, e possıvel

que tal abordagem seja beneficiada pelo uso de um offline profiler. A abordagem

smart JIT possui o atrativo de minimizar o overhead de compilacao, gerando codigo

especializado apenas para regioes quentes. Contudo, incorre no problema de parar o

motor de execucao para que o sistema de compilacao seja acionado. A compilac~ao

contınua, alem de possuir o atrativo de minimizar os problemas inerentes as outras

duas abordagens, possui o potencial de explorar as arquiteturas modernas. Isto

decorre no uso de pelo menos duas threads, uma para o motor de execucao e outra

para o sistema de compilacao.

Acionamento do Sistema de Compilacao O uso de contadores para acionar o sis-

tema de compilacao possui o atrativo de ser uma abordagem simples de imple-

mentar, em comparacao com a abordagem de utilizar amostragem de tempo.

Balance necessita da implementacao de um mecanismo de monitoramento de tempo

de execucao e crossover necessita que o programa seja compilado previamente.

Abordagens que utilizam amostragem de tempo nao sao adequadas para sistemas

interativos. Mas possuem potencial para sistemas servidores, nos quais nao existe a

interacao direta com o usuario e geralmente as aplicacoes possuem um longo tempo

de execucao. E importante ressaltar, que embora com o uso de crossover exista

a necessidade de compilar previamente o programa, a estimativa correta do limite

maximo do contador requer informacoes empıricas, situacao que tambem requer

execucoes previas da aplicacao. De fato, uma boa estimativa ira requerer diversos

experimentos, por outro lado crossover requer apenas uma unica execucao. Nesta

questao, o trabalho de Suganuma et al. (2005) demonstrou que o uso de contadores

pode ser mais eficiente do que o uso de amostras de tempo. Portanto, embora a

estimativa do limite do contador seja uma tarefa dispendiosa, esta pode proporcionar

um bom desempenho ao sistema.

Page 44: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

41

Selecao de Unidades de Compilacao A escolha de sub-rotinas como unidades de

compilacao possui o atrativo de ser uma abordagem natural. Contudo, o fluxo de

execucao de um determinado programa pode se concentrar apenas em uma porcao de

codigo contida em uma sub-rotina. O uso de regioes possui o atrativo de eliminar

porcoes de codigo que nao sao executados frequentemente e o uso de tracos de

execucao, alem de possuir este atrativo, possui o potencial de integrar em uma unica

porcao compilada diversas unidades de codigo. Esta integracao possui a tendencia

de minimizar o custo do chaveamento entre diversas versoes de codigo, como tambem

de aumentar o escopo de aplicacao de otimizacoes, possibilitando assim, o aumento

no ganho de desempenho do sistema. Por outro lado, tracos de execucao requer um

esforco maior de implementacao do que as outras duas abordagens, o que pode ser

evidenciado pelo fato desta estrategia requerer algoritmos mais elaborados para sua

implementacao.

Geracao de Versoes Especializadas Esta tarefa e uma necessidade em sistemas JIT,

devido ao fato de estas terem por objetivo aumentar o desempenho de ambientes

projetados para executar programas. Independente do modo de implementacao do

sistema, o projetista deve prover um mecanismo que seja capaz de especializar o

codigo que esta sendo gerado durante a execucao do programa, em outras palavras

o projetista deve implementar um mecanismo que aplique otimizacoes ao codigo

compilado. Uma abordagem conservativa, embora simples do ponto de vista da

implementacao, possui a tendencia de nao prover um codigo com uma alta eficiencia,

embora a geracao de codigo de alta qualidade seja um problema complexo de

ser resolvido. O ideal e que o sistema se adapte as caracterısticas do programa

em execucao e, desta forma, escolha dinamicamente quais otimizacoes aplicar.

Ainda nesta questao, e papel do desenvolvedor do sistema escolher quais algoritmos

utilizar para implementar cada otimizacao, o que e essencial pelo fato de existirem

algoritmos que sao mais eficientes em situacoes mais especıficas, pois a eficiencia

de um algoritmo de otimizacao esta relacionada ao contexto de sua aplicacao como

tambem a representacao interna utilizada para o codigo do programa.

2.4 Sistemas

Mesmo que os primeiros sistemas de compilacao JIT tenham surgido a partir de 1960, com

LISP, somente uma decada apos, com o trabalho de Hansen, e que os desafios a serem

enfrentados por tais sistemas foram formalizados (Hansen, 1974). Desde entao, sistemas de

Page 45: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

42

compilacao JIT tem incorporado diversos princıpios que diversificaram decisoes de projeto,

arquitetura e tecnicas. Tais decisoes sao destacadas na apresentacao dos sistemas a seguir.

Adaptive Fortran foi projetado para suportar execucao de codigo em modo misto

(Hansen, 1974). Todos as unidades de codigo do programa sao instrumentadas

com contadores, que sao atualizados a cada chamada da unidade. Dessa forma,

uma unidade se torna um candidato para a “proxima otimizacao” caso seu contador

ultrapasse o limite de frequencia pre-estabelecido. Durante esse passo, um codigo

supervisor e invocado entre as unidades de codigo, que acessa os contadores e aplica

otimizacoes (se necessario). Por fim, o sistema transfere o controle de execucao para

a proxima unidade, dando preferencia na execucao da versao nativa dessa unidade,

se existir. As unidades de codigo escalonadas para compilacao sao otimizados por

uma tecnica de otimizacao por vez e recompilados com uma tecnica de otimizacao

diferente caso se tornem regioes crıticas novamente. Esta estrategia mostrou ser

uma esquema de (re)compilacao primitivo, que foi mais tarde aprimorado por outros

sistemas (Arnold et al., 2000; Cierniak et al., 2000; Holzle e Ungar, 1994; Suganuma

et al., 2004).

Sistema de Smalltalk-80 traduz codigo da Maquina Virtual Smalltalk (Gold-

berg e Robson, 1983) para codigo nativo no momento em que um metodo e invocado

(Deutsch e Schiffman, 1984). Apos esse processo, o codigo gerado e armazenado

em uma cache para execucoes posteriores. O sistema projetado e vinculado a um

gerenciamento de memoria, que impede a paginacao de codigo nativo caso a cache

ultrapasse um limite de armazenamento. Se por algum momento esse limite for

alcancado, o codigo nativo e simplesmente descartado e novamente gerado, caso

necessario.

SELF possui um ambiente de execucao que implementa o mecanismo de compilacao mais

recompilacao (Holzle, 1995; Holzle e Ungar, 1994). Basicamente, um compilador

rapido nao otimizador compila as unidades de codigo que estao prestes a serem exe-

cutadas e, utilizando contadores, o sistema identifica os metodos crıticos e compila-os

com um compilador otimizador. Este ultimo emprega compilacao baseada em regiao,

porem diferente daquela apresentado por Suganuma et al. (Suganuma et al., 2006).

Para tal, um sistema de predicao de tipos e utilizado para detectar e remover codigo

das mensagens enviadas as classes pouco comuns, o que significa que apenas codigo

de mensagens enviadas as classes frequentes sao compilados.

Page 46: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

43

Kaffe pode executar codigo tanto em forma interpretada quanto compilada (Wilkinson e

Mehlitz, ????). No modo de compilacao,Kaffe compila todos metodos no momento

de sua invocacao e nao executa codigo misto. Isso significa que o sistema se enquadra

no modelo JIT, segundo a visao de Plezbert e Cytron (Plezbert e Cytron, 1997). O

compilador JIT incorporado converte os bytecodes de entrada em uma representacao

intermediaria chamada KaffeIR, que e mapeada para codigo nativo do hardware

utilizado, por meio de um conjunto de macros pre-definidas.

Jikes RVM emprega a estrategia de compilacao mais recompilacao (Arnold et al.,

2000; Burke et al., 1999). Ele compila todos os metodos na medida em que sao

invocados por um compilador base nao otimizador e recompila as regioes crıticas

com um compilador otimizador (Burke et al., 1999), que emprega varias otimizacoes

separadas em tres nıveis. O primeiro consiste de um conjunto de otimizacoes

aplicadas durante a traducao dos bytecodes para uma representacao intermediaria

utilizada pelo compilador. O segundo nıvel aplica todas as otimizacoes do primeiro

nıvel, em adicao com inline e outras otimizacoes locais. Por fim, o nıvel mais

agressivo emprega todas as otimizacoes do nıvel anterior, em adicao com otimizacoes

baseadas na representacao SSA para variaveis escalares (Cytron et al., 1991).

Basicamente, Jikes RVM detecta regioes crıticas empregando amostras de tempo.

As regioes crıticas sao, portanto, encaminhadas para uma fila e julgadas propıcias

para (re)compilacao (em nıveis maiores de otimizacao) ou nao, baseado em uma

analise de custo-benefıcio realizada pelo sistema. Dessa forma, se parecer rentavel,

a regiao crıtica e (re)otimizada de acordo com o nıvel de otimizacao avaliado por uma

thread especıfica, de modo a evitar pausas na execucao e se beneficiar de paralelismo.

JUDO (Java Under Dynamic Optimization) compila todo o codigo por um gerador

rapido de codigo e instrumenta-o de modo que o sistema possa coletar informacoes

em tempo de execucao (Cierniak et al., 2000). Por fim, as regioes crıticas detec-

tadas sao escalonadas para compilacao por um compilador otimizador, que aplica

otimizacoes agressivas. Tais regioes sao detectadas de duas formas possıveis: (1)

utilizando contadores, ou (2) utilizando tempo. Na primeira abordagem, cada

metodo e instrumentado com um contador fixado com um valor limite. No momento

em que o metodo e chamado, seu contador e decrementado e, chegando a zero, o

metodo e imediatamente enviado para compilacao. Ja, na segunda abordagem uma

thread separada e invocada em determinados intervalos de tempo para verificar o

valor-limiar (medido em segundos) de todos os metodos (seu tempo de execucao)

e enviar para compilacao aqueles que se tornaram regioes crıticas. Com o uso de

Page 47: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

44

contadores, o metodo e enviado para compilacao imediatamente apos o contador

vinculado atingir o valor zero, contadores que sao decrementados antes da execucao

do metodo. Por outro lado, com o uso de tempo, se o sistema identificar que um

metodo atingiu um limiar de execucao, este so sera enviado para compilacao na sua

proxima chamada.

HiPE e um compilador JIT para a linguagem Erlang baseado em compilacao de sub-rotinas

(Pettersson et al., 2002). Este compilador ainda inclui extensoes para que o sistema

suporte execucao em modo misto de codigo. Todas as sub-rotinas sao interpretadas

pela maquina virtual no inıcio da execucao e somente aquelas frequentemente

executadas sao compiladas. Medidas utilizadas para verificar a frequencia de

chamada de sub-rotinas incluem contadores e tempo.

Maquina Virtual da IBM gera codigo nativo somente para os metodos crıticos e

interpreta os demais (Suganuma et al., 2004). A contagem de frequencia se baseia no

uso de contadores, que sao incrementados a cada chamada ao metodo. Unidades de

codigo que representam lacos frequentes tambem sao considerados para compilacao.

Tal como em Jikes RVM, o sistema implementa compilacao em multi-nıvel, cuja

configuracao foi baseada em medidas empıricas de custo versus benefıcio obtidas

do trabalho de Ishizaki et al (Ishizaki et al., 2003). Tres nıveis de otimizacao

sao aplicados: o primeiro nıvel aplica um conjunto muito reduzido de otimizacoes,

proprio para minimizar o overhead de compilacao, enquanto os demais aplicam todas

as otimizacoes disponıveis no compilador repetidas vezes, porem em quantidade

limitada no nıvel intermediario. Na medida em que um metodo e compilado,

este e monitorado periodicamente pelo sistema. Dependendo do valor do contador

encontrado (a frequencia), o metodo e promovido com otimizacoes de nıvel 2 ou 3.

No nıvel 1, a compilacao e regida pela propria thread de aplicacao (configuracao

Smart JIT ), porem os nıveis 2 e 3, empregam threads separadas para compilacao

em segundo plano (compilacao contınua).

HotPathVM e um compilador JIT baseado em caminhos de execucao projetado para a

maquina virtual JamVM (Gal et al., 2006; Lougher, ????), propria para dispositivos

embarcados. O sistema primeiramente interpreta os bytecodes Java construindo os

caminhos para os trechos de codigo executados em maior frequencia e, em seguida,

gera codigo nativo para estes. Infelizmente, informacoes relacionadas a forma de

deteccao de regioes crıticas nao sao fornecidas. Segundo os autores, HotpathVM

Page 48: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

45

utiliza apenas 150 KB de memoria, incluindo codigo e dados, e consegue gerar codigo

compatıvel aqueles gerados por outros compiladores JIT de grande porte.

YAP com compilacao JIT foi projetado para melhorar o desempenho de linguagens

logicas (Silva e Costa, 2007). Inicialmente todas as clausulas sao instrumentadas

com contadores e interpretadas. Cada invocacao, contudo, incremeta o contador

em uma unidade. Dessa forma, uma clausula se torna uma regiao crıtica caso seu

contador atinja um limite pre-estabelecido, embora somente as clausulas com um

tamanho mınimo sejam escalonadas para compilacao. Esta ultima restricao e para

evitar que o compilador gaste tempo compilando uma unidade que possivelmente nao

trara benefıcio na execucao. O sistema em si aplica poucas otimizacoes de codigo

se comparado a outros sistemas JIT existentes, mas consegue acelerar de forma

significativa a execucao de Prolog frente a sua contraparte puramente interpretada.

Sun HotSpot inicialmente interpreta todos os metodos e vincula a estes contadores

que medem a frequencia de execucao. Portanto, cada metodo e escalonado para

compilacao quando o seu contador atinge um limite. Adicionalmente, metodos

com alto tempo de execucao tambem podem ser compilados, mesmo se invocados

poucas vezes. O ambiente de execucao compartilha dois compiladores: o compilador

cliente (Kotzmann et al., 2008) e o compilador servidor (Paleczny et al., 2001), que

podem ser escolhidos manualmente a cada execucao. O compilador Sun HotSpot

Client (Kotzmann et al., 2008) e indicado para programas interativos, cujo tempo

de resposta e mais importante que o desempenho, sendo entao projetado para

alcancar um tradeoff entre a velocidade de execucao e o desempenho do codigo

final gerado. A compilacao e realizada em diversas etapas, que transformam o

codigo gradualmente ate gerar o codigo final da plataforma alvo. O compilador

Sun HotSpot Server (Paleczny et al., 2001) e indicado para programas de longa

duracao, cujo tempo de execucao de codigo nativo compense o tempo de compilacao

gasto. Este compilador, se comparado ao cliente, e mais agressivo nas otimizacoes

e algumas delas sao guiadas por analise global. Alem disso, o compilador servidor

e capaz de detectar metodos virtuais pouco comuns e referencias para classes nao

inicializadas para evitar gerar codigo para essas partes. Na visao de Plezbert e

Cytron (Plezbert e Cytron, 1997), Sun HotSpot Server e classificado como um

sistema de compilacao contınua, pois pode se beneficiar de compilacao em segundo

plano, caso o hardware possua multiplos processadores.

Page 49: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

46

Tamarin-Trace e um compilador para JavaScript baseado em compilacao por selecao

de caminhos de execucao (Chang et al., 2009). Cada backward branch do programa

possui, vinculado ao seu destino, um contador que mede a frequencia de execucao.

A partir disso, considerando que a maior parte do destino do desvio e um loop

header, o interpretador nao somente interpreta o codigo, como tambem constroi

o caminho de execucao a partir dele. Quando a gravacao do caminho alcanca

novamente o loop header, o processo e finalizado e o caminho e transformado para

uma representacao intermediaria de baixo nıvel que, por sua vez, e traduzido para

codigo de maquina. Como no momento da gravacao do caminho, os tipos das

variaveis sao conhecidos, o compilador pode realizar especializacao de codigo para

cada tipo detectado. Adicionalmente, decisoes em tempo de execucao, como desvios

condicionais, sao marcados para que a execucao retorne ao modo interpretado caso

um fluxo de controle ainda nao compilado seja encontrado. Se isso ocorrer, o novo

caminho e gravado e acoplado ao caminho anterior, formando assim, uma arvore de

caminhos de execucao, que e entao tratada com qualquer caminho gravado.

TraceMonkey e um compilador JIT para JavaScript baseada em compilacao por

caminhos de execucao, que segue o modelo de interpretacao e compilacao (Gal et

al., 2009). Os pontos crıticos do programa sao detectados a partir de contadores e

consistem de arestas de retorno dos lacos. Quando um destes pontos e detectado, o

interpretador entra em um modo especial para gravar o caminho de execucao a partir

dele, enquanto ainda interpreta codigo. A gravacao do caminho e finalizado quando

o ponto inicial da gravacao e encontrado. Apos a geracao do codigo nativo, o sistema

mantem a execucao do codigo gerado ate que a avaliacao de tipos retorne um tipo

diferente, ou ate que um caminho nao-compilado seja tomado. Em qualquer destes

casos, o sistema retorna ao modo interpretado e reinicia a construcao do caminho

de execucao.

LuaJIT implementa compilacao baseada em caminhos de execucao (Pall, ????). Primei-

ramente, o sistema interpreta codigo e mantem estatısticas de execucao dos lacos e

chamadas de funcoes, que por sua vez, e medida com contadores. Quando um limite

e alcancado, a unidade de codigo (funcao ou laco) e considerada crıtica e, a partir

dela, o caminho de execucao e construıdo. A interpretacao permanece ate que o

caminho seja definitivamente construıdo. As condicoes para o termino de construcao

do caminho e um pouco diferente do apresentado no decorrer do texto. Basicamente,

LuaJIT finaliza um caminho de execucao apos: (1) uma instrucao nao-tratavel,

como uma excecao, for encontrada ou quando (2) o inıcio do caminho em construcao

Page 50: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

47

for encontrado. No primeiro caso, o caminho e descartado e no segundo, e enviado

para compilacao. Apos a compilacao, o sistema prioriza a execucao da versao nativa,

como em todo o sistema baseado em codigo misto. Durante este passo, decisoes

tomadas em tempo de execucao, como desvios condicionais e checagem de tipos,

podem causar a saıda do caminho de execucao. Isso pode ocorrer caso um caminho

diferente do fluxo de controle (ainda nao compilado) for tomado ou quando uma

checagem de tipos falha. Em qualquer destes casos, o sistema retorna a execucao

ao modo interpretado e reinicia o processo de contrucao do caminho.

ILDJIT e um sistema de compilacao JIT que utiliza a polıtica de interpretacao mais

compila-cao (Campanoni et al., 2008, 2010). A ideia desse sistema e se beneficiar

do paralelismo oferecido pelas maquinas multi-core atuais. A regiao crıtica basica

de ILDJIT e flexıvel, embora um metodo seja a unidade de compilacao mınima. A

deteccao de tais regioes e garantida pela polıtica ahead-of-time, utilizando a tecnica

look ahead compilation (Campanoni et al., 2009). Com essa tecnica, o sistema

verifica a constituicao do programa a partir do metodo atualmente em execucao

e seleciona os metodos mais proximos a este, enviando-os para compilacao mais

cedo. Isso e baseado em uma heurıstica, que espera que tais metodos possuam

maiores chances de serem invocados mais recentemente que outros. O sistema

ainda explora automaticamente as configuracoes da maquina adjacente e dispara

threads de compilacao conforme a maquina oferece. O paralelismo entre execucao e

compilacao e garantido pelo proprio sistema.

HappyJIT e um compilador JIT (Homescu e Suhan, 2011) para PHP desenvolvido a partir

de PyPy (Rigo e Pedroni, 2006), um framework para construcao de maquinas

virtuais que e composto por dois componentes: (1) um interpretador Python

(Lutz e Ascher, 2007) escrito em um subconjunto restrito da linguagem, chamada

RPython (Ancona et al., 2007) e (2) um tradutor, que gera codigo nativo para

o primeiro componente. O objetivo dos autores com essa estrategia e facilitar

a implementacao de linguagens dinamicas, de modo que o projetista se preocupe

apenas em escrever o interpretador para sua linguagem em RPython. Os detalhes

de baixo nıvel e a geracao de codigo fica a cargo do proprio framework. A

fim de facilitar o esforco de implementacao, HappyJIT reutiliza o parser do

motor Zend (Zend, ????), que converte codigo PHP internamente para um bytecode

linear. Esse bytecode e recuperado e traduzido para a representacao suportada pelo

interpretador construıdo. Dessa forma, somente as estruturas de dados necessarias

para representar os tipos de dados de PHP em memoria e este interpretador foram

Page 51: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

48

implementados. Por fim, o interpretador construıdo e passado como entrada para

PyPy. Isso significa que, durante a execucao ha dois interpretadores envolvidos: o

projetado para interpretar o programa PHP do usuario e o utilizado para interpretar

este interpretador. Essa forma de execucao so nao possui um alto overhead por

causa do compilador JIT acoplado ao segundo interpretador (Bolz et al., 2009).

Este compilador gera codigo para caminhos de execucao frequentes e consegue gerar

bons resultados, segundo os proprios autores.

Os princıpios de compilacao JIT descritos na Secao 2.3 podem ser utilizados para

classificar os sistemas que empregam este tipo de compilacao. Desta forma, os sistemas

descritos no presente capıtulo sao classificados da seguinte forma:

• Tipo do sistema que pode ser: interpretacao mais compilacao, compilacao mais

recompilacao ou ainda uma variacao deste ultimo, na qual cada unidade de codigo

e compilada imediatamente antes de sua primeira invocacao, sem ser recompilada.

• Manutencao do sistema, podendo ser: JIT, smart JIT, ou compilacao contınua.

• Forma de deteccao das regioes crıticas que pode ser por meio de contadores ou

fracao de tempo. E importante ressaltar que em implementacoes cuja manutencao

do sistema utiliza a abordagem JIT nao existe um mecanismo de deteccao de regioes

crıticas, pelo fato de cada unidade de codigo invocada ser compilada antes de sua

invocacao. Portanto, em tais sistemas nao existe uma forma de deteccao de regioes

crıticas.

• Estrutura das regioes crıticas podendo ser: sub-rotina, regiao ou caminho de

execucao.

• Polıtica de aplicacao de otimizacoes de codigo que indica se o processo de

compilacao emprega ou nao otimizacoes com o objetivo de gerar um codigo de

qualidade. As possıveis polıticas sao: ingenua (poucas otimizacoes sao aplicadas),

agressiva (diversas otimizacoes sao aplicadas), ou nıveis (o sistema alterna durante

a execucao o nıvel de otimizacao que sera aplicado).

A Tabela - 2.1 apresenta uma comparacao entre os sistemas apresentados nesta secao.

Nesta tabela, a primeira coluna apresenta o nome do sistema, a segunda o seu tipo,

a terceira a forma utilizada na manutencao, a quarta a forma de deteccao de regioes

crıticas, a quinta a estrutura das regioes crıticas e por fim, a ultima coluna apresenta a

polıtica utilizada na aplicacao de otimizacoes de codigo. As siglas nesta tabela significam:

Page 52: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

49

(IC) interpretacao mais compilacao; (CR) compilacao mais recompilacao; (C) compilacao

- para aqueles sistemas que compilam na primeira invocacao sem recompilar; (CC)

compilacao contınua; (NE) nao existente; (INF) informacao nao fornecida.

Estrutura

SistemaTipo de Formas de Forma de

das RegioesPolıtica de

Sistema Manutencao DeteccaoCrıticas

Otimizacoes

AdaptiveFortran

IC Smart JIT Contadores Sub-rotina Ingenua

Sistema deSmalltalk-80

CR JIT NE Sub-rotina INF

SELF CR Smart JIT Contadores Regiao IngenuaKaffe C JIT NE Sub-rotina INF

Jikes RVM CR CC Tempo Sub-rotina NıveisContadores

JUDO CR Smart JITTempo

Sub-rotina Agressiva

ContadoresHiPE IC Smart JIT

TempoSub-rotina INF

Maquina Smart JITVirtual IBM

ICCC

Contadores Sub-rotina Nıveis

HotPathVM IC Smart JIT INF Caminho INFYAP com JIT IC Smart JIT Contadores Sub-rotina IngenuaSun Hotspot Contadores

ClientIC Smart JIT

TempoSub-rotina Ingenua

Sun Hotspot ContadoresServer

IC CCTempo

Sub-rotina Agressiva

Tamarin-Trace IC Smart JIT Contadores Caminho AgressivaTraceMonkey IC Smart JIT Contadores Caminho INF

LuaJIT IC Smart JIT Contadores Caminho IngenuaILDJIT IC Smart JIT INF Sub-rotina INF

HappyJIT IC Smart JIT Contadores Caminho INF

Tabela 2.1: Comparacao entre os sistemas JIT.

Em sıntese, a maioria dos sistemas apostam na estrategia de interpretar e compilar

codigo. Provavelmente, a pouca quantidade de sistemas que compilam e recompilam se

deve pelo trabalho de implementar um compilador-base que, apesar de simples, e ainda

mais complexo que um interpretador. Outro ponto importante e referente as estrategias

de otimizacao de codigo, que mostram ser pouco investigadas no campo de compilacao

JIT. Por outro lado, mecanismos para detectar regioes crıticas tem se mostrado mais

importantes. De fato, diversos sistema tem procurado alcancar desempenho por meio da

Page 53: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

50

deteccao e geracao de codigo para porcoes de codigo que nao se limitam ao escopo de uma

sub-rotina.

2.5 Consideracoes Finais

Uma caracterıstica diferencial de compiladores JIT frente ao compiladores tradicionais

e que a geracao de codigo nativo ocorre em tempo de execucao. Mesmo que isso seja

preocupante no quesito de desempenho, sistemas que empregam compiladores JIT sao

atualmente, os principais componentes integrados que incrementam o desempenho das

maquinas virtuais. Isso se deve principalmente a criacao e aprimoramento de tecnicas

que se baseiam em hipoteses relacionadas a organizacao e comportamento dos programas

que sao, infelizmente, difıceis (senao impossıveis) de se prever, mesmo durante o tempo

de execucao. Dessa forma, as pesquisas nao possuem outra alternativa senao (1) unir

estrategias para obtencao de outra (Krintz, 2003), (2) estender as existentes (Gal et al.,

2006; Lee et al., 2008; Suganuma et al., 2003) ou (3) buscar melhorias nas arquiteturas

de hardware (Campanoni et al., 2009; Kulkarni, 2011; Kulkarni et al., 2007). Portanto, e

de se esperar que sistemas JIT futuros mantenham o uso das mesmas estrategias, porem

aprimoradas, empregadas nos sistemas atuais.

As estrategias de interpretacao mais compilacao e compilacao mais recompilacao ainda

permanecerao por muito tempo. Para sistemas de interpretacao mais compilacao existe

o overhead da interpretacao. Por outro lado, em sistemas que utilizam compilacao mais

recompilacao existe o overhead de compilar o codigo de todo o programa, embora sem

ou com poucas otimizacoes. Por isso e difıcil avaliar qual abordagem se sobressaira sobre

outra.

Relativo a isso, Suganuma et al. (2005) conseguiram importantes informacoes de

desempenho relativas as abordagens classicas de compilacao JIT. Com um framework

especıfico, os autores observaram que a estrategia de interpretacao mais compilacao exe-

cutou programas de forma mais rapida que a estrategia de compilacao mais recompilacao.

No mesmo trabalho, o uso de contadores na deteccao de regioes quentes provou ser mais

preciso que o uso de tempo. Tais resultados, entretanto, nao foram necessariamente

adotados na construcao de todos os sistemas JIT que vieram depois, contudo, podem

ser considerados (juntamente com o resultado de outros trabalhos) no projeto de futuras

maquinas virtuais que incorporam compilacao JIT.

Outra questao que permanecera e o uso de um sistema de otimizacao adaptativa.

O fato de a tendencia dos sistemas JIT convergir ao uso de nıveis de otimizacao se

deve ao fato de que tais sistemas se adaptam melhor as caracterısticas dos programas.

Page 54: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

51

Programas rapidos, quando compilados com o uso de otimizacoes mais leves, ocasionam

pouco overhead de compilacao. E programas com longo tempo de execucao quando

compilados com o uso de otimizacoes mais agressivas ocasionam um codigo mais eficiente

(Arnold et al., 2000).

Diversas pesquisas tem apresentado tendencias para a proxima geracao de sistemas

com compilacao dinamica. Pesquisas na area de otimizacao (Cavazos e O’Boyle, 2005;

Hoste et al., 2010; Triantafyllis et al., 2003) tem demonstrado que os sistemas poderao

se beneficiar de estudos sobre os campos de acao das otimizacoes, projetadas automa-

ticamente por algoritmos heurısticos. Adicionalmente, os sistemas poderao se basear

em aprendizagem de maquina, para que baseado nas otimizacoes e caracterısticas de

programas executados anteriormente, o sistema se adapte com o tempo (Agakov et al.,

2006; Cavazos e O’Boyle, 2006).

Bruening e Duesterwald (2000) demonstraram que a escolha de metodos (e similares)

como unidades de compilacao e uma escolha ruim. Adicionalmente, na visao de sistemas

JIT, a compilacao baseada em regioes e muito conservativa. Portanto, baseado nas

observacoes de Inoue et al. (2011), sistemas JIT baseados em grandes tracos de execucao

podem ser a melhor escolha de implementacao. Adicionalmente, Kulkarni (2011) destaca

que o sistema JIT pode ajustar a quantidade de threads de compilacao e o limite (contador

ou tempo) para tornar uma regiao quente da melhor forma possıvel, desde que o aumento

do numero de threads de compilacao ativas incorra na diminuicao do valor de limite,

segundo as observacoes do proprio autor.

Provavelmente uma diferenca substancial vira do uso de ferramentas como GNU

Lightning (Bonzini, ????) e LLVM (Lattner e Adve, 2004) na producao de novos

compiladores, devido as facilidades oferecidas por elas. Relacionado a isso, e de esperar

que em nao muito tempo novos compiladores estarao sendo desenvolvidos com base

nestas ferramentas. GNU Lightning apresenta uma serie de desvantagens: possui

uma quantidade limitada de registradores, nao implementa um otimizador peephole, nao

implementa um escalonador de instrucoes, e nao possui uma ferramenta para analise de

codigo, porem, e uma ferramenta rapida na construcao dos compiladores, ocupa pouco

espaco em memoria e garante portabilidade. LLVM e uma ferramenta mais robusta e

oferece recursos de modo que o projetista se preocupe somente em implementar um parser

que transforme a linguagem fonte na representacao intermediaria suportada. Alem disso,

LLVM prove diversas otimizacoes em tempo de compilacao, ligacao e execucao. Outra

vantagem desta ferramenta e a possibilidade de ordenar as otimizacoes da melhor forma

possıvel, o que abre oportunidades para a incorporacao de planos de otimizacao especıficos.

Page 55: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

52

Portanto, e baseado nas funcionalidades de LLVM que o sistema relativo a este

trabalho foi desenvolvido. Alem de empregar a coleta de tracos de execucao, os trechos

quentes de codigo sao compilados por essa ferramenta. O Capıtulo 4 apresenta o sistema

desenvolvido e como LLVM foi utilizado para executar essa tarefa. Contudo, antes de

apresentar o sistema em si, e necessario descrever os conceitos de Prolog, que foram

relevantes neste trabalho. Tais conceitos sao apresentados no proximo capıtulo.

Page 56: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

53

3

Prolog

Prolog e uma linguagem de programacao em logica baseada em um subconjunto de logica

de primeira ordem denominada clausulas de Horn (Horn, 1951). Sua principal utilizacao

reside no domınio da programacao simbolica, em que a solucao dos problemas envolve

relacoes entre objetos. Exemplos de sua aplicacao incluem processamento de linguagem

natural (Quintano e Rodrigues, 2006) e construcao de sistemas dedutivos (Ramakrishnan

et al., 2006).

Na pratica, Prolog pode ser implementado tanto por interpretacao de codigo quanto

por compilacao. Interpretadores sao mais faceis de serem mantidos, mas sao prejudicados

na velocidade pela necessidade de traduzir codigo em tempo de execucao. Por outro lado,

compiladores garantem codigo mais rapido, mas sao mais complexos que interpretadores.

Independente do modo de implementacao, a maioria dos sistemas seguem um modelo de

implementacao Prolog desenvolvido por Warren (1983), chamada Maquina Abstrata de

Warren (WAM) (Aıt-Kaci, 1991; Warren, 1983), que define uma organizacao de memoria

e um conjunto de instrucoes.

O objetivo deste capıtulo e conceituar a WAM e apresentar algumas tecnicas utilizadas

para melhorar o desempenho de Prolog. A Secao 3.1 apresenta a forma de controle

da linguagem Prolog, necessaria para introduzir conceitos necessarios para as proximas

secoes. As Secoes 3.2 e 3.3 descrevem a WAM e algumas tecnicas empregadas para

melhorar o seu desempenho. A Secao 3.4, apresenta alguns exemplos de implementacao

para a linguagem e, por fim, a Secao 3.5 apresenta as consideracoes finais.

Page 57: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

54

3.1 Controle da Linguagem

Os programas escritos em Prolog sao especificacoes de um determinado problema por

meio de sentencas em clausula de Horn (Horn, 1951). As clausulas podem ser classificadas

como fatos, que sao clausulas com corpo vazio, ou regras, que sao clausulas formadas por

uma cabeca e um corpo. A cabeca e representada pelo predicado que se deseja provar

(juntamente com os seus argumentos) e o corpo consiste de um conjunto de objetivos que

devem ser satisfeitos a fim de que o predicado presente na cabeca seja verdadeiro.

Durante a execucao, Prolog tenta satisfazer as clausulas na ordem em que elas

aparecem no programa, utilizando uma execucao para frente. Basicamente, ele seleciona

um literal e o unifica (Lloyd, 1987) ate nao existirem mais literais. Quando o sistema

invoca um predicado com mais de uma clausula, o ambiente de execucao tenta satisfazer

a primeira e constroi pontos de escolha para as outras. Nesse processo, se o sistema

nao puder satisfazer a clausula, um retrocesso ocorre e o sistema retorna para o ponto de

escolha mais recente para tentar satisfazer a proxima clausula. E importante ressaltar que

ao ocorrer retrocesso, todas as ligacoes realizadas a fim de tornar a clausula verdadeira sao

desfeitas, pois executar a proxima clausula pode fornecer valores diferentes as variaveis. O

ambiente de execucao procura satisfazer as clausulas a fim de encontrar as condicoes para

que uma determinada consulta (passada como entrada) seja verdadeira. Dessa forma, se

o sistema nao encontrar um padrao de unificacao que satisfaca todas as clausulas e nao

houver outra clausula para executar naquele predicado, o sistema informa que nao ha

resposta para a consulta passada.

Por outro lado, se o ambiente encontrar no mınimo um padrao de unificacao que torne

verdadeira a condicao passada, o sistema retorna sucesso na execucao.

3.2 Maquina Abstrata de Warren

A Maquina Abstrata de Warren (WAM) e um modelo para execucao de Prolog criado

por David Warren em 1983, que rapidamente se tornou padrao nas implementacoes para a

linguagem. A motivacao original deste projeto era implementa-lo em hardware (Van Roy

e Despain, 1992), contudo esta ideia nao obteve sucesso por duas principais razoes: (1) o

hardware deveria ser especializado para suporta-lo, limitando a sua procura no mercado,

afinal ha poucas pessoas interessadas em obter uma maquina que execute apenas Prolog; e

(2) por consequencia de baixa procura, o hardware especializado teria pouco investimento

frente aos demais microprocessadores.

Page 58: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

55

Em contrapartida, implementacoes da WAM por meio de interpretadores (Carlsson

e Mildner, 2012; Costa et al., 2012; Diaz et al., 2012; Hermenegildo et al., 2012; Swift

e Warren, 2012; Tarau, 1991; Wielemaker et al., 2012) se tornaram bastante populares

devido a facilidade de implementacao. Algumas destas implementacoes adquirem um bom

desempenho, contudo, todas elas sao prejudicadas pelo overhead intrınseco a traducao

das instrucoes para a arquitetura em tempo de execucao (Romer et al., 1996), alem

de limitarem a aplicacao de otimizacoes devido a alta granularidade das instrucoes

WAM. Implementacoes que geram codigo nativo alcancam um bom desempenho, mas

tornam a transformacao de codigo uma tarefa complexa, resultando em sistemas de difıcil

manutencao.

3.2.1 O Estado Interno da WAM e a Organizacao da Memoria

Prolog e dinamicamente tipado, isto e, variaveis podem conter objetos de qualquer tipo

em tempo de execucao. Os termos da WAM sao repesentados como palavras compostas

por um rotulo, que define o tipo do termo e um valor, que e utilizado para diferentes

propositos dependendo do seu tipo. Valores podem incluir inteiros, enderecos de variaveis

e termos compostos (listas ou estruturas). Variaveis indefinidas sao implementadas como

ponteiros para elas mesmas e sao resolvidas durante a unificacao, onde uma variavel passa

a apontar para outra. Essa forma de representacao pode criar uma cadeia de ponteiros

entre variaveis, sendo necessario percorrer toda a cadeia para encontrar o valor de uma

variavel qualquer. Essa operacao e chamada de desreferenciacao.

A WAM mantem o estado interno da computacao atual definido por registradores que,

dentre os principais, sao:

• P: localizacao do programa (Program Counter).

• CP: apontador para a continuacao de clausulas (continuation pointer).

• E: apontador para o ambiente atual. Um ambiente normalmente esta associado

a uma clausula e armazena enderecos de retorno e todas as variaveis locais desta

clausula.

• B: apontador para o ultimo ponto de escolha. Os pontos de escolha guardam

informacoes referentes ao estado de execucao, a fim de possibilitar o retrocesso.

• A: topo da pilha local.

• TR: topo da trilha.

Page 59: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

56

• H: topo da pilha global (Heap).

• HB: valor de H no ponto de escolha mais recente.

• S: e usado pela unificacao de termos compostos. Este registrador aponta para o

argumento do termo que esta sendo unificado: na WAM os argumentos sao acessados

por meio de sucessivos incrementos de S.

• Mode: e usado para identificar o modo de execucao de certas instrucoes, leitura ou

escrita. Na WAM existem dois modos de execucao: modo leitura e modo escrita.

O modo de leitura ocorre quando o objeto unificado com a cabeca da clausula e

um termo ja construıdo. O modo de escrita ocorre quando a cabeca da clausula e

unificada com um variavel livre, e o termo precisa ser construıdo.

• A1, ..., AN : registros dos argumentos.

• X1, ..., XN : variaveis temporarias.

• Y1, ..., YN : variaveis permanentes.

Os registradores Ai e Xi sao, na verdade, identicos; a diferenca nos nomes meramente

refletem usos diferentes. Os registradores Ai sao usados para passar os argumentos para

um procedimento enquanto que os registradores Xi sao usados para manter os valores de

variaveis temporarias da clausula.

Uma variavel temporaria e uma variavel que tem sua primeira ocorrencia na cabeca

da clausula e nao ocorre em mais de um objetivo no corpo. Essas variaveis nao precisam

ser armazenadas no ambiente da clausula. Por sua vez, uma variavel permanente e

qualquer variavel nao classificada como variavel temporaria. Variaveis permanentes

sao armazenadas em um ambiente e sao enderecadas por deslocamentos do ponteiro de

ambiente. Estas sao referenciadas como Y1, Y2, etc. Variaveis permanentes sao organizadas

no seu ambiente de tal forma que elas podem ser descartadas na medida em que nao sao

mais necessarias.

Com respeito ao estado externo, a WAM dispoe de cinco regioes na memoria que

consistem de quatro pilhas para tratamentos especıficos e uma area de codigo contendo

instrucoes e dados relativos ao programa. As pilhas se expandem no momento da chamada

de uma clausula e contraem no retrocesso, sao elas: pilha global, pilha local, trilha e a

PDL (push down list). A Figura - 3.1 apresenta a organizacao da memoria na WAM.

A pilha global (ou heap) armazena as estruturas compostas do programa Prolog, isto

e, listas e estruturas. A pilha local contem dois tipos de objetos: os ambientes e os pontos

Page 60: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

57

Figura 3.1: Organizacao da Memoria na WAM.

de escolha. Um ambiente normalmente esta associado a uma clausula e armazena todas

as variaveis locais desta clausula enquanto que os pontos de escolha guardam informacoes

referentes ao estado de execucao, a fim de possibilitar o retrocesso. A trilha armazena

referencias de variaveis que foram definidas durante a unificacao, mas que devem ser

indefinidas durante o retrocesso e a PDL auxilia na unificacao dos termos.

3.2.2 Conjunto de Instrucoes

Os programas Prolog sao codificados em instrucoes sequenciais. Ha, basicamente, uma

instrucao para cada sımbolo do programa. Uma instrucao consiste de um codigo de

operacao, ou simplesmente opcode, mais os operandos, que podem ser inteiros, desloca-

mentos ou enderecos. A maioria das instrucoes Prolog possui dois operandos. O modelo

original da WAM consistia dos seguintes grupos de instrucoes: instrucoes get, instrucoes

put, instrucoes unify, instrucoes de procedimento e instrucoes de indexacao.

Page 61: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

58

As instrucoes get sao responsaveis por unificar os argumentos do predicado com

os valores armazenados nos registradores A. As principais instrucoes deste grupo estao

descritas a seguir1.

get variable Vn, Ai atribui o valor de Ai em Vn;

get value Vn, Ai unifica o valor do registrador Ai com o conteudo de Vn, armazenando

o resultado da unificacao em Vn, se Vn for uma variavel temporaria;

get constant C, Ai obtem o valor de Ai e desreferencia-o. Se o resultado for uma

variavel, C e atribuıdo a ela. Caso contrario, ocorrera um retrocesso se este resultado

for diferente de C;

get nil Ai executa da mesma forma que get constant C, Ai, mas neste caso a cons-

tante e [];

get structure F, Ai desreferencia o valor em Ai e prossegue conforme os casos a seguir:

se o resultado for uma variavel, esta recebe um novo ponteiro que aponta no topo

da heap, o functor F e inserido na heap e a execucao prossegue em modo de escrita;

se o resultado for um functor identico a F, o registrador S e ajustado para apontar

para o endereco da heap imediatamente apos o endereco de F e a execucao prossegue

em modo de leitura. Qualquer outro caso resulta em retrocesso.

get list Ai desreferencia o valor em Ai e prossegue conforme os casos a seguir: se o

resultado for uma variavel, esta recebe um novo ponteiro para o topo da heap e a

execucao prossegue em modo de escrita; se o resultado e uma lista, o registrador

S e ajustado para apontar para o endereco da heap onde a lista esta e a execucao

prossegue em modo de leitura. Qualquer outro caso diferente resulta em retrocesso.

A instrucao get variable Vn, Ai e utilizada se Vn nao estiver instanciada, ou seja,

ela e utilizada somente na primeira ocorrencia da variavel na clausula. Caso contrario, a

instrucao get value Vn, Ai e utilizada.

As instrucoes put sao responsaveis por armazenar os argumentos dos predicados nos

registradores A. As instrucoes deste grupo sao:

put variable Yn, Ai cria uma referencia para uma variavel permanente nao instanciada,

representada por Yn, armazenando-a em Ai e Yn;

1Na descricao de todas as instrucoes, Ai representa o registrador de argumento i, C e F representamrespectivamente, uma constante e um functor e Vn representa tanto uma variavel temporaria (Xn) comouma variavel permanente (Yn).

Page 62: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

59

put variable Xn, Ai cria uma variavel nao instanciada na heap, armazenando-a em Ai

e Xn;

put value Vn, Ai atribui o valor de Vn no registrador Ai;

put unsafe value Yn, Ai atribui o valor de Yn no registrador Ai e globaliza Yn;

put const C, Ai atribui a constante C no registrador Ai;

put nil Ai atribui a constante [] no registrador Ai;

put structure F, Ai inicializa uma estrutura movendo o functor F para uma nova

posicao na heap e atualiza Ai com o ponteiro da posicao criada. A execucao prossegue

em modo de escrita;

put list Ai atribui no registrador Ai o ponteiro da lista correspondente ao topo da heap

e prossegue a execucao em modo de escrita.

A instrucao put unsafe value e utilizada no lugar de put value para tratar variaveis

inseguras que aparecem no ultimo objetivo da clausula. Uma variavel insegura e uma

variavel permanente cuja primeira ocorrencia nao acontece em estruturas ou na cabeca

da clausula, isto e, e uma variavel outrora inicializada pela instrucao put variable.

A falta de um tratamento especial para tais variaveis permitem que estas mantenham

referencias para uma celula dentro de um ambiente mesmo apos a sua exclusao pela

instrucao deallocate, produzindo uma cadeia de referencias que podem levar a um

valor indeterminado para um registrador A. Desta forma, put unsafe value garante que

a variavel seja desreferenciada para algo externo ao ambiente atual, instanciando uma

variavel na heap para ela.

As instrucoes unify sao precedidas por uma instrucao get ou put que leem ou escrevem

estruturas ou listas. Isso significa que tais instrucoes computam conforme o modo de

execucao atual: modo de leitura ou modo de escrita. Basicamente, em modo de leitura,

as instrucoes unify realizam a unificacao de argumentos sucessivos de uma estrutura

existente, enderecada pelo registrador S enquanto que em modo de escrita elas constroem

os argumentos sucessivos de uma nova estrutura, enderecada pelo registrador H. As

instrucoes sao:

unify void N salta N argumentos a partir de S quando esta em modo de leitura. Em

modo de escrita, esta instrucao insere N novas variaveis (indefinidas) na heap;

Page 63: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

60

unify variable Vn armazena o argumento apontado por S em Vn quando esta em modo

de leitura. Em modo de escrita, a instrucao insere uma nova variavel (indefinida)

na heap, e armazena sua referencia em Vn;

unify value Vn unifica o argumento apontado por S com o valor contido em Vn quando

esta em modo de leitura. Alem disso, se Vn for um temporario, o resultado da

unificacao e armazenado nela. Em modo de escrita, a instrucao armazena o valor

da variavel Vn na heap;

unify local value Vn processa da mesma forma que unify value Vn, exceto que no

modo de escrita, o valor de Vn e desreferenciado e e somente inserido na heap se o

resultado nao for uma referencia para uma variavel na pilha local. Caso o resultado

for uma referencia para uma variavel na pilha local, uma nova variavel (indefinida)

e inserida na heap e a variavel na pilha local e ajustada para apontar para esta nova

variavel. Caso Vn for uma variavel temporaria, Vn tambem e ajustado para apontar

para esta nova variavel.

unify constant C operando em modo de leitura desreferencia o argumento apontado por

S e, sendo esta uma variavel, armazena nela a constante C. Se nao for uma variavel,

o valor e comparado com C e, sendo diferente, o retrocesso ocorre. Em modo de

escrita, a constante C e simplesmente inserida na heap.

A instrucao unify void N representa uma sequencia de variaveis de ocorrencia unica,

ou seja, nenhuma variavel e necessaria para processar esta instrucao.

As instrucoes de procedimento realizam a transferencia de controle e alocacao do

ambiente associado com o predicado a ser chamado. As instrucoes que compoem este

grupo sao:

allocate aloca um espaco para um novo ambiente na pilha local;

deallocate : restaura o estado mais recente e retira o ultimo ambiente da pilha local.

call Pred, N : finaliza um objetivo do corpo da clausula e faz o program counter P

apontar para o predicado Pred com aridade N;

execute Pred : finaliza o ultimo objetivo do corpo da clausula e faz o program counter

P apontar para o predicado Pred;

proceed : finaliza a execucao de uma clausula, fazendo o program counter P receber o

valor de CP.

Page 64: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

61

Por fim, as instrucoes de indexacao interligam clausulas diferentes apos uma instrucao

de procedimento, a fim de selecionar a clausula correta a executar dentro de um predicado.

A indexacao e baseada em uma chave que e o functor principal do primeiro argumento

do procedimento (armazenado em A1). As instrucoes deste grupo estao representadas a

seguir. Aqui, L, Lv, Lc, Ll e Ls sao enderecos de clausulas (ou conjuntos de clausulas), e

Table e uma tabela hash de tamanho N.

try me else L cria um novo ponto de escolha armazenando na pilha local o endereco L

da proxima clausula, os valores dos registradores E, CP, B, TR e H e os argumentos

do predicado. Apos isso, HB e B sao ajustados com o ponteiro atual da heap e com

o topo da pilha local, respectivamente;

retry me else L atualiza o ponto de escolha atual com o endereco da proxima clausula

contido em L;

trust me else fail descarta o ponto de escolha atual e recupera o estado mais recente

de B e HB;

try L cria um novo ponto de escolha armazenando na pilha local o endereco da proxima

instrucao, os valores dos registradores E, CP, B, TR e H e os argumentos do predicado.

Apos isso, HB e B sao ajustados com o ponteiro atual da heap e com o topo da

pilha local. Por fim, o program counter P e ajustado com o endereco L da proxima

clausula;

retry L atualiza o ponto de escolha atual com o endereco da proxima instrucao e ajusta

P com o endereco L da proxima clausula;

trust L descarta o ponto de escolha atual e recupera o estado mais recente de B e HB.

Por fim, o program counter P e ajustado com o endereco L da proxima clausula;

switch on term Lv, Lc, Ll, Ls desreferencia o valor contido em A1, e ajusta P com

um dos enderecos Lv, Lc, Ll ou Ls dependendo se o resultado da desreferenciacao

for uma variavel, constante, lista nao vazia ou estrutura, respectivamente.

switch on constant N, Table utiliza a constante armazenada A1 como chave para en-

contrar o endereco que sera armazenado no program counter P. Essa busca e feita

na tabela hash Table, cujo tamanho e N. Ocorrera retrocesso se a busca falhar;

switch on structure N, Table processa da mesma forma que switch on constant,

porem a chave utilizada e o functor principal armazenado em A1.

Page 65: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

62

3.3 Melhorando o Desempenho da WAM

A WAM foi um grande passo para a execucao eficiente de Prolog. A partir do ponto

de vista de provas de teoremas, Prolog e extremamente rapido. Mas existe ainda uma

grande lacuna entre a eficiencia de WAM e implementacoes de linguagens imperativas

(Van Roy, 1994). A seguir, sao apresentadas algumas tecnicas ja propostas para melhorar

ainda mais a execucao de programas Prolog em sistemas baseados na WAM.

3.3.1 Especializar a Unificacao

O esquema de compilacao de termos compostos na WAM foi projetado para ser completo

e compacto, sem levar em conta questoes de eficiencia. Na verdade, as instrucoes de

unificacao padrao da WAM geram operacoes redundantes, principalmente porque a visita

dos termos em estruturas compostas e feito em largura (Meier, 1990). Alem disso, o modo

de escrita nao e propagado para as subestruturas. De fato, sempre que uma estrutura e

unificada em modo de escrita, e claro que todas as suas subestruturas tambem devem

ser unificadas nesse modo. Nao obstante, a WAM necessita utilizar varias variaveis

temporarias no decorrer deste processo.

A alta granularidade das instrucoes WAM provem de tais caracterısticas, visto que na

unificacao dos subtermos, as instrucoes devem testar o modo a cada momento, evitando a

aplicacao de otimizacoes para um determinado contexto do programa. O trabalho de Turk

(1986) descreve algumas otimizacoes para a WAM, inclusive um metodo para reducao do

overhead de manter o registrador de modo. Marien (1988) apresenta um metodo para

compilar unificacao no modo de escrita que usa um numero mınimo de operacoes. Uma

linguagem intermediaria para auxiliar nas operacoes de unificacao da WAM foi introduzida

por Van Roy (1989), no custo de aumentar o tamanho do codigo. A eliminacao das

redundancias nas operacoes de unificacao so foram retiradas com o metodo proposto por

Meier (1990), onde os termos das estruturas eram visitados em profundidade. O metodo

de Meier possibilitava ainda propagar o modo de escrita, alem de utilizar menos variaveis

temporarias que a WAM.

Dentre as implementacoes Prolog atuais, YAP (Costa et al., 2012) implementa o

metodo proposto por Meier. SICStus Prolog (Carlsson e Mildner, 2012; Nassen, 2001)

emprega uma forma menos geral, onde somente os termos de listas sao visitados em

profundidade. Os demais sistemas nao fornecem informacoes quanto a especializacao das

instrucoes de unificacao.

Page 66: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

63

3.3.2 Otimizar Selecao de Clausulas

Como apresentado na Secao 3.2.2, a WAM possui instrucoes que escolhem clausulas

dependendo da constante ou do functor principal do primeiro argumento. Porem, se

todas as clausulas dentro de um predicado contem functors (ou constantes) diferentes,

entao uma tabela hash precisa ser construıda, a fim de possibilitar uma busca eficiente

para a clausula correta, alem de evitar a criacao de um ponto de escolha excedente (que

seria inevitavel sem esta estrutura). Isso significa que, no caso geral, os predicados podem

ser compilados para criar no maximo um ponto de escolha entre o ponto de entrada e a

execucao da primeira clausula (Carlsson, 1987; Van Roy, 1984).

Esta caracterıstica facilita a implementacao da selecao de clausulas em sistemas

baseados na WAM, mas muitos programas podem nao se beneficiar desta estrategia,

como por exemplo, em programas cuja selecao depende de mais de um argumento. Nesse

sentido, um algoritmo ideal de selecao de clausula deveria gerar codigo com as seguintes

propriedades (Van Roy, 1994):

• Ele testa somente as clausulas que podem ser invocadas, baseado nos tipo dos

argumentos;

• Ele evita todas as criacoes inuteis de pontos de escolha;

• Seu tamanho e linear com o tamanho do programa;

• Ele cria pontos de escolha de forma incremental, isto e, os pontos de escolha contem

somente partes do estado de execucao que necessitam ser salvos;

• A degradacao do desempenho e gradual conforme a insuficiencia da informacao sobre

os tipos.

Infelizmente, nao existe um metodo publicado que satisfaca todas essas condicoes.

O que existe sao algoritmos que satisfazem algumas delas e realizam melhor selecao de

clausulas que a WAM. Van Roy et al. (1987) apresentaram um algoritmo que gera uma

arvore de selecao ingenua e cria pontos de escolha de forma incremental. Uma forma mais

restrita desta tecnica, chamada shallow backtracking, foi implementada por Nassen nas

primeiras versoes do sistema SICStus Prolog (Nassen, 2001). Para isso, o conjunto de

instrucoes foi extendido com uma instrucao especial chamada neck. A versao atual de

SICStus implementa uma versao ainda mais simples desta tecnica (Carlsson e Mildner,

2012).

Page 67: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

64

Hickey e Mudambi (1989) apresentaram um algoritmo para gerar uma arvore de testes

de modo a minimizar o overhead do retrocesso. No pior caso, o tamanho da arvore tem

uma proporcao quadratica ao tamanho do codigo. Alem disso, seu trabalho cria pontos de

escolha de forma incremental, possibilitando que o coletor de lixo recupere mais memoria.

Um ano mais tarde, Kliger e Shapiro (1990) utilizaram grafo acıclico direcionado para

atingir o mesmo proposito e garantiram que, independente de qualquer programa, a selecao

de clausulas sempre seria melhor que a selecao de clausulas original da WAM.

O sistema Aquarius (Van Roy, 1990; Van Roy e Despain, 1992) produz um grafo de

selecao para disjuncoes contendo testes para unificacoes, tipo e comparacoes aritmeticas.

Duas transformacoes sao utilizas para possibilitar os testes: (1) type enrichment, que

adiciona informacoes de tipo para um predicado que carece dela e (2) factoring que permite

o sistema tomar vantagem de testes em variaveis realizando a unificacao de um termo para

todas as ocorrencias dele. Parma (Taylor, 1996) e outro sistema que implementa uma

estrategia semelhante.

Outras implementacoes atuais de Prolog, tais como SWI-Prolog (Wielemaker,

2003; Wielemaker et al., 2012), XSB (Sagonas et al., 1993; Swift e Warren, 2012)

realizam a selecao de clausulas baseada em multiplos argumentos, mas requerem um

esforco adicional por parte do programador para possibilitar este processo. Este esforco

nao e necessario em ilProlog (Troncon et al., 2007), que emprega uma heurıstica

em tempo de compilacao para realizar a mesma tarefa. Infelizmente, este tipo de

selecao sofre o risco de indexar argumentos de saıda, cujo efeito e aumentar o tempo

de compilacao de forma desnecessaria. De fato, analise global poderia evitar este risco,

prevendo os modos de execucao possıveis em tempo de compilacao. Contudo, nenhum

destes sistemas implementam analise global. Uma forma sofisticada de contornar este

problema foi apresentada por Costa et al. (2007), com a indexacao por demanda,

que permite a indexacao de predicados estaticos e dinamicos baseados somente nos

argumentos de entrada, sem necessitar de analise global ou qualquer intervencao por

parte do programador. Atualmente este metodo e o principal esquema de selecao de

clausulas do sistema YAP (Costa et al., 2012).

3.3.3 Gerar Codigo Nativo

Uma base teorica para acelerar a execucao de programas Prolog e representar o codigo

em simples instrucoes. Isso diminui a granularidade e da oportunidades para a aplicacao

de diversas otimizacoes de codigo. Os primeiros experimentos publicados utilizando esta

ideia foram realizados por Tamura (1986) e Komatsu et al. (1987), que demonstraram

Page 68: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

65

que a chave para o alto desempenho de Prolog nao esta associado necessariamente a um

hardware especializado.

Por volta de 1988, Taylor e Van Roy trabalharam nos sistemas Parma (Taylor, 1996)

e Aquarius (Van Roy, 1990; Van Roy e Despain, 1992) que compilam codigo Prolog

para nativo, utilizando analise global para fornecer informacoes para as otimizacoes. Ao

contrario de Komatsu et al. e Tamura, Taylor e Van Roy ignoraram o uso da WAM, pois

estavam confiantes que a baixa granularidade do conjunto de instrucoes permitiria que

todas as otimizacoes fossem expressadas. Parma compilava codigo Prolog utilizando

uma representacao intermediaria de tres enderecos e Aquarius se baseava na Berkeley

Abstract Machine (BAM), que continha mais instrucoes que aWAM (porem mais simples),

inclusive algumas especializadas em tempo de execucao. O resultado nao foi diferente,

apesar da dificuldade de manutencao destes sistemas, Aquarius e Parma superaram

outras implementacoes existentes.

Essa forma de execucao, no entanto, nao ficou restrita somente a esses sistemas.

Atualmente, uma boa parte das implementacoes Prolog geram codigo nativo, tais como

GNU-Prolog (Diaz et al., 2012), SICStus Prolog (Carlsson e Mildner, 2012; Nassen,

2001), CIAO (Hermenegildo et al., 2012) BinProlog (Tarau, 1991) e XSB (Sagonas et

al., 1993; Swift e Warren, 2012).

Uma variacao dessa estrategia e a geracao de codigo nativo em tempo de execucao,

com o uso de compiladores just-in-time. O unico compilador JIT para YAP existente

e o YAPc, desenvolvido para o sistema YAP por Silva e Costa (2007). Com este

compilador, as clausulas mais frequentes de um programa sao especializadas em tempo

de execucao. Resultados mostraram que alguns programas obtiveram uma reducao do

tempo de execucao entre 2 a 7 vezes, sob uma execucao que somente interpreta (Silva e

Costa, 2007). YAPc foi utilizado com um prova de conceito para execucao eficiente de

Prolog e nao chegou a integrar a arquitetura do YAP.

3.3.4 Utilizar Analise Global

Tradicionalmente, analise global para programas logicos e usado para derivar informacoes,

como de tipo e modo, com o objetivo de aumentar a velocidade de execucao e/ou reduzir

o tamanho do codigo. Os algoritmos de analise global estudados ate o momento sao

todas instancias de um metodo geral chamado de interpretacao abstrata, cuja ideia geral

e executar o programa sobre um domınio simples, isto e, um domınio conservativo, a fim

de satisfazer um pequeno conjunto de restricoes (Mellish, 1981). No termino da execucao,

os resultados encontrados fornecem uma aproximacao correta de informacoes sobre o

Page 69: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

66

programa analisado. Le Charlier et al. (1990, 1993) realizaram um estudo extensivo de

algoritmos e domınios de interpretacao abstrata e sua efetividade em derivar tipos. Por

outro lado, Getzinger (1993) apresentou uma taxonomia extensa de domınios de analises

e estudou seus efeitos sobre o tempo de execucao e tamanho do codigo.

As primeiras evidencias de que analise global seria considerada util para imple-

mentacoes Prolog vieram nos trabalhos de Mellish (1981, 1985), mas as primeiras medidas

de praticidade foram publicadas em 1988 por Warren et al. (1988), ao avaliar dois sistemas

de analise global: MA3 e Ms. O trabalho concluiu que ambos os analisadores sao efetivos

em derivar tipos e nao aumentam o tempo de compilacao de forma consideravel. Van

Roy e Taylor tambem obtiveram bons resultados nos sistemas Aquarius (Van Roy,

1990; Van Roy e Despain, 1992) e Parma (Taylor, 1996). Atualmente, poucos sistemas

nao-obsoletos empregam analise global, a exemplo, o sistema CIAO (Hermenegildo et al.,

2012).

3.3.5 Utilizar Memoizacao

Memoizacao (do ingles memoization) e uma tecnica para manter em cache a solucao

de predicados ja processados. A adicao desta tecnica no mecanismo de resolucao de

Prolog permite obter um novo modelo de execucao que realiza execucao de baixo para

cima e execucao de cima para baixo. Para certos algoritmos, como algoritmos de

programacao dinamica, esse novo modelo permite executar definicoes logicas com uma

baixa complexidade, se comparado ao mecanismo tradicional da WAM.

Uma implementacao de memoizacao e a resolucao OLDT (Ordered Linear Resolution

of Definite Clauses with Tabulation) (Swift e Warren, 1992) e uma generalizacao dela e

a resolucao SLG (Linear resolution with Selection function for General logic programs)

(Chen e Warren, 1993), que lida tambem com negacao e foi implementada primeiramente

no sistemaXSB (Sagonas et al., 1993; Swift e Warren, 2012). Essa implementacao executa

codigo Prolog com menos de 10% de overhead relativo a WAM e e muito mais rapido

que sistemas de banco de dados dedutivos (Swift e Warren, 1993). Memoizacao tambem

e empregada pelo sistema YAP (Rocha et al., 2001) e esta em fase de implementacao no

sistema GNU-Prolog. (Diaz et al., 2012)

3.4 Implementacoes Prolog

Geralmente as implementacoes da WAM por software sao uma ordem de magnitude mais

lenta do que linguagens imperativas. Por um lado, o uso de interpretadores possui o

Page 70: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

67

atrativo de tornar o sistema portavel e interativo. Por outro lado, compiladores conseguem

gerar codigo mais eficiente. As implementacoes citadas neste trabalho sao descritas a

seguir e uma boa parte delas suportam ambos os modos de execucao.

Aquarius foi desenvolvido por Peter Van Roy, sendo o primeiro sistema a compilar

codigo nativo sem um estagio intermediario baseado na WAM (Van Roy, 1990;

Van Roy e Despain, 1992). Aquarius adotava o modelo de execucao BAM

(Berkeley Abstract Machine) que, ao contrario da WAM, empregava instrucoes mais

simples, o que permitia aplicar extensas otimizacoes. Outras caracterısticas deste

compilador incluem: (1) exploracao do determinismo, que permitia simplificar o

retrocesso por saltos condicionais; (2) especializacao de unificacoes, simplificando

a unificacoes para simples atribuicoes, quando possıvel e (3) analise de fluxo de

dados, que fornecia informacoes necessarias para a exploracao do determinismo e

especializacao da unificacao. Aquarius mostrou que a execucao de programas

Prolog pode competir com programas gerados por um compilador otimizador C

para uma classe de programas nao-triviais (Van Roy e Despain, 1992). Contudo,

em vista das tecnicas empregadas, somado ao cuidado sobre algumas instrucoes da

BAM (que necessitavam ser especializadas em tempo de execucao), Aquarius se

tornou um sistema muito complexo para ser mantido. Em consequencia, Aquarius

nao teve continuidade, sendo abandonado em 1993.

BinProlog foi desenvolvido por Tarau, sendo um sistema Prolog capaz de interpretar

codigo, gerar codigo C/C++ e ainda gerar codigo executavel (Tarau, 1991). Bin-

Prolog prove um alto nıvel de abstracao para o desenvolvimento de aplicacoes

distribuıdas e para Internet, alem de uma interface para as linguagens C (Ritchie,

1993), C++ (Stroustrup, 2011) e Java (Arnold et al., 2005), alem de Tcl/Tk (Flynt,

2012).

CIAO e um ambiente de programacao multiparadigma desenvolvido na Universidade

Politecnica de Madri (Hermenegildo et al., 2012). Este sistema foi inicialmente

projetado para transformar codigo Prolog para C (Ritchie, 1993), deixando para o

compilador desta linguagem gerar o codigo executavel para a arquitetura subjacente.

Nas versoes atuais, CIAO fornece um ambiente completo de desenvolvimento

incluindo um interpretador, um compilador, uma IDE, um analisador estatico de

codigo, alem de um pre-processador potente capaz de gerar diversas otimizacoes,

inclusive paralelizacao automatica. O sistema oferece ainda uma linguagem de

declaracao, que possibilita a insercao estatica de informacoes de tipo e modo,

Page 71: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

68

fornecidas pelo proprio usuario. Estas informacoes sao utilizadas para realizar

diversas otimizacoes de alto nıvel, incluindo especializacao abstrata multipla (Puebla

e Hermenegildo, 1995), avaliacao parcial (Puebla et al., 2006) e reducao de con-

correncia (Puebla et al., 1997). Na ausencia de tais informacoes, o proprio sistema

tenta inferi-las, utilizando os metodos propostos em (Muthukumar e Hermenegildo,

1992), (Saglam e Gallagher, 1995) e (Vaucheret e Bueno, 2002).

GNU-Prolog e um sistema Prolog desenvolvido por Diaz et al. (2012), que teve inıcio

em 1996 com o nome de Calypso e que foi posteriormente lancado como um

produto GNU com o nome de GNU Prolog. O sistema fornece dois modos de

execucao a saber: interpretado e nativo. Embora o compilador gere codigo nativo

de alta qualidade, um trabalho publicado recentemente mostrou que o interpretador

nao tem um bom desempenho frente a outros sistemas interpretados, como CIAO,

SICStus e YAP (Martins e Silva, 2011). GNU-Prolog esta em desenvolvimento

para prover suporte a um coletor de lixo e a memoizacao. Metas de longo prazo

estipulam a criacao de um compilador mais sofisticado, alem da integracao com

LLVM (Lattner e Adve, 2004).

Parma e um compilador Prolog experimental para arquitetura MIPS, desenvolvido na

Universidade New South Wales em Sidney, Australia (Taylor, 1996). O componente

mais importante no desempenho do Parma e a fase de analise global, que examina o

programa como um todo para reunir informacoes que sao utilizadas durante a com-

pilacao do programa. Informacoes sobre as caracterısticas operacionais do programa,

como cadeias de desreferenciamento, sao utilizadas para remover muitas operacoes

inerentes da linguagem, que sequer eram tratadas em outras implementacoes. Em

Parma, as instrucoes sao compiladas utilizando uma representacao intermediaria

de tres enderecos, embora o modelo de memoria seja ainda similar ao da WAM.

Alem disso, Parma emprega uma forma de armazenamento de modo a reduzir o

custo do retrocesso. Infelizmente, assim como Aquarius, Parma foi abandonado

devido a sua difıcil manutencao.

SICStus Prolog foi desenvolvido pelo Swedish Institute of Computer Science (SICS).

A implementacao deste sistema foi baseada na especificacao da WAM, porem

implementa alguns recursos adicionais como o corte, predicados aritmeticos, testes

de tipo, alem de ter suporte para coleta de lixo, corrotinas e manipulacao de

interrupcoes (Carlsson e Mildner, 2012; Nassen, 2001). SICStus Prolog ainda

implementa instrucoes de teste aritmeticos sofisticados, baseado numa variacao mais

Page 72: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

69

simples do metodo shallow backtracking (Carlsson, 1989). Indexacao de clausulas

e retrocesso sao tratados dentro das instrucoes call e execute, ao contrario da

especificacao original da WAM, em que havia instrucoes especıficas para essas

tarefas. SICStus pode executar codigo Prolog em tres modos de execucao

distintos: (1) interpretado, onde as clausulas sao representadas como termos, a

fim de acelerar a atualizacao na base de dados, alem de dar suporte para depuracao

de codigo; (2) nativo, para execucao rapida e (3) emulado, que simplifica a carga do

sistema e o gerenciamento de memoria.

SWI-Prolog foi desenvolvido por Wielemaker, com o proposito de ser um sistema simples

e compacto (Wielemaker, 2003; Wielemaker et al., 2012). SWI-Prolog possui

compatibilidade com outros sistemas comoCIAO eGNU-Prolog. Com o objetivo

de ser um ambiente de desenvolvimento e academico, possui um framework de

desenvolvimento completo, incluindo uma IDE, um analisador e uma interface para

diferentes linguagens de programacao, como C (Ritchie, 1993), C++ (Stroustrup,

2011) e Java (Arnold et al., 2005). Uma caracterıstica interessante e o fato deste

sistema possuir um modulo para servidores web multithreaded, capaz de gerar codigo

HTML (Silva, 2011), autorizacao HTTP (Shiflett, 2003), alem de gerenciar sessoes.

XSB e um sistema Prolog que foi desenvolvido por diversas instituicoes, com o intuito de

prover uma abordagem alternativa para criar sistemas de banco de dados dedutivos

(Sagonas et al., 1993; Swift e Warren, 2012). XSB emprega memoizacao para evitar

avaliacoes nao-finitas e redundancia na resolucao dos predicados, que sao inerentes

ao algoritmo de inferencia presente nas implementacoes-padrao de Prolog. Isso e

importante no contexto do sistema, visto que o reuso de informacoes ja computadas

e uma boa abordagem para sistemas que manipulam grande quantidade de dados. A

execucao de programas neste sistema pode ser feito da forma interpretada e nativa.

A execucao interpretada e lenta, mas predicados compilados sao considerados

estaticos por XSB no momento da compilacao, o que pode ser indesejavel ao

manipular muitos dados. Como uma alternativa para compilacao, XSB permite

predicados dinamicos, cujo codigo pode ser modificado durante a execucao.

Uma comparacao do desempenho de alguns destes sistemas foi descrita no trabalho

de Martins e Silva (Martins e Silva, 2011).

Page 73: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

70

3.5 Consideracoes Finais

A principal motivacao para o uso de programacao em logica e permitir que os progra-

madores descrevam o que eles querem separadamente de como alcancar este objetivo.

Isto e baseado na premissa de que qualquer algoritmo consiste de duas partes: uma

especificacao logica, a “logica”, e uma descricao de como executar esta especificacao,

o “controle”. Programas logicos sao declaracoes descrevendo propriedades do resultado

esperado, com o controle para entender o sistema. A maior parte deste controle pode ser

automaticamente provida pelo sistema, o que o mantem claramente separado da logica.

Prolog (Casanova et al., 1987; Sterling e Shapiro, 1994) e uma linguagem que foi

originalmente criada para resolver problemas em linguagem natural. A semantica de

Prolog ataca um balanceamento entre eficiente implementacao e completude logica

(Meier, 1990; Warren, 1983). Isto atenta para descrever a programacao como um

subconjunto de logica de primeira ordem, que nao e apenas um provador simples de

teorema, mas tambem uma linguagem de programacao usual devido a simplicidade e a

implementacao eficiente dos conceitos de unificacao e busca.

A primeira implementacao de Prolog foi um interpretador desenvolvido por Roussel

e Colmerauer na decada de 70 (Colmerauer e Roussel, 1996). Em 1977, David Warren

criou o primeiro compilador de Prolog, o DEC-10 Prolog (Warren, 1977), que gerava

codigo assembly para o DEC-10. A investigacao na implementacao de Prolog continuou

com a Maquina Abstrata de David Warren (a WAM), uma linguagem intermediaria para

a compilacao de Prolog. A WAM oferecia varias vantagens, tais como facil compilacao,

portabilidade e codigo compacto. Por essas razoes, a WAM se revelou uma forma eficiente

e elegante de permitir a execucao de programas Prolog numa maquina sequencial e desta

forma se tornou rapidamente como modelo para implementacoes de Prolog.

A motivacao original no projeto de maquinas abstratas era a construcao de hardware

para suportar Prolog eficientemente. Porem as instrucoes WAM realizam operacoes muito

complexas, como a unificacao, enquanto o desenvolvimento das novas arquiteturas seguiu

uma direcao oposta, possuir um pequeno conjunto de instrucoes simples. As dificuldades

em obter bom desempenho em arquiteturas tradicionais e o custo de desenvolver hard-

ware para suportar Prolog justificam que a WAM tenha sido principalmente usada em

implementacoes por software. Estas implementacoes tradicionalmente compilam o codigo

Prolog para o codigo de uma maquina abstrata que depois e interpretado, como realizado

em: YAP (Costa et al., 2012), SICStus Prolog (Carlsson e Mildner, 2012; Nassen,

2001), SWI-Prolog (Wielemaker, 2003; Wielemaker et al., 2012), GNU-Prolog (Diaz

Page 74: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

71

et al., 2012), BinProlog (Tarau, 1991) e XSB (Sagonas et al., 1993; Swift e Warren,

2012).

Apos o advento dos interpretadores para Prolog, os sistemas Aquarius (Van Roy,

1990) e Parma (Taylor, 1996) provaram que em alguns casos, as linguagens logicas podem

ter desempenho comparavel ao das linguagens imperativas. O bom desempenho destes

sistemas e devido basicamente a dois fatores: a geracao de codigo nativo e o uso de

analise global. Contudo tais sistemas foram descontinuados devido a alta complexidade

de manutencao.

A geracao de codigo nativo para Prolog e um problema complexo. Usualmente o pro-

blema e solucionado organizando a computacao em um conjunto de fases especializadas,

como ocorre no sistema SICStus Prolog que transforma o codigo Prolog em codigo

WAM, para depois transformar em uma nova linguagem intermediaria (Haygood, 1994).

Uma alternativa a esta abordagem e a geracao de codigo C a partir de Prolog (Morales

et al., 2003). A filosofia desta abordagem e deixar o trabalho de geracao de codigo, como

tambem da otimizacao, para o compilador C. Outra alternativa e a geracao de codigo

nativo em tempo de execucao, como ocorre no sistema YAP com uso de compilacao JIT

(Silva e Costa, 2007).

Cada abordagem possui alguns problemas inerentes. Primeiro, a complexidade de

alguns sistemas os tornam difıceis de serem mantidos. Consequentemente, sistemas como

Aquarius e Parma foram abandonados, nao existindo mais uma atualizacao para eles.

Segundo, o uso de analise global nao consegue obter uma aceleracao maior que tres. Alem

disso, esta tecnica nao funciona para qualquer tipo de programa. Terceiro, o overhead dos

interpretadores, como por exemplo o YAP, e baixo, desta forma os sistemas que geram

codigo nativo nao conseguem um desempenho consideravelmente melhor.

Utilizando uma abordagem totalmente diferente, Mercury (Conway et al., 1995;

Henderson e Somogyi, 2002) mudou a linguagem. O objetivo foi melhorar o desempenho

de programas logicos. Contudo, surgiu um novo problema: Mercury nao e Prolog.

Consequentemente, nem todos programas Prolog sao executados por Mercury.

Nos ultimos anos ocorreram melhorias significativas na compilacao de Prolog, re-

sultando no desenvolvimento de sistemas eficientes, como SWI-Prolog e YAP. Tais

melhorias foram decorrentes das tecnicas propostas para melhorar o desempenho do

modelo padrao de execucao Prolog: a Maquina Abstrata de Warren.

Por fim, com relacao ao YAP e possıvel que este alcance um desempenho ainda maior

visto que, com a nova arquitetura, YAP tambem sera capaz de gerar codigo nativo. A

visao de alto nıvel e a arquitetura do YAP, bem como a arquitetura do sistema proposto,

que permitira essa tarefa, serao apresentadas no Capıtulo 4. Porem antes de prosseguir

Page 75: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

72

para a proposta deste trabalho, a proxima secao apresenta os trabalhos relacionados em

respeito a compilacao JIT e, mais especificamente, a compilacao JIT baseada em tracos

de execucao.

Page 76: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

73

4

O Ambiente Experimental de

Compilacao Just-in-Time Baseada em

Tracos de Execucao

A implementacao eficiente de linguagens tipicamente interpretadas atualmente apostam

no uso de um sistema de compilacao JIT para compilar e otimizar codigo em tempo de

execucao. Neste contexto, uma contribuicao esperada com este trabalho e a elaboracao

de um ambiente de execucao mista de codigo para o sistema YAP, que seja capaz de

alcancar melhor desempenho na execucao por meio dessa abordagem.

Desta forma, o objetivo deste capıtulo e descrever a nova arquitetura do YAP, um

sistema capaz de gerar codigo nativo em tempo de execucao para os tracos (ou caminhos)

de execucao mais frequentes. Adicionalmente, este capıtulo apresenta a nova interface do

ambiente, que e capaz de proporcionar aos usuarios a facilidade de realizar experimentos

diversos no contexto de compilacao JIT para Prolog.

Este capıtulo esta organizado como se segue. A Secao 4.1 apresenta a visao de alto nıvel

do YAP, bem como a sua arquitetura interna. Em seguida, na Secao 4.2 e apresentada a

nova arquitetura do YAP, proposto neste trabalho, e a relacao entre os seus componentes.

As principais alteracoes realizadas na arquitetura atual para que esta pudesse ser integrada

a arquitetura proposta tambem sao mencionadas nessa secao.

A Secao 4.4 descreve esses novos predicados do YAP, cujo objetivo e torna-lo um

ambiente experimental. Por fim, este capıtulo e finalizado com algumas consideracoes na

Secao 4.5.

Page 77: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

74

4.1 Yet Another Prolog

Yet Another Prolog (YAP) (Costa et al., 2012) e uma implementacao de Prolog desenvol-

vida na Universidade do Porto desde 1985. Este sistema suporta or -paralelismo (Gupta,

1994) e threads, sendo o primeiro trabalho a conter estas caracterısticas juntamente com

memoizacao (Rocha et al., 2001). YAP utiliza um algoritmo de indexacao dinamica, que

e capaz de indexar multiplos argumentos e termos compostos, alem de tornar irrelevante

a forma de como os argumentos de uma clausula estao dispostos (que, no contexto de

sistemas Prolog em geral, e uma causa do aumento do tempo de execucao para alguns

programas). O sistema de indexacao dinamica, denominada JITI (Costa, 2009; Costa et

al., 2007), em conjunto com memoizacao tornam YAP uma boa alternativa para criacao

de sistemas de banco de dados dedutivos, assim como XSB Prolog (Sagonas et al.,

1993; Swift e Warren, 2012).

4.1.1 Estruturas de Dados e Organizacao da Memoria

Assim como na WAM tradicional, YAP mantem o estado interno de execucao em seis

regioes na memoria: a pilha global, pilha local, trilha, pilha auxiliar, a area de codigo e

uma regiao de memoria para o coletor de lixo. As pilhas global e local tambem funcionam

de forma semelhante a WAM, armazenando objetos, pontos de escolha e ambientes.

Basicamente, YAP define seis tipos concretos para os objetos:

1. Pequenos inteiros;

2. Atomos, que sao constantes nao numericas;

3. Aplicacoes, que em um contexto generico, sao as estruturas compostas;

4. Pares, que sao compostos por uma cabeca e uma cauda e sao geralmente usadas

para definir listas;

5. Referencias, ou variaveis, que sao ponteiros para outros objetos. Assim como na

WAM, YAP desreferencia uma variavel para encontrar o seu valor. Variaveis nao

instanciadas sao referencias para elas mesmas ou para NULL; e

6. Extensoes, que sao utilizadas para definir grandes inteiros e ponto flutuante, alem

de estruturas de dados mais complexas, como strings e arrays multidimensionais.

No que se refere ao estado de execucao interno, YAP define diversos registradores. Os

principais sao:

Page 78: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

75

• P: ponteiro para a localizacao do programa (program counter).

• CP: endereco de retorno.

• H: topo da pilha global.

• HB: valor de H no ponto de escolha mais recente.

• B: apontador para o ultimo ponto de escolha.

• BB: topo da pilha local no ultimo ponto de escolha.

• ASP: topo da pilha local.

• TR: topo da trilha.

• AuxTop: topo da pilha auxiliar.

• ENV e YENV: apontadores para o ambiente atual, onde um pode ser diferente do

outro.

• S: apontador para os termos compostos, a fim de possibilitar a unificacao.

• A1, ..., AN : argumentos da clausula em execucao, onde N determina a quantidade

de argumentos.

YAP nao utiliza um registrador especial para armazenar o modo de execucao atual.

Ao contrario da WAM, sua forma de unificar termos compostos dispensa o uso de tal

registrador.

4.1.2 Principais Diferencas com a WAM

YAP compila cada clausula dos programas Prolog para uma representacao baseada na

WAM, chamada YAAM (Costa, 1999; Lopes, 1996), cuja principal diferenca esta no modo

como e realizada a unificacao de termos compostos. O algoritmo de unificacao utilizado

foi publicado em 1990 por Meier (Meier, 1990). Nele, os sub-termos sao compilados em

instrucoes de unificacao por meio de uma busca em profundidade, enquanto na WAM

isso era feito por uma busca em largura. Em adicao, a YAAM assume uma pilha de

Page 79: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

76

unificacao, que e inicializada por uma instrucao get list1 ou get struct2 e estendida

por uma instrucao unify list3 ou unify struct4.

Alem de ser mais simples de implementar, esse algoritmo nao aplica pressao sobre

registradores e permite a heranca de modo. Em outras palavras, se o sistema comeca a

processar uma estrutura em modo de escrita, todas as suas sub-estruturas tambem serao

processadas neste modo. Essa caracterıstica motiva o esquema de duplo-opcode presente

em YAP (Costa, 1999; Lopes, 1996), em que cada instrucao unify possui duas versoes:

uma executada em modo de leitura e outra executada em modo de escrita. Dessa forma,

toda instrucao YAAM executada em modo de escrita realiza menos verificacoes, pois

obedecem as seguintes propriedades:

1. Toda instrucao unify que e executada em modo de escrita e seguida por outra

instrucao em modo de escrita se a execucao procede em um mesmo sub-termo;

2. Toda instrucao unify que e executada em modo de escrita e seguida por uma

instrucao pop5 se a execucao procede para um sub-termo pai;

3. Toda instrucao unify que e executada em modo de escrita e seguida por uma

instrucao get ou uma instrucao de controle se a execucao procede para fora do

termo.

A YAAM ainda emprega outras formas diferenciadas para tratar termos compostos,

que incluem:

• O uso de uma instrucao unify last em vez de uma instrucao unify para tra-

tar o ultimo sub-termo de um termo composto. Instrucoes last nao precisam

atualizar o registrador S, simplificando o codigo. Alem disso, unify last list

e unify last struct nao precisam atualizar a pilha de unificacao; e

• A finalizacao de um sub-termo quando uma instrucao unify last atom, unify last var

ou unify last val e executada. Em seguida, uma instrucao pop e necessaria para

1Similar a instrucao get list da WAM2Similar a instrucao get structure da WAM3No modo de leitura, unify list unifica o termo apontado pelo registrador S se o argumento nao e

variavel. Se o argumento for variavel, unify list inicia uma nova lista. No modo de escrita, unify list

escreve o termo da lista no registrador S e o insere na heap.4No modo de leitura, unify struct unifica o termo apontado pelo registrador S se o argumento nao

e variavel. Se o argumento for variavel, unify struct inicia uma nova estrutura. No modo de escrita,unify struct escreve o termo da estrutura no registrador S e o insere na heap.

5Pop recupera o registrador S e salta para uma instrucao em modo de escrita caso a pilha auxiliarutilizada para unificacao indicar que ainda ha termos para serem unificados. Nao existindo termos, osalto ocorre para uma instrucao em modo de leitura.

Page 80: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

77

retornar um sub-termo acima e configurar o modo para escrita ou leitura e direcionar

a execucao da proxima instrucao.

Em vista disso, e possıvel perceber que a YAAM possui uma quantidade maior de

instrucoes que a WAM, embora mais simples. Isto facilita a implementacao e possibilita

a aplicacao de diversas otimizacoes de codigo.

4.1.3 Estrutura das Clausulas

YAP estrutura as clausulas como uma sequencia de instrucoes YAAM que sao executadas

da primeira ate a ultima, desde que nao ocorra alguma excecao ou operacao de corte.

Basicamente, todas as clausulas possuem as seguintes caracterısticas:

• Podem iniciar com qualquer instrucao YAAM, mas a ultima instrucao e sempre

execute, dexecute ou procceed;

• Na maioria da vezes, logo apos a execucao de uma instrucao call, fcall, execute

ou dexecute, instrucoes de indexacao sao necessarias para invocar a clausula correta.

Tendo em vista que YAP utiliza uma estrutura para representar predicados, isto

e, um conjunto de clausulas com mesmo nome e aridade, essas instrucoes sao

necessarias para determinar a clausula dentro do predicado que precisa ser invocada

apos uma chamada;

• Toda clausula e executada da primeira ate a ultima instrucao YAAM que a compoe,

desde que nao ocorra alguma excecao. Se entende por excecao todo fluxo que

direciona para a execucao de codigo que nao pertence a clausula, que incluem acoes

para backtracking6 e tratamento de overflow nas regioes de memoria do sistema.

Este conceito de excecao sera utilizado deste ponto ate o final do texto.

• Instrucoes de corte bem sucedidas nao geram excecoes, mas evitam que algumas

instrucoes dentro da mesma clausula sejam executadas.

4.1.4 Organizacao do Sistema

As subsecoes anteriores apresentaram uma visao de alto nıvel do YAP, que se resumiram,

de fato, nas principais diferencas com a WAM. Ao contrario disso, o foco desta secao

e apresentar uma visao geral de sua arquitetura interna. O interesse nesse contexto

6Um exemplo de backtrack ocorre quando uma instrucao get list recebe como argumento um termoque nao e uma lista.

Page 81: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

78

e apresentar a forma com que seus principais componentes se relacionam para, entao,

descrever as modificacoes que foram realizadas para adapta-lo ao sistema desenvolvido.

A Figura - 4.1 apresenta a arquitetura do sistema YAP, adaptada de Costa et al. (2012).

Arquitetura YAP (atual)

BibliotecasBibliotecas

Interpretador YAP

Engine CompiladorCompilador

Áreade

código

Área deCódigoYAAM

Carregamentoinicial

Requisição decompilação

Início dainterpretação

Cláusula Prologcompilada (YAAM)

Código YAAMpara interpretar

Arquitetura YAP (atual)

Interpretador YAP

Área deCódigoYAAM

Engine

Figura 4.1: Estrutura interna da versao atual do sistema YAP (adaptado de Costa etal. (2012)).

A inicializacao do sistema ocorre em uma biblioteca de alto nıvel escrita em Prolog e

sua manutencao e feita por bibliotecas escritas em C. Ambas bibliotecas sao denominadas

bibliotecas de alto nıvel e compoem o componente de mesmo nome apresentado na Figura

- 4.1. Apos o carregamento das bibliotecas de alto nıvel, a Engine carrega as demais

bibliotecas do sistema, denominadas bibliotecas de baixo nıvel, que dao suporte a threads

e aos predicados nativos de YAP.

A Engine inicializa o Compilador, que gera as sequencias de instrucoes YAAM a partir

das clausulas escritas em Prolog. Basicamente, o compilador gera codigo YAAM em tres

fases distintas. Primeiramente, ele compila a cabeca da clausula e depois o seu corpo. Na

segunda etapa ele identifica e otimiza variaveis temporarias. Por fim, ele otimiza o codigo

gerado eliminando instrucoes superfluas, similar a uma otimizacao peephole (Muchnick,

1997). Apos essas tres etapas, o compilador cria as instrucoes de indexacao e armazenada

o codigo final na Area de Codigo YAAM para serem interpretadas pelo Interpretador YAP.

Apos a geracao de codigo, o controle segue para o Interpretador YAP, que executa as

instrucoes outrora geradas pelo Compilador.

Page 82: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

79

4.2 A Nova Geracao do YAP

Para que o YAP suporte a execucao de codigo misto, sua arquitetura foi modificada para

conter novos componentes. A nova organizacao do sistema esta representada na Figura -

4.2. Assim como na organizacao anterior, a inicializacao do sistema ocorre nas bibliotecas

de alto nıvel, contudo, alem da Engine, novos componentes tambem sao inicializados.

Dentre estes novos componentes, estao as duas novas areas de codigo: a Area de Codigo

Nativo, responsavel por armazenar os tracos de execucao compilados e a Area de Codigo

Intermediario, responsavel por armazenar os tracos em construcao.

Em nıvel de implementacao, essas areas sao representadas como estruturas de dados

dinamicas, que crescem conforme novos tracos sao coletados e/ou compilados. Juntamente

a essas estruturas estao associadas informacoes de perfil, que registram as estatısticas de

execucao, como a quantidade de tracos coletados/executados e o tamanho ocupado por

cada area de memoria.

Gerentede código

Motor de Execução

Monitor

Compilador JIT

Fila de Compilação

Arquitetura YAPCódigoYAAM

CódigoInterm.

Códigonativo

Áreas de código

Áreas de código

Inicialização das áreas decódigo e do sistema em geral

Código compilado

Requisição decompilação e

código compilado

Versão correta decódigo para executar

Gerenciamento das áreasde código (busca e inserção)

Início da interpretação

Bibliotecas Engine Compilador

InterpretadorInstrumentado

InterpretadorYAP Construtor

de TraçosBlocosbásicos

Traços deexecução

Instrumentaçãodas cláusulas

ProfilerInformaçõesúteis para recompilação

Informaçõescoletadas

Módulo de

Recompilação

Bibliotecas Engine Compilador

Construtorde Traços

ProfilerCompilador JIT Gerentede código

Motor de Execução

Figura 4.2: Estrutura interna do sistema proposto.

O Motor de Execucao e responsavel por executar os programas em diversos modos

de execucao, que incluem somente interpretar, smart JIT, compilac~ao contınua e

somente compilar. Todo codigo nativo e armazenado na Area de Codigo Nativo apos

a geracao de codigo pelo Compilador JIT. Basicamente, todas as clausulas do programa

sao instrumentadas com contadores inteiros ou faixa de tempo pelo Monitor e enviadas

ao Compilador JIT quando se tornam quentes. Nesse contexto, o que define uma clausula

Page 83: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

80

quente e o fato de seu codigo de instrumentacao atingir um determinado limite, conforme

a mesma definicao de regiao quente utilizada no decorrer do texto.

O gerenciamento das clausulas, sejam elas interpretadas ou nativas, e realizado pelo

Gerente de Codigo. Este envia a versao correta da clausula para execucao (priorizando o

codigo nativo), invoca o Monitor para que o mesmo atualize o parametro de frequencia

da respectiva clausula (na forma de codigo intermediario) e envia clausulas para serem

compiladas.

O Interpretador Instrumentado, o qual e acionado somente nos modos de execucao

com codigo misto, emite os blocos basicos, que simbolizam a sequencia de instrucoes

recentemente executadas naquela clausula. O Coletor de Tracos, no perıodo em que a

clausula se torna crıtica (quando o parametro de frequencia esta prestes a alcancar um

limite) ate o momento que ela se torne quente (quando o parametro alcanca o limite),

recebe os blocos basicos emitidos pelo Interpretador Instrumentado e constroi o traco de

execucao a partir deles. Apos a construcao do traco, este e armazenado na Area de Codigo

Intermediario.

Por fim, o Modulo de Recompilacao permite que tracos outrora compilados, porem

invalidados com o tempo, sejam recompilados. Este modulo utiliza um Profiler, que coleta

o ponto do codigo a partir do qual o traco precisa ser reconstruıdo e o Coletor de Tracos,

que reconstroi o traco.

Em especıfico, as principais alteracoes realizadas na versao atual para suportar a nova

arquitetura do YAP foram:

Suporte ao novo interpretador

O Interpretador Instrumentado e identico ao Interpretador YAP do sistema atual,

exceto pela capacidade de emitir blocos basicos para o Construtor de Tracos. Este

interpretador e invocado substituindo a chamada ao primeiro interpretador quando

o modo de execucao ativo for um modo de codigo misto. Nenhuma mudanca

na estrutura de codigo do sistema atual, exceto na chamada ao interpretador,

foi necessaria, pois todos os predicados nativos7 sao executados pelo Interpretador

YAP. Portanto, por exemplo, se um predicado especıfico para mudanca do modo

de execucao (um dos predicados desenvolvidos e apresentado na Secao 4.4.4) for

invocado no inıcio do programa, o sistema apenas realiza um teste do modo de

execucao ativo para entao, invocar o interpretador correto;

7Os predicados nativos se assemelham as funcoes pre-existentes nas linguagens comumente usadas.Estes incluem tanto os predicados da versao atual do sistema, como os predicados desenvolvidos nestetrabalho.

Page 84: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

81

Suporte ao Compilador JIT e ao novo Gerente de Codigo

Todo o acesso as novas areas de codigo por parte do Gerente de Codigo e invocacao

ao Compilador JIT e feita por meio de uma estrutura associada a cada clausula

dos programas. Essa estrutura contem o valor atual do parametro de frequencia,

endereco do traco em construcao na Area de Codigo Intermediario, endereco do

codigo nativo na Area de Codigo Nativo e sub-estruturas para armazenar informacoes

utilizadas pelos predicados de depuracao (Secao 4.4.5). O acesso a essa estrutura e

feita na execucao de uma nova instrucao YAAM denominada jit handler, que e

gerada pelo Compilador (de codigo Prolog para YAAM) quando o modo de execucao

requerer acesso a devida estrutura.

Suporte ao Modulo de Recompilacao

Basicamente, a saıda do fluxo de execucao do codigo nativo para o interpretador

ocorre quando uma excecao precisa ser tratada no interpretador ou quando o traco

em execucao se tornar invalido a partir de um bloco basico. Em especıfico, o segundo

caso ocorre quando houver a necessidade de executar um bloco basico que nao foi

inserido no traco durante a sua construcao. Nesse sentido, e necessario que o sistema

identifique se a causa da saıda do fluxo de execucao ocorreu por este ultimo caso.

Para isso, dois registradores foram inseridos no sistema: K, para identificar o caso e

BADDR, para identificar o ponto exato onde o fluxo de execucao necessitou retornar

ao interpretador. Dessa forma, se o registrador K marcar verdade, o traco sera

reconstruıdo a partir do endereco marcado por BADDR.

4.3 Os Modulos da Nova Geracao do YAP

A arquitetura da nova geracao do YAP consiste de um conjunto de componentes que se

inter-relacionam de modo que as tarefas necessarias para manter e gerenciar o fluxo de

execucao entre codigo nativo e interpretado sejam bem distribuıdas. O objetivo desta

secao e apresentar uma descricao mais detalhada dos componentes do sistema, mantendo

o foco em suas especificacoes individuais.

4.3.1 Motor de Execucao

O Motor de Execucao foi projetado para executar os programas em diversos modos de

execucao. Um modo de execucao define quais componentes estarao ativos durante a

execucao de um programa, influenciando a forma que os programas serao tratados. A

vantagem de disponibilizar modos de execucao diferentes no sistema e a garantia de

Page 85: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

82

torna-lo adequado para a realizacao de diversos experimentos, o que complementa um

dos objetivos deste trabalho. Alem disso, alguns modos de execucao empregam codigo

misto que compilam unidades de codigo quentes em tempo de execucao, o que garante a

execucao de codigo mais eficiente em um estagio final de implementacao, como e o caso

de outros sistemas que utilizam esse modelo (Arnold et al., 2000; Campanoni et al., 2010;

Chang et al., 2009; Gal et al., 2009; Homescu e Suhan, 2011; Kotzmann et al., 2008;

Paleczny et al., 2001; Suganuma et al., 2004). Relativo a isso, o sistema proposto suporta

tanto a execucao de codigo misto como a execucao de codigo unico, cujas caracterısticas

estao descritas nas subsecoes que seguem.

Modos de Execucao de Codigo Misto Modos de execucao que utilizam codigo misto

nao existem na versao atual do sistemaYAP. Baseado nisso, o sistema foi modificado para

conter duas novas areas de codigo para suportar esse tipo de execucao. A primeira area

armazena os tracos de execucao do programa corrente, que sao construıdos pelo Construtor

de Tracos para que sejam compilados no momento adequado. Essa area e denominada Area

de Codigo Intermediario, que contem as clausulas quentes em representacao intermediaria

e sao enviadas como entrada para o Compilador JIT. A outra area de codigo, denominada

de Area de Codigo Nativo e a regiao de memoria onde o codigo compilado e armazenado.

Basicamente, o sistema proposto suporta dois modos mistos de execucao a saber:

smart JIT e compilac~ao contınua.

Em smart JIT, o Motor de Execucao interpreta as clausulas do programa ate que

alguma se torne crıtica. Durante a interpretacao, em vez de utilizar o interpretador padrao

do sistema, um interpretador especial, denominado Interpretador Instrumentado executa os

programas enquanto emite os blocos basicos que compoem exatamente o fluxo de execucao

corrente. Os blocos basicos emitidos so serao tratados pelo Construtor de Tracos apos a

clausula de partida do traco se tornar crıtica. Nesse contexto, se entende por clausula

crıtica, as clausulas cujos parametros de frequencia alcancarem um percentual do limite

estabelecido para esta se tornar quente.

No decorrer deste processo, quando alguma clausula se tornar quente, o traco de

execucao e enviado ao Compilador JIT, que se encarrega de gerar codigo nativo. Todo

codigo nativo e armazenado na Area de Codigo Nativo e e priorizado durante a execucao.

Em outras palavras, em smart JIT as instrucoes dos programas so sao interpretadas

(somente pelo Interpretador Instrumentado) se nao ha uma versao nativa para ser executada.

Em especial, neste modo uma unica thread e compartilhada entre o Motor de Execucao

e o Compilador JIT. Basicamente, enquanto o ambiente de execucao nao detectar clausulas

quentes, a thread e inteiramente dedicada ao Interpretador Instrumentado. Quando uma

Page 86: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

83

clausula se torna uma clausula crıtica e, depois disso, uma clausula quente, ela e enviada

para compilacao e o Motor de Execucao suspende a sua atividade ate que o codigo nativo

seja gerado. Apos esse processo, o Motor de Execucao comeca a executar codigo nativo

e permanece nessa iteracao ate que (1) a clausula seja executada ate o final e a clausula

seguinte, a qual nao foi ainda compilada, precisa ser executada ou (2) uma excecao ocorra

e a clausula em execucao precise ser executada na versao interpretada. De qualquer

forma, se o fluxo de execucao retornar ao Interpretador Instrumentado, o controle retorna

novamente para executar codigo nativo quando o traco compilado for novamente invocado.

No modo compilac~ao contınua as clausulas sao compiladas sem a necessidade de

interromper o Motor de Execucao. Alem da thread principal, que e dedicada para a

execucao de codigo, seja ele nativo ou interpretado, no mınimo outra thread adicional e

utilizada para compilar os tracos de execucao coletados. Esse modo de execucao necessita

que o sistema mantenha uma Fila de Compilacao para armazenar os tracos que necessitam

ser compilados.

Em compilac~ao contınua, a forma como as clausulas sao detectadas como crıticas (e

depois quentes) e como os tracos sao coletados acontecem da mesma forma que em smart

JIT. A unica diferenca e que sempre havera uma thread dedicada ao Motor de Execucao,

nao sendo necessaria a sua suspensao durante a geracao de codigo.

Modos de Execucao de Codigo Unico Os modos de execucao que utilizam versoes

unicas de codigo sao dois dentro do sistema: o modo somente interpretar, que e padrao

desde a primeira versao do YAP e o modo somente compilar (tambem chamado de

JIT por Plezbert e Cytron (1997). O modo somente compilar, assim como o modo

smart JIT compartilha uma unica thread entre o Motor de Execucao e o Compilador

JIT. A principal diferenca entre smart JIT e somente compilar e que neste ultimo

todas as clausulas sao compiladas imediatamente antes de serem invocadas, evitando,

por consequencia, o custo de atualizar o parametro de frequencia de clausula, o custo da

interpretacao inicial e o custo de coletar os tracos de execucao.

No modo somente compilar a execucao de codigo nativo permanece ate que alguma

excecao ocorra, pois esta deve ser tratada pelo interpretador. Isso na verdade aponta um

problema, pois forca o modo de execucao a interpretar codigo para tratar tais casos 8.

Alem disso, esse modo apresenta ainda tres desvantagens:

1. Consome muita memoria, visto que todas as clausulas sao compiladas;

8Isso implica que, mesmo neste modo, o sistema proposto continua mantendo codigo misto. Um dostrabalhos futuros propostos consiste em resolver este problema, permitindo que as excecoes sejam tratadastambem no codigo nativo.

Page 87: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

84

2. Ha maiores chances de que a execucao de alguma clausula nao compense o custo de

sua compilacao, no caso de programas compostos de clausulas pouco frequentes; e

3. O codigo nao pode ser especializado. Como toda clausula e compilada na primeira

execucao, nao ha como obter informacoes dinamicamente sobre o comportamento

da aplicacao e utiliza-las para especializar a clausula sendo compilada.

Os modos de execucao supracitados definem comportamentos diferentes do Motor de

Execucao, o qual e composto por outros tres modulos, que sao habilitados conforme a

modo de execucao ativo. Estes tres modulos sao: o Monitor, o Interpretador YAP e o

Interpretador Instrumentado.

Monitor O Monitor instrumenta as clausulas do programa com parametros de frequencia

a fim de medir a frequencia de execucao das clausulas. Em modos de execucao com codigo

misto, cada clausula e instrumentada com contadores ou fracao de tempo. Desta forma,

e papel do Monitor atualizar o parametro de frequencia antes que o Motor de Execucao

execute a primeira instrucao da referida clausula.

Interpretador YAP O Interpretador YAP executa codigo conforme a versao atual do

YAP. Ele e acionado no modo de execucao somente interpretar, embora ainda seja

ativado no modo de execucao somente compilar, quando alguma excecao precisa ser

tratada.

Interpretador Instrumentado O Interpretador Instrumentado e similar ao Interpretador

YAP, porem ele e o interpretador utilizado em modos de execucao com codigo misto. Ba-

sicamente, todo bloco basico executado e emitido ao Construtor de Tracos, que se encarrega

de construir os tracos de execucao e armazena-los na Area de Codigo Intermediario. Para

possibilitar essa tarefa o interpretador instrumentado e composto por instrucoes YAAM

estendidas, as quais executam codigo enquanto emitem blocos basicos para o Construtor

de Tracos. Nesse interpretador, toda execucao e similar ao Interpretador YAP. Isso significa

que, mesmo que os tracos tenham sido construıdos e compilados, o Interpretador YAP ainda

e utilizado para tratar excecoes geradas no codigo nativo.

4.3.2 Compilador JIT

O Compilador JIT gera codigo nativo em tempo de execucao para os tracos de execucao (no

caso de modos smart JIT e compilac~ao contınua) ou clausulas de um programa (no caso

Page 88: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

85

do modo somente compilar). Por padrao, todo codigo compilado e otimizado com um

conjunto de otimizacoes pre-definido, independente do programa em execucao. Contudo,

o sistema permite que o usuario aplique as otimizacoes (ou conjunto de otimizacoes) que

desejar.

LLVM (Low Level Virtual Machine) (Lattner e Adve, 2004) e o framework utilizado

para implementar o Compilador JIT. O atrativo deste framework e o fato deste fornecer um

conjunto de bibliotecas que podem ser utilizadas para configurar o processo de geracao

de codigo. A principal razao para utilizar LLVM neste trabalho e pela sua capacidade

de gerar codigo nativo em memoria. Alem desta razao e possıvel enumerar as seguintes:

1. A possibilidade de gerar codigo para diversas arquiteturas, o que e importante para

o sistema proposto, pois a versao original do YAP possui esta caracterıstica.

2. O mapeamento automatico dos enderecos de variaveis globais, que garante que

toda modificacao em estruturas globais realizada na execucao de codigo nativo seja

mantida na interpretacao.

3. A possibilidade de aplicar transformacoes e analise de codigo de forma arbitraria,

alem de coletar estatısticas sobre as tarefas realizadas. Em nıvel de codigo gerado,

LLVM ainda permite a selecao arbitraria do alocador de registradores, escalona-

dor de instrucoes e formas de tratar operacoes com ponto flutuante. Tudo isso

reflete uma maior flexibilidade ao sistema, possibilitando a execucao de programas

em diversas configuracoes. Em particular, este ponto e garantido pelo ambiente

experimental descrito na Secao 4.4.

Em consideracao a geracao de codigo nativo, o Compilador JIT realiza esse processo

em, basicamente, duas etapas: primeiramente, ele transforma a entrada, que consiste

de um traco de execucao, ou mesmo uma clausula completa, em codigo LLVA (que e

a representacao intermediaria de LLVM) (Adve et al., 2003) e, por fim, traduz essa

representacao para codigo nativo utilizando a LLVM, de acordo com as configuracoes

ajustadas para ela. Mesmo realizando a tarefa em dois passos, em nıvel de implementacao,

o Compilador JIT consiste de quatro fases, as quais estao representadas na Figura - 4.3 e

descritas nas proximas subsecoes.

Pre-processamento

A fase de pre-processamento transforma a estrutura de entrada dos tracos de execucao

(em modos de codigo misto) ou clausulas (no modo somente compilar) em codigo inter-

Page 89: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

86

TraduçãoTraduçãoGeraçãode Código

Geraçãode Código

Análises eTransformações

de Código

Análises eTransformações

de Código

Código LLVA Código LLVAotimizado eanalisado

Código nativoCláusula ou traço

(estrutura de entrada)

Pré-processamento Cláusula ou traço(Código intermediário)

Pré-processamento

Figura 4.3: Fases do Compilador JIT.

mediario, que serve como entrada para a proxima fase do Compilador JIT. A transformacao

e direta e nao aplica qualquer instrumentacao sobre o codigo resultante.

Traducao

A fase de traducao transforma um traco ou uma clausula inteira para codigo LLVA. Como

a caracterıstica do sistema e preservar a livre escolha do usuario, nenhuma tecnica de

transformacao (otimizacao) ou analise de codigo e aplicada nessa fase. Todo codigo, neste

caso, e traduzido para gerar codigo LLVA a partir do codigo intermediario.

Analises e Transformacoes de Codigo

Essa fase aplica analises e transformacoes de codigo sobre o codigo gerado na fase anterior,

de acordo com a configuracao padrao do sistema ou de acordo com as configuracoes

definidas pelo usuario. Em geral, suas tarefas consistem em:

• Analises e transformacoes de codigo. Por padrao e aplicado apenas as

analises e transformacoes habilitadas no nıvel de otimizacao O3. Contudo, com

o uso de predicados do ambiente experimental, o usuario pode habilitar as analises

e transformacoes de codigo que ele deseja aplicar.

• Pre-configuracao da geracao de codigo, que configura a LLVM para que

esta utilize o escalonador de instrucoes, alocador de registradores e modelos de

tratamento de ponto flutuante que o usuario deseja aplicar durante a geracao de

codigo. Por padrao, essas configuracoes sao aquelas configuradas como padrao em

LLVM.

Geracao de Codigo

A fase final do Compilador JIT e gerar codigo nativo em memoria a partir do codigo LLVA.

E tambem papel do Compilador JIT instalar o codigo gerado na Area de Codigo Nativo.

Page 90: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

87

4.3.3 Gerente de Codigo

O Gerente de Codigo gerencia as areas de codigo do sistema. Suas tarefas consistem

basicamente em:

1. Enviar a versao correta da clausula para execucao, priorizando o envio de codigo

nativo em modos de execucao com codigo misto;

2. Enviar uma clausula ou o traco de execucao coletado para compilacao.

3. Invocar o Monitor para que este atualize o parametro de frequencia da clausula.

A interacao do Gerente de Codigo com os demais componentes, bem como o seu

comportamento com uma clausula e definido pelo estado atual da clausula em questao.

Em modos de execucao com codigo misto, cada clausula do programa pode assumir,

no maximo, tres estados diferentes: interpretado, crıtico e nativo. No modo somente

interpretar, cada clausula assume somente o primeiro estado e no modo somente

compilar, cada clausula pode assumir um dos dois ultimos estados. As proximas

subsecoes descrevem o comportamento do Gerente de Codigo baseado no estado ativo

de uma clausula.

Tratamento das Clausulas Interpretadas

Para clausulas interpretadas, o Gerente de Codigo pode ter tres comportamentos distintos,

dependendo do modo de execucao ativo. Em primeiro lugar, ele e simplesmente desativado

no modo de execucao somente interpretar. Em modos de execucao com codigo misto

ele envia a correta versao da clausula para ser executada pelo Motor de Execucao e invoca

o Monitor para que ele atualize o parametro de frequencia da clausula. Por fim, no modo

somente compilar o Gerente de Codigo executa apenas algumas funcoes (enviar ao Motor

de Execucao o codigo interpretado que precisa tratar as excecoes e depois disso, retornar

ao codigo nativo).

Nenhum tratamento especial foi necessario para o primeiro caso, pois todo o codigo

YAAM esperando para ser executado sera interpretado. Em outras palavras, como o

Gerente de Codigo e desativado no modo somente interpretar, as clausulas sao tratadas

da mesma forma que a versao atual do sistema. Em segundo, quando se trata de codigo

misto, esse gerenciamento precisa ser intermediado pelo Gerente de Codigo. Como nos

modos com codigo misto o codigo nativo e priorizado, o Gerente de Codigo precisa enviar

ao Motor de Execucao a versao de codigo que deve ser executada. Por fim, no modo de

Page 91: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

88

execucao somente compilar o Gerente de Codigo tem a sua funcao reduzida, pois apenas

intermedia o retorno ao interpretador, que ainda e necessario na ocorrencia de excecoes.

Tratamento das Clausulas Crıticas

Clausulas crıticas sao clausulas que estao prestes a serem compiladas. Necessariamente,

em modos de execucao com codigo misto, uma clausula se torna crıtica quando o seu

parametro de frequencia esta prestes a atingir um limite. Quando isso ocorre, o Gerente de

Codigo passa a enviar codigo interpretado para o Motor de Execucao, mais especificamente

o Interpretador Instrumentado, para que este emita o fluxo de execucao da clausula crıtica.

Por fim, quando o parametro de frequencia efetivamente atingir um limite, o traco coletado

e enviado para o Compilador JIT.

Por outro lado, quando se trata do modo somente compilar, toda clausula e crıtica na

sua primeira invocacao. Nesse caso, o Gerente de Codigo interage apenas com o Compilador

JIT, que se encarrega de gerar codigo nativo na primeira invocacao da clausula.

Tratamento das Clausulas Nativas

Para tratar clausulas ja compiladas, o Gerente de Codigo volta a interagir com o Motor

de Execucao, independente do modo de execucao ativo. Normalmente, o Gerente de

Codigo verifica a existencia de codigo nativo e o envia para execucao, permanecendo

nesse processo ate nao encontrar mais codigo nativo para executar ou ate finalizar o

programa. Adicionalmente, a execucao de codigo nativo pode ser interrompida no caso

de ocorrer alguma excecao. Nesse caso, o Gerente de Codigo precisa direcionar o controle

para o interpretador ativo e enviar codigo nativo para execucao somente apos a excecao

ser tratada.

4.3.4 Construtor de Tracos

Em nıvel de implementacao, cada instrucao YAAM contem blocos basicos que sempre

serao executados e outros que so sao alcancados a partir de desvios condicionais. Nesse

sentido, como uma clausula e constituıda por uma sequencia bem definida de instrucoes

YAAM, o processo de eliminar os testes condicionais e reconstruir a clausula somente com

os blocos executados pode garantir que o codigo compilado seja compacto e eficiente em

termos de velocidade de execucao. Basicamente, a coleta dos blocos basicos se inicia a

partir da primeira instrucao YAAM de uma clausula e continua ate a ultima instrucao da

mesma clausula.

Page 92: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

89

Quando um traco de execucao e inicializado, a clausula de partida se torna a clausula

principal e sua primeira instrucao YAAM se torna a cabeca do traco. A partir de entao,

todo bloco basico executado e emitido pelo Interpretador Instrumentado para o Construtor de

Tracos para formar uma funcao equivalente. Nesse sentido, toda sequencia de instrucoes

YAAM e perdida, para entao formar uma sequencia de blocos basicos equivalente que

forma a referida funcao. Essa sequencia e constituıda por um conjunto composto pelos

fluxos de execucao de cada instrucao YAAM (representada por uma sequencia ordenada

de blocos basicos), iniciada com um rotulo e finalizada com um desvio incondicional para o

rotulo da proxima instrucao. Todos os rotulos sao identificados pelo endereco da instrucao

referente a ela, a fim de distinguir instrucoes de mesmo nome na mesma sequencia. Como

exemplo, a Figura - 4.4 mostra um traco gerado a partir de uma clausula composta de

tres instrucoes YAAM que nao invoca nenhuma outra clausula.

Bloco 1 da Instrução 1Bloco 2 da Instrução 1...Bloco N da instrução 1

Label_inst1_address1:

goto Label_inst2_address2:

Bloco 1 da Instrução 2Bloco 2 da Instrução 2...Bloco N da instrução 2

Label_inst2_address2:

goto Label_inst3_address3:

Bloco 1 da Instrução 3Bloco 2 da Instrução 3...Bloco N da instrução 3

Label_inst3_address3:

retorno ao interpretador

Instrução 1Instrução 2Instrução 3

Cláusula

Figura 4.4: Exemplo de um traco gerado para uma clausula com 3 instrucoes.

Idealmente, uma sequencia otima gerada pelo Construtor de Tracos deve ser constituıda

unicamente por blocos basicos executados, o que elimina qualquer necessidade de manter

instrucoes condicionais ou outro bloco basico qualquer. Contudo, a construcao desse tipo

de traco nem sempre e viavel, pois ele pode garantir a eficiencia em um programa, mas

inviabilizar a execucao de outro programa distinto9. Por essa razao, no contexto deste

trabalho, todo traco construıdo, alem de ser eficiente em termos de tempo de execucao

deve tambem (1) garantir o termino do programa e (2) uma saıda correta. Basicamente,

tais condicoes sao satisfeitas obedecendo os seguintes criterios:

9Isso foi observado durante a implementacao do Construtor de Tracos.

Page 93: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

90

1. O traco construıdo deve ser apropriado para o tipo de termo10 para o qual ele foi

construıdo;

2. Condicoes sobre a ocorrencia de excecoes, isto e, condicoes para que o fluxo de

execucao saia do codigo nativo para o interpretador, devem ser mantidas;

3. A operacao de desreferenciacao (Secao 3.2.1) deve ser concluıda com sucesso. Isto

e, o percurso na cadeia de variaveis precisa encontrar o valor correto do termo

desreferenciado;

4. Durante a chamada de clausulas, as instrucoes de indexacao devem invocar clausulas

corretas;

5. Nem todas as instrucoes condicionais podem ser ignoradas.

Em seguida, as formas de como os criterios supracitados foram implementados sao

apresentadas nas proximas subsecoes.

Tratamento dos Testes de Tipos dos Termos

Na pratica, todas as instrucoes YAAM do YAP sao genericas para todos os tipos dos

termos. Portanto, o Construtor de Tracos garante um traco eficiente eliminando testes

condicionais para esses casos. Contudo, tendo em vista que os termos em Prolog podem

mudar de tipo durante a execucao, o Construtor de Tracos ajusta os tracos construıdos

para gerar codigo correto para todos os tipos detectados durante a construcao. Dessa

forma, enquanto nenhum termo alterar o seu tipo durante a construcao de um traco que

ele pertence, o traco tera uma caracterıstica linear.

A Figura - 4.5 mostra um trecho de traco linear quando o Interpretador Instrumentado

executa uma instrucao YAAM que possui um teste condicional sobre o tipo de um

termo. Contudo, se um teste condicional anteriormente bem-sucedido chegue a falhar,

e necessario que o traco seja modificado para conter essa instrucao juntamente com os

blocos alcancados por ela. Ao final, tal modificacao, assegura o fluxo de controle exato

para os tipos daquele termo durante o tempo de execucao. Um exemplo de um traco

modificado dessa forma esta representado na Figura - 4.6.

Tratamento das Condicoes para Ocorrencia de Excecoes

No contexto do sistema YAP, se entende por excecao todo fluxo de execucao que nao

pertence a uma clausula em execucao. Na pratica, ocorrem excecoes durante o backtrack

10Um termo e para uma clausula o que um argumento e para uma funcao.

Page 94: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

91

Instrução YAAM que possui5 blocos e uma instrução paratestar o tipo de um termo

Instrução condicional paratestar tipo de um termo

B1

B2

B3 B4

B5

(a)

Trecho de um Traçocom característica linear

B1

B2

B4

B5

(b)

Figura 4.5: Trecho de um traco com caracterıstica linear em (b) que representa o fluxode execucao (marcado em vermelho) em (a).

Instrução YAAM que possui5 blocos e uma instrução paratestar o tipo de um termo

Instrução condicional paratestar tipo de um termo

B1

B2

B3 B4

B5

(a)

Traço com característicanão-linear

Instrução condicional paratestar tipo de um termo

B1

B2

B3 B4

B5

(b)

Figura 4.6: Trecho do traco representado na Figura - 4.5, apos o fluxo de execucao(marcado em vermelho) mudar apos o teste condicional.

(quando, por exemplo, um termo passado para get list nao for uma lista) e durante a

coleta de lixo (quando a pilha e a trilha precisam ser tratadas). Ambas as excecoes sao

priorizadas pelo Construtor de Tracos, o que infere um traco construıdo cujas condicoes

para ocorrencia de excecoes nao sejam ignoradas.

Em nıvel de implementacao, instrucoes condicionais que acarretam excecoes para

coleta de lixo nao sao precedidas por instrucoes de teste de tipos e, portanto, constituem

um bloco basico unico em um traco construıdo. A Figura - 4.7 mostra o trecho de um

Page 95: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

92

traco construıdo com esse tipo de bloco. Nela, o bloco basico GARBAGECOLLECTION EXCEPT

representa uma instrucao condicional que, se bem sucedida, retorna um ponteiro para o

tratamento daquela excecao ao interpretador11.

Bloco 1Bloco 2GARBAGECOLLECTION_EXCEPT...Bloco N

Label_inst_address:

Se a condição para exceção for satisfeita então:retorna ao interpretador

Figura 4.7: Trecho de um traco em uma instrucao YAAM que causa uma excecao paracoleta de lixo. Isso implica que, em codigo nativo, as condicoes para essetipo de excecao sao as mesmas para codigo interpretado. O efeito e que,mesmo executando codigo nativo, a coleta de lixo sempre ocorre em codigointerpretado.

Por outro lado, excecoes causadas por backtrack sempre sao precedidas por instrucoes

condicionais, inclusive instrucoes para testes de tipos de termos. Ao contrario das excecoes

para coleta de lixo, estas sao tratadas no proprio codigo nativo e nao devem ter as

instrucoes condicionais que a precedem ignoradas. Por exemplo, a condicao do traco

representado na Figura - 4.6 e valida desde que os blocos basicos posteriores a instrucao

condicional nao precedam uma excecao causada por backtrack. Caso contrario, o traco

precisa ser construıdo por um bloco basico mais robusto, denominado neste contexto,

de bloco elementar, um tipo de estrutura que contem instrucao(oes) condicional(is),

juntamente com os seus blocos de destino e finalizado por desvios multiplos, ativados

de acordo com o fluxo de execucao tomado. Neste contexto, se um dos blocos basicos

posteriores a instrucao condicional da Figura - 4.6 conter uma excecao para tratar

backtrack, o traco construıdo deve ser como o representado na Figura - 4.8.

Tratamento da Desreferenciacao

A desreferenciacao, explicada na Secao 3.2.1, e implementada em YAP como um laco

de repeticao para percorrer uma cadeia de ponteiros construıda durante a unificacao dos

termos. Esse laco e finalizado quando o valor do termo de partida for encontrado ou

quando for determinado que um termo ainda nao foi unificado com um valor. Antes

que esse laco seja executado, um teste condicional para verificar se o termo e variavel e

realizado e a desreferenciacao ocorre somente se esse teste tiver sucesso.

11Isso indica que tratamentos de excecao para coleta de lixo nao sao tratados em codigo nativo, mesmoem modos de execucao que compilam codigo.

Page 96: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

93

Trecho de um traço comum bloco elementar

Bloco Elementar

B1

B2

Se executou o bloco B3então:

Salta para o código quetrata backtrack

Continuanormalmente

Instrução condicional

B4

B5

B3Tratamento de backtrack

Sim Não

Figura 4.8: Trecho do traco representado na Figura - 4.6, mas usando um blocoelementar para suportar instrucoes condicionais onde um dos blocos dedestino causam backtrack.

Tracos de execucao que possibilitam instrucoes com o mesmo nome, como e no contexto

deste trabalho, possibilitam especializar a desreferenciacao pelo fato de tais instrucoes

serem distinguidas pelos seus enderecos. Tais enderecos sao como uma delimitacao de

escopo de clausula e, portanto, possuem o mesmo comportamento no que se refere ao fluxo

de execucao. Em outras palavras, se um termo e desreferenciado durante a execucao de

uma instrucao de endereco unico, a desreferenciacao sempre ocorrera quando a instrucao

neste endereco for executada novamente. Analogamente, a mesma situacao ocorrera

em casos em que a desreferenciacao nao ocorre. Portanto, considerando o esquema

de desreferenciacao implementado em YAP, a operacao de desreferenciacao pode ser

construıda dentro de um traco de uma das seguintes formas:

• Se o teste condicional executado antes do laco da desreferenciacao determinar que o

termo nao e variavel, a operacao nao e inserida no traco. Este, portanto, e o caso em

que o traco gera desempenho sobre a desreferenciacao, pois os custos da instrucao

condicional e do laco para percorrer a cadeia de ponteiros sao eliminados do traco

e, consequentemente, do codigo nativo;

• Por outro lado, se o termo for variavel, um bloco elementar contendo a operacao

de desreferenciacao sera inserida no traco. Esse bloco contem dois saltos: um deles

sera executado somente se a desreferenciacao terminar com o termo ainda sendo

variavel e, portanto, saltara para um bloco basico que trata variaveis. O segundo

salto, por sua vez, sera executado se, no final da desreferenciacao, for encontrado

Page 97: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

94

um valor nao-variavel para o termo. O destino desse salto e um bloco basico que

trata termos nao-variaveis12.

Chamada de Clausulas e Tratamento das Instrucoes de Indexacao

Na pratica, o Construtor de Tracos trata as instrucoes de chamada de clausulas com

a tecnica de integracao de clausulas, que permite substituir a chamada pelo corpo da

clausula invocada. Basicamente, toda vez que uma nova clausula for invocada seus

blocos basicos executados tambem sao inseridos no traco em construcao, como se eles

pertencessem a clausula invocadora. Alem disso, se instrucoes de indexacao tambem

forem invocadas nesse intervalo, estas tambem sao inseridas neste traco13.

Na pratica, as instrucoes de indexacao nao sao perfiladas como as demais instrucoes

e sao mantidas por inteiro dentro do traco, mesmo que todos os seus blocos basicos

nao sejam executados. Neste processo e importante notar que antes que uma clausula

invocada seja efetivamente executada, as instrucoes de indexacao precisam ser executadas

(e consequentemente coletadas) primeiro, a fim de que o sistema identifique a clausula

correta a invocar. Como na maioria dos programas a condicao de parada esta relacionada

a mudanca de tipo de algum argumento, essa condicao nao e detectada pelo Construtor de

Tracos. Portanto, a estrategia utilizada e manter uma construcao conservativa sobre as

instrucoes de indexacao, a fim de detectar esses casos, mesmo que os tais nunca tenham

ocorrido durante a construcao dos tracos.

Alem disso, as instrucoes de indexacao sao geradas durante o tempo de execucao,

sendo difıcil determinar todas as clausulas que serao invocadas apos elas, o que reforca

ainda mais a necessidade de manter uma estrategia conservativa. Por essa razao, as

instrucoes de indexacao sao construıdas como blocos elementares de multiplas instrucoes

de desvio. Cada instrucao de desvio realiza um salto para o inıcio de uma clausula-destino

daquela instrucao de indexacao, desde que esta tenha sido detectada durante a construcao

do traco. Alem dos desvios, os blocos elementares contem tambem um retorno para o

interpretador, caso a instrucao de indexacao necessite invocar uma clausula que nao tenha

sido inserida no traco.

A Figura - 4.9 mostra um exemplo de um traco que contem uma instrucao de indexacao

no seu corpo. (a) mostra uma clausula crıtica com uma instrucao YAAM de invocacao,

cujas instrucoes de indexacao podem invocar as clausulas de 2 a 6. Ao supor que o perıodo

12E importante salientar que o tratamento para termos variaveis e nao variaveis sao especıficos paracada instrucao YAAM. Alem disso, nem todas as instrucoes desreferenciam termos.

13Instrucoes de indexacao sao criadas em tempo de execucao no YAP e sao invocadas logo apos umainstrucao de chamada para invocar a clausula correta dentro de um predicado.

Page 98: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

95

Cláusula 1

B1

B2

B3

Instrução YAAM queinvoca outra cláusula

Instruções deindexação

Cláusula 2

Cláusula 6

Cláusula 3

Cláusula 4

Exemplo de traço iniciado na cláusula 1 com um blocoelementar para as instruções de indexação

B1

B2

B3

Instrução YAAM queinvoca outra cláusula

Bloco elementar paraas instruções de indexação

Se o program counter atualé igual à primeira

instrução da cláusula 2então:

retorno para ointerpretadorCláusula 2

Sim Não

(a)

(b)

Cláusula 5

Figura 4.9: Exemplo de traco que contem uma instrucao de indexacao.

em que a clausula crıtica se torna quente a unica instrucao invocada e a clausula 2, o traco

final construıdo (e compilado) e como o mostrado em (b). A instrucao de retorno inserida

no traco construıdo e para garantir a corretude do programa caso a instrucao de indexacao

invocar uma clausula diferente da clausula 2.

Tratamento das Instrucoes Condicionais

Por fim, as demais instrucoes condicionais que formam as instrucoes YAAM nao sao

eliminadas (exceto aquelas relacionadas a desreferenciacao e testes de tipos). Tais

instrucoes sao tratadas dessa forma porque os operadores para condicao sao os valores dos

termos (em vez dos tipos) e os registradores do sistema, que se caracterizam por mudar

frequentemente.

4.3.5 Modulo de Recompilacao

O Modulo de Recompilacao e o componente responsavel por recompilar um traco an-

teriormente compilado quando o fluxo de execucao e modificado no codigo nativo.

Normalmente, todo traco construıdo contem, no mınimo, um bloco elementar, que possui

multiplos destinos. Nesses blocos, e ainda inserido um destino adicional, para permitir

que o fluxo de execucao retorne ao interpretador quando for identificado que um bloco

basico qualquer ainda nao foi perfilado, isto e, inserido no traco. Alem disso, um Profiler e

utilizado para coletar as informacoes que estarao contidas nos registradores K e BADDR, que

sao informacoes uteis para que a recompilacao seja efetivamente realizada. Primeiramente,

ele detecta se o endereco de codigo onde houve retorno ocorreu por um destino de um

bloco elementar ou por uma excecao para coleta de lixo (essa informacao e armazenada em

K) e, em segundo lugar, se o retorno ocorrer a partir de um bloco elementar, ele identifica

Page 99: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

96

o endereco deste bloco para que, a partir dele, o traco seja reconstruıdo (essa informacao

e armazenada em BADDR).

Em outras palavras, ocorrendo um retorno ao interpretador por um bloco elementar, a

recompilacao e ativada, a representacao intermediaria do codigo nativo que acabou de ser

executado e recuperada da Area de Codigo Intermediario (pois esta nao e excluıda apos a

compilacao) e novos blocos executados sao inseridos nela. A partir deste ponto, quando o

interpretador alcancar a cabeca do traco, este e recompilado e invocado no lugar do traco

anterior. Ainda nesta acao, o novo traco compilado simplesmente substitui o anterior,

pois assim diminui os custos de espaco e evita a manutencao de um coletor de lixo. Por

exemplo, se na Figura - 4.9-(b) a instrucao de indexacao passar a invocar a clausula 3 em

vez da clausula 2, o fluxo de execucao retorna ao codigo interpretado e, com a recompilacao

ativa o traco e reconstruıdo e recompilado, se tornando como o traco mostrado na Figura

- 4.10 (que, depois disso, ocupara o mesmo espaco outrora ocupado pelo traco da Figura

- 4.9-(b)).

B1

B2

B3

Instrução YAAM queinvoca outra cláusula

Bloco elementar paraas instruções de indexação

Se o program counter atualé igual à primeira

instrução da cláusula 2então:

retorno para ointerpretador

Cláusula 2

Sim Não

Se o program counter atualé igual à primeira

instrução da cláusula 3então:

Cláusula 3

B3

Figura 4.10: Traco da Figura - 4.9-(b) apos ser reconstruıdo e recompilado.

4.4 Os Predicados Suportados na Nova Geracao do YAP

O ambiente experimental e uma interface que estende a arquitetura proposta a fim de

prover um conjunto de predicados que auxiliam na configuracao do sistema. Os predicados

podem configurar a forma que o ambiente de execucao se comportara enquanto os

programas sao executados, alem de poder reconfigura-lo sem a necessidade de reinicia-lo.

Um exemplo de sua aplicacao pode ser visto no seguinte codigo:

O codigo a seguir configura o ambiente de execucao antes que o programa principal

(invocado por run) comeca a executar. Nesse codigo, o predicado main e o ponto de

partida do programa e os predicados execution mode, transform passes e disable t

Page 100: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

97

1 initialization(main).

2 main :-

3 execution mode(smartjit),

4 transform passes(all),

5 run(args ),

6 disabe transform pass(all),

7 run(args ).

sao predicados do ambiente experimental, responsaveis por configurar os componentes

da arquitetura. Nesse exemplo, execution mode(smartjit) configura o sistema para

funcionar no modo de execucao smart JIT. Em seguida transform passes(all) con-

figura o Compilador JIT para que este aplique todas as transformacoes (otimizacoes)

de codigo disponıveis, durante a geracao de codigo nativo. Neste exemplo, quando

o programa for executado pela segunda vez (na linha 7), o Compilador JIT gerara

codigo nao otimizado, pois todas as transformacoes de codigo foram desabilitadas por

disabe transform pass(all) na linha anterior. Isso mostra que o benefıcio imediato

dessa interface e a praticidade ao projetar experimentos voltados na area de compilacao

JIT para Prolog.

Interface

Predicadosdo

Ambiente

Usuário

Arquivo deConfiguração

Predicadosdo

Ambiente

Gerentede código

Motor de Execução

Monitor

Compilador JIT

Fila de Compilação

Arquitetura YAPCódigoYAAM

CódigoInterm.

Códigonativo

Áreas de código

Áreas de código

Inicialização das áreas decódigo e do sistema em geral

Código compilado

Requisição decompilação e

código compilado

Versão correta decódigo para executar

Gerenciamento das áreasde código (busca e inserção)

Início da interpretação

Bibliotecas Engine Compilador

InterpretadorInstrumentado

InterpretadorYAP Construtor

de TraçosBlocosbásicos

Traços deexecução

Instrumentaçãodas cláusulas

ProfilerInformaçõesúteis para recompilação

Informaçõescoletadas

Módulo de

Recompilação

Bibliotecas Engine Compilador

Construtorde Traços

ProfilerCompilador JIT Gerentede código

Motor de Execução

Figura 4.11: Organizacao do sistema com suporte aos novos predicados.

A visao de alto nıvel do ambiente experimental esta representada na Figura - 4.11.

Nesta figura, a Interface se relaciona com um Arquivo de Configuracao, cujos valores

influenciam no comportamento de cada componente da arquitetura do sistema, mas

Page 101: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

98

que sao modificados pelos Predicados do Ambiente (acessados pelos codigos escritos pelo

Usuario).

Os Predicados do Ambiente estao subdivididos em classes de predicados de acordo com

as suas aplicacoes, a saber: predicados para analises de codigo, predicados para trans-

formacoes de codigo, predicados para geracao de codigo, predicados para configuracao

geral, predicados para depuracao e predicados para coleta de perfil de execucao. Dentre

eles, os predicados de transformacao, analise e geracao de codigo utilizam as bibliotecas

da LLVM enquanto que os demais interagem diretamente com os modulos da arquitetura.

4.4.1 Predicados para Analises de Codigo

Os predicados para analise habilitam as analises de codigo que serao realizadas pelo

Compilador JIT na fase de analises e transformacoes de codigo e toda a interacao destes

predicados com o sistema e feita com o uso das bibliotecas da LLVM. Os predicados que

integram esse conjunto sao:

analysis pass(an )

Recebe como argumento um atomo an que indica o passo de analise a ser ativado.

A analise deve estar implementada pela versao de LLVM instalada no sistema.

analysis passes(L )

Recebe como argumento uma lista L , que contem todos os passos de analise na

ordem que serao ativados.

analysis passes(all )

Recebe como argumento um atomo all, que ativa todas as analises de codigo.

all analysis passes

Tem o mesmo efeito de analysis passes(all ).

disable analysis pass(an )

Desabilita a analise de codigo an . Se for all, todas as analises sao desabilitadas.

enable analysis pass(an )

Tem o mesmo efeito de analysis pass(an ). Se for all, funcionara como all analysis passes.

enable stats

Mostra na saıda de erro padrao as estatısticas dos passos empregados durante a

geracao de codigo nativo. Assim como as analises, as estatısticas coletadas sao

Page 102: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

99

dependentes da versao de LLVM instalada no sistema. Exemplos de estatısticas

incluem a quantidade de variaveis globais do codigo, o numero de spills e o numero

de instrucoes de maquina emitidas.

disable stats

Desabilita enable stats.

enable time passes

Mostra na saıda de erro padrao os tempos dos passos empregados durante a geracao

de codigo nativo. Assim como as analises e estatısticas, os tempos coletadas sao

dependentes da versao de LLVM instalada no sistema. Exemplos destes incluem

o tempo de cada fase do compilador de LLVM e o tempo de cada fase das

transformacoes de codigo aplicadas.

disable time passes

Desabilita enable time passes.

enable checking hotclauses

Permite verificar a corretude do codigo LLVA gerado apos a fase de traducao do

Compilador JIT. Ocorrendo erro, uma mensagem e emitida e o sistema e finalizado.

Este predicado esta desabilitado, por padrao, mas e util quando o usuario suspeite

que o Compilador JIT nao esteja gerando codigo correto para um determinado

programa.

disable checking hotclauses Desabilita enable checking hotclauses.

4.4.2 Predicados para Transformacoes de Codigo

Os predicados para transformac~oes de codigo configuram a etapa de analises e

transformacoes de codigo do Compilador JIT e nao influenciam no comportamento dos

demais componentes. Assim como os predicados de analise, estes tambem utilizam

as bibliotecas de LLVM. Os predicados para transformacao sao:

transform pass(opt )

Recebe como argumento um atomo opt , que indica o passo de transformacao a ser

ativado. A transformacao deve estar implementada pela versao da LLVM instalada

no sistema. Em pratica, as transformacoes sao aplicadas a toda clausula que sera

compilada, na ordem em que sao ativadas por este predicado.

Page 103: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

100

transform passes(L )

Recebe como argumento uma lista L que contem todos os passos de transformacao

na ordem que serao ativados.

transform passes(all )

Recebe como argumento um atomo all, que ativa todas as transformacoes de codigo.

all transform passes

O mesmo que transform passes(all ).

disable transform pass(opt )

Desabilita a transformacao de codigo opt . Se for all, todas as otimizacoes sao

desabilitadas.

enable transform pass(opt )

Tem o mesmo efeito de transform pass(opt ). Se for all, funcionara como

all transform passes.

transform level(n )

Recebe como argumento um inteiro n , que indica o nıvel de otimizacao a ser

aplicado. As transformacoes de codigo que sao aplicadas em cada nıvel dependem da

versao de LLVM instalada no sistema. Atualmente, quatro nıveis de transformacao

sao suportados, a saber: O0, O1, O2 e O3.

4.4.3 Predicados para Geracao de Codigo

Os predicados para gerac~ao de codigo tambem utilizam as bibliotecas de LLVM e,

como os demais, somente alteram o comportamento do Compilador JIT.

enable excess fp precision

Ativa otimizacoes que podem aumentar a precisao de ponto flutuante. Este predi-

cado e ativado por padrao no sistema.

disable excess fp precision

Desativa enable excess fp precision.

enable unsafe fp math

Ativa otimizacoes que podem diminuir a precisao de ponto flutuante. O efeito e o

mesmo de disable excess fp precision.

Page 104: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

101

disable unsafe fp precision

Desativa enable unsafe fp precision.

soft float

Configura o Compilador JIT para que este utilize bibliotecas para tratar ponto

flutuante.

no soft float

Desativa soft float e configura o Compilador JIT para que este utilize instrucoes de

hardware equivalentes para tratar ponto flutuante. Tratamento de ponto flutuante

por hardware e o padrao no Compilador JIT.

code model(cm )

Recebe como argumento um atomo cm que indica o modelo de codigo que o

Compilador JIT utilizara. Os modelos de codigo disponıveis sao implementados em

LLVM e sao os seguintes: default , small , kernel , medium e large .

register allocator(reg )

Seleciona o alocador de registradores que sera utilizado pelo Compilador JIT. Os

disponıveis na versao da LLVM utilizada sao: basic, fast, greedy e pbqb. O alocador

padrao do sistema e o greedy.

default code model

Restaura o modelo de codigo padrao do sistema. O mesmo que code model(default ).

4.4.4 Predicados para Configuracao Geral

Os predicados para configurac~ao geral alteram o comportamento dos componentes

do sistema, exceto do Compilador JIT. A unica diferenca para esse conjunto com os demais

apresentados anteriormente e que este nao utiliza as bibliotecas de LLVM.

execution mode(i )

Altera o modo de execucao para o modo representado pelo inteiro i . Os valores

validos de i sao:

• 1 : Modifica o modo de execucao para somente interpretar;

• 2 : Modifica o modo de execucao para smart JIT;

• 3 : Modifica o modo de execucao para compilac~ao contınua; ou

• 4 : Modifica o modo de execucao para comente compilar;

Page 105: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

102

execution mode(mode name )

Altera o modo de execucao pelo modo representado pelo atomo mode name . Os

valores validos de mode name sao:

• interpreted : Modifica o modo de execucao para somente interpretar;

• smartjit : Modifica o modo de execucao para smart JIT;

• continuous : Modifica o modo de execucao para compilac~ao contınua;

• justcompiled : Modifica o modo de execucao para somente compilar;

interpreted mode

Tem o mesmo efeito de execution mode(1 ) ou execution mode(interpreted ).

smartjit mode

Tem o mesmo efeito de execution mode(2 ) ou execution mode(smartjit ).

continuous mode

Tem o mesmo efeito de execution mode(3 ) ou execution mode(continuous ).

justcompiled mode

Tem o mesmo efeito de execution mode(4 ) ou execution mode(justcompiled ).

frequencyty1(type )

Altera o parametro de frequencia representado pelo atomo type (somente em modos

smart JIT e compilac~ao contınua). Os valores validos para type sao:

• count : Configura o Monitor para utilizar contadores para medir a frequencia

das clausulas. O sistema utiliza o valor 1024 como limite padrao do contador

de frequencia para que uma clausula seja considerada quente.

• time : Configura o Monitor para utilizar tempo para medir a frequencia das

clausulas. o sistema utiliza o valor 0, 02 (segundos) como limite padrao de

tempo de frequencia para que uma clausula seja considerada quente.

frequencyty2(type, bound )

Tem o mesmo efeito de frequencyty1(type ), mas o limite maximo do contador

(ou tempo) sao configurados para bound .

frequency bound(value )

Altera o limite do parametro de frequencia ativo para o valor definido por value .

Value pode ser inteiro ou ponto flutuante, mas se para este ultimo caso o parametro

de frequencia for contador, seu valor sera truncado.

Page 106: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

103

profiling start point(f )

O ponto flutuante f define como um limite L o resultado de f × value, sendo value

o valor do parametro de frequencia ativo. Dessa forma, quando o parametro de

frequencia atinge o limite L a clausula se torna crıtica e o Construtor de Tracos

inicializa a construcao do traco do traco de execucao. A faixa de valores aceitavel

para f e o intervalo (0 .. 1), sendo 0.5 o valor padrao do sistema.

main clause ty(i )

Define como clausula principal do traco de execucao o formato da clausula repre-

sentado pelo inteiro i . A clausula principal do traco e a primeira clausula que o

compoe. Os valores validos de i sao:

• 1 : A clausula principal e a primeira que se torna crıtica;

• 2 : A clausula principal deve ser crıtica e conter, no mınimo, uma instrucao

call ou fcall. Esta e a configuracao padrao do sistema.

• 3 : A clausula principal deve ser crıtica e conter mais instrucoes que as demais

clausulas; ou

• 4 : A clausula principal deve ser crıtica e conter um historico de ocorrencia de

excecoes menor que todas as outras clausulas;

main clause ty(type )

Define como clausula principal do traco de execucao o formato da clausula repre-

sentado pelo atomo type . A clausula principal do traco e a primeira clausula que

o compoe. Os valores validos de type sao:

• justhot : A clausula principal e a primeira que se torna crıtica;

• hotandcallee : A clausula principal deve ser crıtica e conter, no mınimo, uma

instrucao call ou fcall. Esta e a configuracao padrao do sistema.

• hotandgreater : A clausula principal deve ser crıtica e conter mais instrucoes

que as demais clausulas; ou

• hotandless : A clausula principal deve ser crıtica e conter um historico de

ocorrencia de excecoes menor que todas as outras clausulas;

compilation threads(i )

Define como a quantidade de threads de compilacao o valor representado por i . O

valor padrao e a quantidade de nucleos de processamento menos 1.

Page 107: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

104

default

Restaura a configuracao padrao.

4.4.5 Predicados para Depuracao

Os predicados para depurac~ao foram projetados para uso especıfico dos desenvolvedo-

res do sistema. Todos eles emitem uma informacao na saıda de erro padrao ou arquivo,

que ajudam a identificar falhas provenientes de erros de programacao, ou mesmo verificar

a corretude do codigo a partir da saıda gerada. Os predicados para depuracao sao:

print this(cond )

Emite na saıda de erro padrao um determinado conteudo quando uma condicao

correta for satisfeita. Ambos conteudo e condicao estao relacionados com o atomo

cond , que e passado como argumento. Sempre que tal condicao tiver sucesso, o

conteudo sera emitido. Os possıveis valores de cond sao:

print basic <nome da instr> Emite na saıda de erro padrao o nome da instrucao

que esta entre ‘‘<’’ e ‘‘>’’ toda vez que esta for executada no Interpretador

YAP;

print profiled <nome da instr> Emite na saıda de erro padrao o nome da

instrucao que esta entre ‘‘<’’ e ‘‘>’’ toda vez que esta for executada no

Interpretador Instrumentado;

print native <nome da instr> Emite na saıda de erro padrao o nome da ins-

trucao que esta entre ‘‘<’’ e ‘‘>’’ toda vez que esta for executada no

codigo nativo;

print emitted BB Emite na saıda de erro padrao o bloco basico representado por

BB toda vez que este for emitido;

print put BB Emite na saıda de erro padrao o bloco basico representado por BB

toda vez que este for tratado pelo Construtor de Tracos;

print main when head Emite na saıda de erro padrao o clausula inteira quando

sua cabeca for executada, mas somente em modos de execucao que compilam

codigo;

print main on trace Emite na saıda de erro padrao a clausula principal do traco

(a primeira clausula). Ao contrario de print main when head , este predicado

habilita a emissao da clausula somente uma vez, quando esta se tornar crıtica.

Page 108: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

105

print calls Emite na saıda de erro padrao as chamadas entre clausulas (clausula

chamadora ⇒ clausula chamada);

print callsi Emite na saıda de erro padrao as chamadas entre clausulas (clausula

chamadora ⇒ indexacao ⇒ clausula chamada);

print trace on jit Emite na saıda de erro padrao o traco construıdo em forma

de blocos basicos (somente em smart JIT ou compilac~ao contınua) antes da

etapa de traducao do Compilador JIT;

print yaam on jit Emite na saıda de erro padrao a clausula em forma de ins-

trucoes YAAM (somente no modo somente compilar) antes da etapa de

traducao do Compilador JIT;

print intermediate on jit Emite na saıda de erro padrao o traco coletado (ou

clausula) como codigo intermediario antes da etapa de traducao do Compilador

JIT;

print llvabefore on jit Emite na saıda de erro padrao o traco coletado (ou

clausula) como codigo LLVA antes da etapa de analises e transformacoes de

codigo do Compilador JIT;

print llvaafter on jit Emite na saıda de erro padrao o traco coletado (ou

clausula) como codigo LLVA apos a etapa de analises e transformacoes de

codigo do Compilador JIT;

print this2(cond, n )

Tem o mesmo efeito de print this(cond ). Contudo, o conteudo sera emitido

apenas na ocorrencia de n condicoes bem sucedidas.

print this2(cond, msg )

Tem o mesmo efeito de print this( cond) , mas a string msg sera tambem emitida,

porem, apos o conteudo.

print this2(msg, cond )

Tem o mesmo efeito de print this( cond) , mas a string msg sera tambem emitida,

porem, antes do conteudo.

print this3(cond, msg, n )

Tem o mesmo efeito de print this2( cond, msg) , porem, para n condicoes bem

sucedidas.

Page 109: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

106

print this3(msg, cond, n )

Tem o mesmo efeito de print this( msg, cond) , porem, mesmo que a condicao

tenha sucesso, os valores serao impressos na quantidade de vezes representada por

n .

print this3(msg1, cond, msg2 )

Emite na saıda de erro padrao um determinado conteudo quando uma condicao

correta for satisfeita. Ambos conteudo e condicao estao relacionados com o atomo

cond , que e passado como argumento. As strings msg1 e msg2 tambem serao

emitidas: msg1 estara antes e msg2 estara depois do conteudo. Sempre que a

condicao tiver sucesso, o conteudo sera emitido.

print this4(msg1, cond, msg2, n )

Tem o mesmo efeito de print this( msg1, cond, msg2) , porem, mesmo que a

condicao tenha sucesso, os valores serao emitidos na quantidade de vezes represen-

tada por n .

no print this(cond ) Desabilita print this(cond ) (bem como as suas variacoes) re-

lativo a cond .

print me(cond, msg )

Emite na saıda de erro padrao a mensagem msg sempre que a condicao cond for

satisfeita durante o tempo de execucao. Os possıveis valores de cond sao:

interpreted backtrack Emite na saıda de erro padrao msg quando ocorre back-

tracking em codigo interpretado;

native backtrack Emite na saıda de erro padrao msg quando ocorre backtracking

em codigo nativo;

treati heap Emite na saıda de erro padrao msg quando o sistema precisa tratar

a pilha por alguma excecao ocorrida em codigo interpretado;

treatn heap Emite na saıda de erro padrao msg quando o sistema precisa tratar

a pilha por alguma excecao ocorrida em codigo nativo;

treati trail Emite na saıda de erro padrao msg quando o sistema precisa tratar

a trilha por alguma excecao ocorrida em codigo interpretado;

treatn trail Emite na saıda de erro padrao msg quando o sistema precisa tratar

a trilha por alguma excecao ocorrida em codigo nativo;

Page 110: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

107

criticals Emite na saıda de erro padrao msg toda vez que uma clausula se tornar

crıtica;

at compilation Emite na saıda de erro padrao msg no momento em que um traco

(ou clausula) for compilado;

at recompilation Emite na saıda de erro padrao msg no momento em que um

traco for recompilado;

nativerun init Emite na saıda de erro padrao msg quando o sistema comecar a

executar qualquer codigo nativo;

nativerun exit by exception Emite na saıda de erro padrao msg quando a

execucao de codigo nativo retornar ao interpretador pela ocorrencia de alguma

excecao;

nativerun exit by fail Emite na saıda de erro padrao msg quando a execucao

de codigo nativo retornar ao interpretador para executar um bloco ainda nao

perfilado;

nativerun exit Emite na saıda de erro padrao msg quando a execucao de codigo

nativo retornar ao interpretador (por qualquer razao);

no print me(cond )

Desabilita print me(cond, msg ) relativo a condicao cond .

copy to file(filename )

Copia para o arquivo filename toda saıda emitida na saıda de erro padrao.

emit to file(filename )

Deixa de emitir erro na saıda de erro padrao para faze-lo no arquivo filename .

nofile

Toda saıda e emitida para a saıda de erro padrao e todo arquivo aberto (por

copy to file(filename ) ou por emit to file(filename )) sao fechados.

print predicate msgs(L )

Recebe como argumento uma lista L que aceita, no maximo, tres atomos success ,

warning e error , que indica quais tipos de mensagens os predicados podem emitir.

Por exemplo, print predicates msgs(success ) permitira que todos os predicados

emitam uma mensagem quando estes tiverem sucesso (retornarem verdade).

print all predicate msgs

Habilita a emissao de todos os tipos de mensagens por parte dos predicados.

Page 111: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

108

print success predicate msgs

Habilita a emissao de mensagens de sucesso por parte dos predicados. Por padrao,

mensagens de sucesso nao sao emitidas.

print warning predicate msgs

Habilita a emissao de mensagens de advertencia por parte dos predicados. Por

padrao, mensagens de advertencia sempre sao emitidas.

print error predicate msgs

Habilita a emissao de mensagens de erro por parte dos predicados. Por padrao,

mensagens de erro sempre sao emitidas.

no print predicate msgs(type )

Recebe como argumento um atomo type que pode ser success , warning e error ,

que desabilita os respectivos predicados para emissao de mensagens. Pode tambem

aceitar o atomo all , que desabilita todas as mensagens.

print default predicate msgs

Restaura a configuracao padrao de emissao de mensagens: mensagens de sucesso

nao sao emitidas, mas mensagens de advertencia e erro sao emitidas.

exit on warning

Finaliza o sistema quando uma condicao de advertencia ocorre, mas mensagens de

advertencia nao sao emitidas. Por padrao, este predicado e desabilitado.

no exit on warning

Desabilita exit on warning.

disable on warning

Nao permite alteracoes pelos predicados quando ocorrem condicoes de advertencia,

mas a execucao continua normalmente. Por padrao, este predicado e desabilitado.

enable on warning

Desabilita disable on warning. A execucao continua normalmente.

exit on error

Finaliza o sistema quando uma condicao de erro ocorre. Alem disso, mensagens de

erro ainda sao emitidas. Por padrao, este predicado e desabilitado.

Page 112: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

109

no exit on error

Desabilita exit on error. Mensagens de erro ainda sao emitidas, mas o sistema

nao e finalizado.

nodebug

Desativa todo predicado de depuracao ativo.

4.4.6 Predicados para Coleta de Perfil de Execucao

Os predicados para coleta de perfil de execuc~ao sao predicados uteis para habili-

tar e mostrar os perfis de execucao dos programas. Nesse contexto, se entende por perfis de

execucao, os valores relacionados ao tempo de compilacao e construcao dos tracos, tempo

de interpretacao e tamanho de codigo. Atualmente, existem apenas dois predicados dentro

deste grupo, que habilitam a coleta de informacoes que tem alguma relacao com a Area

de Codigo Intermediario ou a Area de Codigo Nativo. Esses predicados sao:

statistics jit

Emite na saıda de erro padrao estatısticas a respeito do ambiente de execucao. Esse

predicado e habilitado somente em modos de execucao que compilam codigo e as

informacoes emitidas incluem: tempo total para construir os tracos de execucao (se

o modo de execucao ativo permitir), tempo total para compilar todos os tracos de

execucao, tempo de execucao dos tracos, tamanho da Area de Codigo Intermediario

e tamanho da Area de Codigo Nativo.

detailed statistics jit

Emite na saıda de erro padrao informacoes mais detalhadas a respeito do ambiente

de execucao. As informacoes incluem as mesmas apresentadas por statistics jit,

incluindo: tempo para construir, compilar e executar cada traco de execucao, tempo

tratando excecoes no interpretador (excecoes causadas no codigo nativo), tamanho

de cada traco compilado e representado em codigo intermediario, quantidade de

invocacao de cada traco e proporcao de excecoes causadas em cada traco.

4.5 Consideracoes Finais

Este capıtulo apresentou em detalhes a nova arquitetura proposta para o YAP. Como

observado, a nova arquitetura e uma extensao da arquitetura existente, com acrescimo de

novos modulos e novas areas de codigo. De fato, a principal contribuicao dessa proposta

e que o novo ambiente de execucao e capaz de gerar codigo nativo em tempo de execucao

Page 113: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

110

para os tracos mais frequentes dos programas. Outra importante contribuicao e a interface

do ambiente experimental, que possibilita configurar o comportamento do sistema por

meio dos novos predicados desenvolvidos.

Para validar a arquitetura proposta, o proximo capıtulo apresenta a avaliacao do

sistema desenvolvido. Os resultados que serao apresentados demonstram que a coleta

de tracos e uma boa estrategia desde que estes sejam bem construıdos. O mesmo sera

demonstrado para os predicados do ambiente experimental, que mostraram ser uteis para

coletar as informacoes de perfis de execucao.

Page 114: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

111

5

Avaliacao Experimental

No decorrer deste trabalho, uma nova arquitetura para o YAP foi desenvolvida como

uma extensao da sua arquitetura atual. Os principais componentes sao o Compilador JIT,

o Construtor de Tracos e o Interpretador Instrumentado. Basicamente, a interacao entre

estes componentes definem uma das contribuicoes deste trabalho, que e a construcao,

compilacao e execucao de tracos de execucao. Este capıtulo apresenta uma avaliacao do

sistema desenvolvido, em torno do impacto dos principais modulos e do desempenho de

execucao alcancado. A avaliacao esta dividida em duas partes:

• Avaliacao de desempenho: esta avaliacao tem por objetivo apresentar os

resultados quanto ao desempenho relativo a execucao e a criacao dos tracos. Esta

avaliacao foi dividida em duas partes: a primeira parte apresenta o impacto do

Interpretador Instrumentado e a segunda parte apresenta os resultados de desempenho

dos diferentes modos de execucao.

• Avaliacao da estrategia de construcao de tracos : esta avaliacao apresenta

os resultados sobre a eficiencia do Construtor de Tracos.

Em todas as avaliacoes os resultados foram obtidos em um Intel(R) Core(TM) i7-3770

CPU 3.40GHz com 4GB de memoria, executando sistema operacional Linux com kernel

versao 3.5.0. Nenhuma ferramenta externa foi utilizada para coletar os resultados e apenas

os predicados nativos do YAP foram utilizados. A Secao 5.1 apresenta a metodologia

considerada em todas as fases de avaliacao supracitadas. Em seguida, a Secao 5.2

apresenta o impacto do Interpretador Instrumentado sobre o ambiente de execucao. A Secao

5.3 apresenta o desempenho dos diferentes modos de execucao. A Secao 5.4 apresenta

Page 115: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

112

questoes de desempenho quanto a eficiencia do Construtor de Tracos e, por fim, o capıtulo

finaliza com algumas consideracoes na Secao 5.5.

5.1 Metodologia

Para avaliar o sistema de acordo com os criterios definidos no inıcio deste capıtulo

foram utilizados 18 programas-teste com aplicacoes distintas, sendo estas divididas em

dois diferentes grupos. O primeiro grupo consiste de nucleos de programas completos

habitualmente usados pela comunidade cientıfica de Prolog. O segundo grupo consiste

de um conjunto de programas do benchmark shootout (Shootout, ????).

Uma breve descricao dos programas-teste do primeiro grupo e apresentada na Tabela

Tabela - 5.1 e do segundo grupo na Tabela Tabela - 5.2.

Tabela 5.1: Programas-teste habitualmente utilizados pela comunidade cientıfica deProlog.

Numero de

Programa Predicados Descricao Entrada

Insere uma lista de N elementos noappend 1

inıcio de outra.10000000

Torre de hanoi contendo 3 pinos ehanoi 1

N discos.24 discos

nreverse 2 Inverte uma lista com N elementos. 100000Ordena uma lista de N elementos

quicksort 2pelo metodo quick-sort.

8000000

Funcao recursiva controlada portak 1

operacoes aritmeticas simples.57, 21, 36

Quebra-cabeca logico baseado emzebra 5 restricoes, resolvido por busca Nao ha entrada

exaustiva.

Visto que um dos objetivos do trabalho e fornecer um conjunto de predicados que

possibilitam realizar experimentos voltados a compilacao JIT para Prolog, nenhuma

avaliacao apresentada nas proximas secoes utilizou ferramentas externas para coletar os

perfis de execucao. Isso foi proposital a fim de mostrar que os predicados propostos sao

suficientes para realizar essa tarefa. As configuracoes do sistema e os predicados utilizados

sao apresentados no inıcio de cada secao que prossegue.

Page 116: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

113

Tabela 5.2: Programas-teste do benchmark shootout.Numero de

Programa Predicados Descricao Entrada

Aloca e desaloca varias arvoresbinary trees 6

binarias.19

Realiza todas as permutacoes defannkuch 11

um conjunto de tamanho N.11

Gera uma sequencia aleatoria defasta 13

DNAs.8000000

Conta todas as sequencias de Knucleotıdeos. O valor de K varia Saıda de

k nucleotide 19entre 3, 4, 6, 12 e 18 durante a fasta 100000execucao.Gera um conjunto de Mandelbrot

mandelbrot 5e escreve um bitmap portatil.

1800

Realiza uma simulacao com Nn-body 9

planetas jovianos.1800000

Conta a quantidade de numerosnsieve 9 primos de 2 a M usando o 6

algoritmo Crivo de Erastotenes.Conta a quantidade de numerosprimos de 2 a M usando oalgoritmo Crivo de Erastotenes.

nsieve bits 9A diferenca para o algoritmo

12

anterior e que este emprega vetorde bits.Realiza uma serie de somas

partial sum 3 parciais que necessitam de 18000000precisao dupla.Calcula os N primeiros dıgitos de

pidigits 7Pi.

18000000

Calcula tres funcoes numericasrecursive 4 simples: ackermann, fibonnaci 12

e tak.Encontra um valor proprio usando

spectral norm 13power method.

1000

5.2 Impacto do Interpretador Instrumentado

O Interpretador Instrumentado compoe a arquitetura do sistema para executar codigo em

modos de execucao com codigo misto, enquanto ainda emite blocos basicos para serem

tratados pelo Construtor de Tracos. Essa emissao e contınua mesmo antes de qualquer

Page 117: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

114

clausula se tornar crıtica e se mantem mesmo na ocorrencia de excecoes dentro do

codigo nativo (pois estas sao tratadas neste mesmo interpretador). O objetivo desta

secao, portanto, e avaliar o Interpretador Instrumentado e o seu impacto no ambiente

de execucao em comparacao ao Interpretador YAP. Os resultados obtidos servirao para

justificar algumas questoes de desempenho discutidas nas proximas secoes.

Para esta analise, as seguintes situacoes foram consideradas:

• Cada programa foi executado 10 vezes com o Interpretador YAP e com o Interpretador

Instrumentado;

• O Compilador JIT foi desativado;

• Nenhum predicado apresentado na Secao 4.4 foi utilizado;

• O tempo de execucao para todos os programas foram coletados pelo predicado

statistics, que esta presente na versao atual do YAP e que e util para mostrar

perfis de execucao do sistema quando este nao invoca o Compilador JIT.

• Os resultados foram apresentados em grafico, em termos da aceleracao (ou desace-

leracao) obtida. A Formula 5.1 mostra como esta grandeza foi calculada no contexto

deste trabalho.

Acelerac~ao =Tempo Interpretador YAP

Tempo Interpretador Instrumentado(5.1)

Os resultados obtidos estao representados na Figura - 5.1. Nesta figura, cada barra

representa a aceleracao dos programas executados, de acordo com a Formula 5.1. Alem

disso, para fins de comparacao, a figura apresenta tambem os tempos de execucao (em

segundos) dos programas executados pelo Interpretador YAP.

A Figura - 5.1 mostra que, para todos os programas, o valor da aceleracao foi menor

que 1, o que aponta desaceleracao por parte do Interpretador Instrumentado ou, em outras

palavras, uma execucao mais lenta de codigo. Em valores, este e, em media, 11, 31 vezes

mais lento que o Interpretador YAP, com perdas de desempenho variando de 1, 018 vezes

para o programa zebra, a quase 36 vezes para o programa mandelbrot.

A principal razao para o alto custo do Interpretador Instrumentado e a sua funcao de

emitir blocos basicos, que e uma tarefa contınua durante toda a execucao. Os blocos

emitidos sao tratados pelo Construtor de Tracos (apos a clausula-cabeca do traco se tornar

crıtica) para que, apos um tempo, os tracos compilados sejam executados a fim de alcancar

ganhos de desempenho em modos de execucao com codigo misto. Por um lado, os valores

Page 118: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

115

appe

ndhan

oi

nreve

rse

quick

sort tak

zebr

a

binar

y tre

es

fannku

chfa

sta

k nucle

otide

mande

lbrot

n-bod

y

nsieve

nsieve

bits

parti

al su

m

pidigi

ts

recu

rsive

spec

tral n

orm

0

0.1

0.2

0.3

0.4

0.5

0.6

0.7

0.8

0.9

1Aceleração do InterpretadorInstrumentado

append -- 70,702hanoi -- 53,635nreverse -- 225,458quicksort -- 85,453tak -- 68,105zebra -- 0,082binary trees -- 114,158fannkuch -- 402,198fasta -- 76,965k nucleotide -- 153,574mandelbrot -- 86,382n-body -- 68,630nsieve -- 238,316nsieve bits -- 95,491partial sum -- 73,298pidigits -- 72,654recursive -- 171,146spectral norm -- 173,259

Tempo de execução com o interpretador YAP (s)

Figura 5.1: Impacto do Interpretador Instrumentado no ambiente de execucao. Quantomenor a barra, maior a desaceleracao.

de desaceleracao observados permitem concluir que, nestes modos de execucao, o essencial

e manter o fluxo de execucao em codigo nativo pelo maior tempo possıvel, de modo que o

custo anterior a compilacao seja amortizado. Por outro lado, programas que sao incapazes

de gerar tracos que mapeiem um escopo consideravel do codigo para manter esse tipo de

comportamento possuem grandes chances de obterem perdas de desempenho devido ao

Interpretador Instrumentado.

Portanto, neste contexto, a modificacao do interpretador para que este emita blocos

basicos somente no momento da construcao dos tracos seria a estrategia ideal para

amenizar os custos relacionados a esse problema. Basicamente, o comportamento do

Interpretador Instrumentado seria guiado pelo estado da clausula que ele esta prestes a

executar, similar ao comportamento do Gerente de Codigo. Em primeiro lugar, quando

nenhuma clausula esta em estado crıtico, o interpretador executaria instrucoes nao

instrumentadas e os blocos basicos so seriam emitidos para clausulas que, com o passar do

tempo, se tornassem crıticas. Nesse momento, em vez de uma instrucao YAAM padrao,

a sua contraparte instrumentada seria executada. Por fim, o comportamento retornaria

a configuracao padrao apos a geracao de codigo nativo, garantindo que qualquer excecao

seja executada sem o custo adicional de emitir blocos basicos.

5.3 Desempenho dos Diferentes Modos de Execucao

No decorrer deste texto foi apresentado uma arquitetura para a nova geracao do YAP com

suporte a construcao e geracao de codigo de tracos de execucao com o proposito de alcancar

um dos objetivos deste trabalho, que visa obter uma execucao eficiente dos programas

frente a versao atual do sistema. Esta secao apresenta analises de desempenho dos

Page 119: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

116

programas-teste selecionados e discussoes sobre os resultados coletados para cada modo

de execucao implementado. Para essa secao, os seguintes parametros foram considerados:

• Todos os programas-teste foram executados 10 vezes nos modos somente interpretar,

smart JIT, compilac~ao contınua e somente compilar.

• Considerando os modos smart JIT e compilac~ao contınua, os seguintes parametros

foram considerados:

– Ambos foram executados com a recompilacao ativada e desativada, com os

programas-teste executados 10 vezes para cada configuracao;

– O mecanismo para selecao da clausula principal de um traco foi definido pelo

predicado main clause ty, no seu valor padrao.

– O parametro de frequencia foi contador, com um limite de 1024.

– O valor do contador ajustado para detectar uma clausula como crıtica foi a

metade do limite estabelecido, isto e, 512.

– Os predicados para analise, transformacao e geracao de codigo nao foram

utilizados. Logo, a configuracao do Compilador JIT e a configuracao padrao

do sistema.

• Nenhum predicado para depuracao foi utilizado.

• Os perfis de execucao foram coletados pelo predicado detailed statistics jit.

Assim como na analise do Interpretador Instrumentado, os graficos apresentados nas

proximas secoes foram construıdos com base nos valores de aceleracao/desaceleracao

calculados pela Formula 5.1, adaptada para medir o impacto dos modos de execucao

sobre o modo somente interpretar. A partir da aceleracao, foi calculada a melhoria

dos programas (Formula 5.2), cujos valores foram apenas mencionados no decorrer do

texto.

Melhoria = (Acelerac~ao - 1)× 100 (5.2)

A analise dos resultados para essa fase da avaliacao esta dividida para cada modo de

execucao nas proximas subsecoes.

Page 120: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

117

5.3.1 O Desempenho de Smart JIT

Os resultados obtidos no modo smart JIT sobre o modo somente interpretar estao

representados na Figura - 5.2. Nesta figura, o desempenho de cada programa e apresentado

em duas barras. Da esquerda para direita, a primeira barra representa o desempenho

no modo smart JIT com recompilacao e a segunda barra representa o desempenho no

modo smart JIT sem recompilacao. Cada barra indica a aceleracao obtida pelo programa

executado no seu respectivo modo, em que valores menores que 1 indicam programas com

um desempenho pior que o modo somente interpretar. Adicionalmente, a Figura - 5.3

indica o percentual em que o fluxo de execucao se manteve no Interpretador Instrumentado,

no Construtor de Tracos, no Compilador JIT e na execucao do codigo nativo.

appe

ndhan

oi

nreve

rse

quick

sort tak

zebr

a

binar

y tre

es

fannku

chfa

sta

k nucle

otide

mande

lbrot

n-bod

y

nsieve

nsieve

bits

parti

al su

m

pidigi

ts

recu

rsive

spec

tral n

orm

00.20.40.60.8

11.21.41.61.8

22.22.4

Com recompilação

Sem recompilação

Figura 5.2: Aceleracao/desaceleracao dos programas teste no modo smart JIT (com esem recompilacao) sobre o modo somente interpretar. Valores menoresque 1 indicam desaceleracao.

appe

ndhan

oi

nreve

rse

quick

sort tak

zebr

a

binar

y tre

es

fannku

chfa

sta

k nucle

otide

mande

lbrot

n-bod

y

nsieve

nsieve

bits

parti

al su

m

pidigi

ts

recu

rsive

spec

tral n

orm

0%10%20%30%40%50%60%70%80%90%

100%

Interpretador InstrumentadoConstrutor de TraçosCompilador JITCódigo Nativo

Figura 5.3: Percentuais do fluxo de execucao nos componentes ativos no modo smart

JIT.

Em primeiro lugar, e possıvel perceber que, para a maioria dos programas, os custos

do Construtor de Tracos e do Compilador JIT sao mınimos, ou ate mesmo desprezıveis,

Page 121: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

118

nao ocasionando perda de desempenho. Relativo a esses dados, em media, o tempo

para construir os tracos variou na proporcao de 0, 0001% (k nucleotide) a 0, 013%

(fasta) do tempo total de execucao quando a recompilacao foi desativada. Com a

recompilacao ativa essa proporcao foi de 0, 006% (quicksort, tak e fannkuch) a 25, 6%

(k nucleotide). Nessa ultima configuracao, a razao media do tempo construcao de

tracos pelo tempo de execucao total foi de 1, 5% para todos os programas, mas a alta

razao relacionada ao programa k nucleotide e devido a alta concentracao de execucao

em codigo interpretado. Como a recompilacao ainda permanece ativa, parte desse fluxo

precisa garantir a reconstrucao de tracos outrora construıdos. Com excecao do programa

k nucleotide, o maior tempo de construcao de tracos ficou para o programa spectral

norm, que ocupou 0, 5% do tempo de execucao.

Relacionado ao Compilador JIT, o tempo medio de sua execucao no modo sem re-

compilar foi de apenas 0, 105 segundos. Para este, a proporcao variou de 0, 001% (k

nucleotide) a 0, 2% (pidigits). Como esperado, o tempo deste componente foi um

pouco maior com a recompilacao ativada, tendo media de 0, 746 segundos, variando

na razao de 0, 005% (nreverse) a 0, 6% (mandelbrot) do tempo total de execucao.

Tais valores mostram que, embora o Compilador JIT seja invocado diversas vezes para

recompilacao, o efeito de sua execucao e pouco significativo no impacto de desempenho.

Por essa razao, e valido dizer que, pela estrategia de construcao de tracos im-

plementada neste trabalho, o ideal e manter a recompilacao sempre ativa. Embora

nessa configuracao, programas como hanoi, fasta, nsieve, partial sum, recursive

e spectral norm tenham sido executados por mais tempo que a configuracao sem

recompilacao, o desempenho se manteve compatıvel em geral. Dentre tais programas,

hanoi foi o que obteve maior diferenca entre ambas as configuracoes, mas com uma

diferenca de apenas 4, 8% (o programa zebra nao entra nesta comparacao porque nao foi

gerado codigo nativo em sua execucao). Por outro lado, programas cujos desempenhos

foram piores na configuracao sem recompilacao, a diferenca foi maior. Dentre eles, os

programas k nucleotide e mandelbrot chegaram a ser, respectivamente, 540% e 1000%

mais lentos do que a execucao com recompilacao.

Novamente, com base nos resultados coletados, estes demonstram que a maior parte

da execucao de todos os programas se concentra na interpretacao (pelo Interpretador YAP)

e/ou na execucao de codigo nativo. Levando em consideracao a eficiencia do sistema

de compilacao no modo com recompilacao (cujo desempenho, em geral foi melhor), 13

dentre os 18 programas-teste obtiveram um ganho de desempenho quando executados no

modo smart JIT, sao eles: nreverse, quicksort, tak, binary trees, fannkuch, fasta,

mandelbrot, n-body, nsieve, nsieve bits, partial sum, recursive e spectral norm.

Page 122: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

119

Analisando a Figura - 5.2, e possıvel verificar que o modo smart JIT com recompilacao

obteve o melhor ganho de desempenho sobre o modo somente interpretar para o

programa mandelbrot, sendo este ganho de 134, 4%. No outro extremo esta o programa

tak, que proporcionou apenas um ganho de 1, 006%. Entre esta faixa de desempenho

se encontra, portanto, os outros nove programas, cujos ganhos de desempenho foram:

50, 5% para n-body, 26, 7% para fasta, 22, 4% para nreverse, 19, 6% para fannkuch,

18, 4% para partial sum, 14, 1% para nsieve bits, 13, 9% para recursive, 10, 8% para

spectral norm, 6, 5% para binary trees, 5, 5% para quicksort e 3, 6% para nsieve.

O que pode ser notado de imediato na Figura - 5.3 e que, para a maioria dos programas

com o tempo de execucao reduzido pelo modo smart JIT (nesse caso, com recompilacao

ativa), o fluxo de execucao se manteve a maior parte na execucao de codigo nativo. Isso,

portanto, comprova que a principal razao para o ganho de desempenho obtido neste

modo e a alta proporcao de tempo que o fluxo permanece executando codigo nativo. Na

pratica, quanto maior e a proporcao de tempo gasto em codigo nativo, maior e o ganho

de desempenho. Isso e uma vantagem, porque minimiza o custo inerente do Interpretador

Instrumentado. Por outro lado, isso aponta um problema porque requer tecnicas mais

sofisticadas para detectar e construir tracos de execucao cada vez melhores.

Embora a maioria dos programas avaliados provessem tracos de execucao, um dos

fatores para a alta concentracao do tempo de execucao em codigo nativo nao se deve,

necessariamente, a construcao de tracos em si, mas ao mecanismo de deteccao de clausula

principal do traco. De fato, iniciar a construcao de um traco a partir de uma clausula

que esta no final de uma cadeia de chamadas proporciona um traco reduzido porque

somente as clausulas invocadas apos a clausula inicial serao inseridas no corpo do traco.

Por outro lado, se o mecanismo de deteccao detectar clausulas no inıcio de uma cadeia

de chamadas, o traco construıdo sera maior e, consequentemente, isso resultara em fluxos

de execucao mantidos em codigo nativo por mais tempo. Embora esse mecanismo tenha

detectado tracos otimos para alguns programas-teste, ele e ainda muito instavel, pois foi

registrada alta degradacao de desempenho em alguns programas, como k nucleotide e

mandelbrot. A recompilacao surgiu como uma forma de amenizar essa instabildade, o

que realmente mostrou ser eficiente, porem nao para todos casos.

Alem disso, existe outro problema que impede a manutencao do fluxo de execucao em

codigo nativo, mas este sera mencionado na proxima secao, que avalia a efetividade do

Construtor de Tracos.

Em relacao aos programas para os quais smart JIT resultou em perdas de desem-

penho, a media de desaceleracao foi de 55, 07 vezes na execucao sem recompilacao e de

14, 247 vezes com recompilacao. Na primeira configuracao, a desaceleracao variou de

Page 123: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

120

1, 002 (append) a 4, 691 vezes (mandelbrot), embora o alto valor da media tenha sido

decorrente da desaceleracao proveniente do programa k nucleotide, que chegou a ser

429, 638 vezes mais lento. Por outro lado, a desaceleracao da maioria dos programas com

a recompilacao ativada variou de apenas 1, 001 (append) a 1, 047 vezes (hanoi), mas com

um salto de desaceleracao para 67, 092 vezes tambem para o programa k nucleotide.

Analisando, portanto, mais uma vez a Figura - 5.2, e possıvel observar que a maioria

dos programas que obtiveram queda no desempenho foi devido a alta concentracao

do fluxo de execucao no Interpretador Instrumentado. Os programas pidigits (com e

sem recompilacao) e nsieve bits (sem recompilacao) tambem apresentaram queda no

desempenho, mesmo concentrando grande parte da execucao em codigo nativo, porem

este fato pode ser explicado pela falta de otimizacoes dos tracos construıdos para o

programa, que, como foi mostrado na Secao 4.3.4, nao sao aplicaveis a todos os casos.

Adicionalmente, quedas de desempenho podem tambem estar relacionadas as excecoes

trataveis em codigo interpretado, que se trata da manipulacao das regioes de memoria do

YAP (heap, pilha local e trilha), mas as causas para este caso serao apresentadas somente

na Secao 5.4, que avalia o Construtor de Tracos.

Por fim, exceto os programas pidigits e nsieve bits, para todos os programas

que apresentaram queda de desempenho, o fluxo de execucao permaneceu a maior parte

no Interpretador Instrumentado. Isso da evidencias de tracos superficiais construıdos,

isto e, tracos que nao puderam mapear muitas clausulas dentro de uma cadeia de

invocacoes. A consequencia imediata e justamente a concentracao de execucao dentro

de um interpretador lento (conforme discutido na Secao 5.2).

Mapear a maior quantidade possıvel de clausulas dentro de um unico traco de execucao

nao e uma tarefa trivial. Tracos cujo fluxo de execucao sao mantidos na maior parte do

tempo sao difıceis de encontrar, pois o comportamento da execucao e dependente de

diversas informacoes, a saber: do tamanho da entrada, dos tipos das variaveis Prolog

e nas possibilidades de ocorrer excecoes. Uma forma viavel de investigar esse problema

seria empregar analise global (Mellish, 1981) para detectar clausulas que estao presentes

no inıcio de uma cadeia de invocacao, para entao criar tracos de execucao a partir delas

(onde o traco construıdo sera maior). Outra alternativa e empregar online profiling

para realizar a mesma tarefa. Basicamente, online profiling pode investigar a cadeia

de invocacoes durante a interpretacao enquanto nenhuma clausula se torna crıtica. Essa

ultima estrategia e mais simples de implementar, mas sua aplicacao e inviavel no modo

somente compilar. Ambas as implementacoes sao viaveis no sistema proposto, porque o

custo do Construtor de Tracos e desprezıvel ao tempo de execucao total, portanto e valido

que qualquer esforco seja aplicado, mesmo que algum custo adicional seja gerado.

Page 124: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

121

Adicionalmente, outra estrategia consiste em modificar o interpretador utilizado em

modos de execucao com codigo misto, para que este emita blocos basicos somente quando

for necessario construir um traco. A ideia desse novo interpretador ja foi apresentada

na Secao 5.2. Na verdade, isso nao construiria tracos melhores, mas o fato de a

execucao manter mais tempo interpretando que executando codigo nativo nao prejudicaria

o desempenho do sistema pela emissao desnecessaria de blocos basicos.

5.3.2 O Desempenho de Compilacao Contınua

Os resultados obtidos no modo compilac~ao contınua sobre o modo somente interpretar

estao representados na Figura - 5.4. Nesta figura, o desempenho de cada programa

tambem e apresentado em duas barras. Da esquerda para direita, a primeira barra

representa o desempenho no modo compilac~ao contınua com recompilacao e a segunda

barra representa o desempenho no modo compilac~ao contınua sem recompilacao. Alem

disso, assim como na Figura - 5.2, as barras representam a aceleracao (ou desaceleracao) do

respectivos modos sobre o modo somente interpretar. Adicionalmente, a Figura - 5.5

indica o percentual em que o fluxo de execucao se manteve no Interpretador Instrumentado,

no Construtor de Tracos e na execucao do codigo nativo, sem considerar o tempo gasto no

Compilador JIT, devido o fato de todo codigo ser compilado por threads dedicadas.

appe

ndhan

oi

nreve

rse

quick

sort tak

zebr

a

binar

y tre

es

fannku

chfa

sta

k nucle

otide

mande

lbrot

n-bod

y

nsieve

nsieve

bits

parti

al su

m

pidigi

ts

recu

rsive

spec

tral n

orm

00.20.40.60.8

11.21.41.61.8

22.22.4

Com recompilação

Sem recompilação

Figura 5.4: Aceleracao/desaceleracao dos programas teste no modo compilac~ao

contınua (com e sem recompilacao) sobre o modo somente interpretar.Valores menores que 1 indicam desaceleracao.

Como esperado, os tempos gastos na construcao dos tracos dos programas executados

no modo compilac~ao contınua foram similares ao modo smart JIT. Executando sem

recompilacao, a proporcao do tempo de construcao de tracos pelo tempo de execucao

variou da mesma forma que no modo smart JIT sem recompilacao: a menor proporcao

foi de 0, 0001% (k nucleotide) e a maior foi de 0, 01% (fasta). Com a recompilacao

Page 125: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

122

appe

ndhan

oi

nreve

rse

quick

sort tak

zebr

a

binar

y tre

es

fannku

chfa

sta

k nucle

otide

mande

lbrot

n-bod

y

nsieve

nsieve

bits

parti

al su

m

pidigi

ts

recu

rsive

spec

tral n

orm

0%10%20%30%40%50%60%70%80%90%

100%

Interpretador InstrumentadoConstrutor de TraçosCódigo Nativo

Figura 5.5: Percentuais do fluxo de execucao nos componentes ativos no modocompilac~ao contınua.

ativa a variacao entre as proporcoes foram semelhantes para a maioria dos programas.

Nesse ultimo caso, a unica excecao ocorreu para o programa k nucleotide que, desta vez

teve um tempo de construcao de tracos muito maior, ocupando cerca de 60% do tempo

de execucao total.

Essa alta proporcao se deve a alta dinamicidade do programa k nucleotide ou, em

outras palavras, a constante modificacao do comportamento deste programa em tempo

de execucao. Em particular, os tracos compilados para este programa se tornam invalidos

muito rapidamente. Em nıvel de implementacao, isso significa que os blocos elementares

de multiplos destinos dentro dos tracos compilados regularmente precedem blocos basicos

que nunca foram tratados pelo Construtor de Tracos, fazendo entao, que o fluxo de execucao

retorne ao interpretador e a reconstrucao dos tracos. Esse comportamento serve para

explicar o porque este programa teve altas quedas de desempenho nos modos smart JIT

e compilac~ao contınua. Apenas para tıtulo de comparacao, k nucleotide teve 12

tracos construıdos, com cada um deles recompilados tres vezes. Por outro lado, dentre os

demais programas, aquele que mais recompilou construiu apenas 3 tracos e, em media,

cada um deles foi recompilado apenas duas vezes.

De qualquer forma, embora ainda compilasse programas com threads separadas, o

modo compilac~ao contınua teve um tempo de execucao total compatıvel com smart JIT

devido a dois fatores. O primeiro fator esta relacionado com o Interpretador Instrumentado,

pois, visto que na compilac~ao contınua o Compilador JIT e invocado por threads

separadas, a execucao ainda mantem, mesmo que por pouco tempo, a execucao em codigo

interpretado ate que o codigo compilado seja instalado na Area de Codigo Nativo. Nesse

sentido, isso amortiza qualquer ganho obtido durante a geracao de codigo.

O segundo fator esta relacionado ao Compilador JIT. Na verdade, este componente

e muito rapido para gerar codigo e, portanto, dificilmente o ganho de desempenho

Page 126: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

123

relacionado e perceptıvel. O modo compilac~ao contınua com recompilacao obteve

melhor desempenho que smart JIT (tambem com recompilacao) ao executar os programas

hanoi, mandelbrot, n-body, partial sum e pidigits. Para estes, a melhoria foi de

4, 7%, 2, 3%, 0, 6%, 0, 02% e 0, 3%, respectivamente. Sem recompilacao, entretanto, os

programas que apresentaram melhoria de desempenho foram novamente mandelbrot

(7, 9%), n-body (1, 7%), pidigits (3%), alem de tak (1, 9%), fannkuch (4, 5%), k

nucleotide (4, 8%) e spectral norm (2, 1%). Esses resultados, juntamente com aqueles

apresentados na Secao 5.3.1 permitem calcular a media de desempenho dos modos de

execucao. Em primeiro lugar, o melhor modo e smart JIT com recompilacao, cuja

melhoria sobre o modo somente interpretar foi de 12%, em media. Em seguida foi

o modo compilac~ao contınua com recompilacao (10, 6%), depois o modo smart JIT

sem recompilacao (−1, 6%) e, por fim, o modo compilac~ao contınua sem recompilacao

(−2, 4%)1.

Por fim, e possıvel concluir que o modo de compilac~ao contınua e, em geral, pior

que o modo smart JIT porque, em media, o baixo tempo de compilacao nao e capaz

de amortizar o tempo total de execucao devido ao custo de Interpretador Instrumentado,

que precisa permanecer ativo durante a geracao de codigo. Isso, portanto, demonstra que

a unica alternativa para aumentar o desempenho dos programas no modo compilac~ao

contınua e utilizar um interpretador mais sofisticado, que emita blocos basicos somente

quando necessario, como descrito na Secao 5.2.

5.3.3 O Desempenho de Somente Compilar

Os resultados obtidos no modo somente compilar sobre o modo somente interpretar

estao representados na Figura - 5.6. Nesta figura, o desempenho de cada programa e

apresentado em uma barra que representa a (des)aceleracao dos programas. Alem desta

figura, a Figura - 5.7 ainda indica o percentual em que o fluxo de execucao se manteve no

Compilador JIT e na execucao do codigo nativo.

Mesmo nao invocando o Interpretador Instrumentado, o modo somente compilar nao

alcancou melhor desempenho em nenhum programa em comparacao aos demais modos e

e, portanto, considerado o modo com pior desempenho. Ainda assim, apenas os programas

desacelerados nos modos smart JIT e compilac~ao contınua tiveram melhor desempenho

no modo somente compilar.

1Os valores negativos e devido a alta desaceleracao apresentada nos programas k nucleotide emandelbrot.

Page 127: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

124

appe

ndhan

oi

nreve

rse

quick

sort tak

zebr

a

binar

y tre

es

fannku

chfa

sta

k nucle

otide

mande

lbrot

n-bod

y

nsieve

nsieve

bits

parti

al su

m

pidigi

ts

recu

rsive

spec

tral n

orm

0

0.1

0.2

0.3

0.4

0.5

0.6

0.7

0.8

0.9

1

Figura 5.6: Aceleracao/desaceleracao dos programas teste no modo somente compilar

sobre o modo somente interpretar. Valores menores que 1 indicamdesaceleracao.

appe

ndhan

oi

nreve

rse

quick

sort tak

zebr

a

binar

y tre

es

fannku

chfa

sta

k nucle

otide

mande

lbrot

n-bod

y

nsieve

nsieve

bits

parti

al su

m

pidigi

ts

recu

rsive

spec

tral n

orm

0.01%

0.1%

1%

10%

100%

Compilador JITCódigo Nativo

Figura 5.7: Percentuais do fluxo de execucao nos componentes ativos no modo somente

compilar. O grafico esta representado em escala logaritmica para destacaros tempos do Compilador JIT.

No modo somente compilar, todas as clausulas sao compiladas na primeira invocacao.

Se uma clausula contem instrucoes call ou fcall, estas sao compiladas normalmente,

como qualquer outra, mas logo apos estas, um codigo adicional e inserido para que a

clausula nativa seja capaz de compilar e chamar a clausula que ela precisa invocar. O

custo desta instrumentacao, somado ao custo de compilacao e invocacao e manutencao de

funcoes e o que justifica porque nenhum programa executado no modo somente compilar

alcancaram desempenho melhor que o modo somente interpretar. Neste ponto e

importante ressaltar que a queda do desempenho nao esta associado a interpretacao de

codigo. De fato, o modo somente compilar ainda interpreta codigo para tratar excecoes

ocorridas em codigo nativo, mas como nao ha necessidade de construir tracos de execucao,

o interpretador utilizado e o Interpretador YAP, que nao atribui custos consideraveis frente

ao Interpretador Instrumentado.

Page 128: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

125

Enfim, tais resultados demonstram que a unica alternativa para obter desempe-

nho no modo somente compilar e que o sistema consiga inferir tracos de execucao

nao-superficiais (tracos que mapeiam a maior quantidade de codigo de uma cadeia de

chamadas), antes mesmo da primeira invocacao da primeira clausula. Analise global

seria util nesse sentido, ao analisar o corpo das clausulas e, consequentemente, uma

cadeia de invocacoes de clausulas. Realizar essa analise no tempo de carregamento do

programa seria ainda mais interessante pois, conhecendo o tamanho da entrada, seria

possıvel descobrir (ou inferir) quantas vezes um determinado traco seria invocado. Na

verdade, o principal problema relacionado a isso, e o fato de que o YAP gera instrucoes

de indexacao em tempo de execucao, sendo difıcil definir quais delas integrarao os tracos

que serao inferidos. Para este ultimo caso, uma solucao seria investigar em mais detalhes

o algoritmo para geracao de tais instrucoes (Costa, 2009; Costa et al., 2007) e entao,

implementar um mecanismo para integrar as conclusoes obtidas nesta investigacao na

tecnica de analise global empregada.

5.4 Desempenho na Construcao dos Tracos

A Secao 5.3 mostrou que para casos em que os programas alcancam melhor desempenho

os tracos construıdos mapeiam o maior escopo possıvel dos programas, ocasionando um

fluxo de execucao que se mantem a maior parte do tempo. Nesta secao e apresentada

uma avaliacao sobre a eficiencia do Construtor de Tracos. Os resultados servirao para

mostrar o porque que determinados programas nao obtiveram um ganho de desempenho

na execucao.

Para esta parte da analise, todos os dados relevantes foram coletados a partir da

execucao no modo smart JIT, conforme a configuracao apresentada na Secao 5.3. Mas,

como o foco nesta parte e avaliar a eficiencia do Construtor de Tracos, as conclusoes foram

baseadas nos resultados obtidos na configuracao sem recompilacao. A configuracao com

recompilacao foi considerada apenas para comparacao, a fim de avaliar a efetividade do

Modulo de Recompilacao.

Os resultados obtidos sao mostrados na Figura - 5.8 (sem recompilacao) e na Figura -

5.9 (com recompilacao). Nessas figuras, cada traco e representado por uma barra dividida

em tres campos que indicam o percentual do tempo em que o fluxo permanece construindo

tracos, compilando e executando codigo nativo. Este percentual foi calculado dividindo

o tempo gasto em cada tarefa pelo tempo somado das tres tarefas, resultando em um

valor que indica a dominancia da tarefa. Baseado nisso, e possıvel definir que a tarefa

Page 129: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

126

dominante em cada traco e aquela representada pela maior sub-barra que compoe a barra

do traco.

T1 T1 T1 T2 T1 T2 T10,001%

0,01%

0,1%

1%

10%

100%

ConstruçãoCompilaçãoExecução

T1=(0,004; 0,006; 0,209; 0,050) T1=(0,004; 0,013; 1,958; 0,486)

T2=(0,004; 0,008; 122,965; 0,018)

T1=(0,004; 0,004; 0,005; 289,912)

T2=(0,004; 0,017; 18,223; 0,167)

T1=(0,004; 0,018; 1,733; 1,794) T1=(0,004; 0,013; 4,818; 0,244)

append hanoi nreverse quicksort tak

T1 T2 T3 T1 T2 T3 T4 T1 T2 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T110,001%

0,01%

0,1%

1%

10%

100%

ConstruçãoCompilaçãoExecução

T2=(0,004; 0,042; 55,840; 0,049)

T1=(0,004; 0,023; 15,013; 0,201)

T2=(0,004; 0,020; 33,113; 0,080)

T3=(0,004; 0,027; 14,248; 0,243)

T1=(0,004; 0,052; 265,751; 0,072)

T2= (0,004; 0,055; 42,766, 0,466)

T4= (0,004; 0,052; 25,068; 0,763)

T1=(0,004; 0,072; 0,160; 31339,096) T2=(0,004; 0,080; 0,892; 6213,055)

T4=(0,004; 0,060; 13,381; 315,586)

T5=(0,004; 0,028; 24,826; 85,049) T6=(0,004; 0,168; 0,024; 472865,030)

T7=(0,008; 0,152; 1,964; 5374,919) T8=(0,004; 0,156; 1,852; 5699,948)

T9=(0,004; 0,060; 8,133; 519,250) T10= (0,004; 0,016; 0,064; 20619,115)

T11=(0,004; 0,008; 0,016; 49485,875)

binary trees fannkuch fasta k nucleotide

T3= (0,004; 0,052; 0,429; 44,607)

T1= (0,004; 0,050; 0,834; 3,909)

T3=(0,004; 0,016; 55,864; 23,622)

T1 T2 T1 T1 T2 T3 T1 T2 T3 T1 T1 T2 T1 T2 T3 T1 T2 T30,001%

0,01%

0,1%

1%

10%

100%

ConstruçãoCompilaçãoExecução

T1=(0,004; 0,055; 0,729; 32,672)

T1=(0,004; 0,077; 44,439; 0,084)

T1=(0,004; 0,010; 33,390; 0,103)

T2=(0,004; 0,014; 92,423; 0,047)

T3=(0,004; 0,028; 100,079; 0,079)

T2=(0,004; 0,020; 31,643; 0,074)

T3=(0,004; 0,030; 48,376; 0,070)

T1=(0,004; 0,008; 0,348; 3,496)

T1=(0,004; 0,052; 60,360; 0,057)

T1= (0,004; 0,066; 8,915; 0,561)

T2=(0,004; 0,068; 60,316; 0,085)

T1=(0,004; 0,016; 50,482; 0,058)

T2=(0,004; 0,018; 39,354; 0,084)

T3=(0,004; 0,019; 55,405; 0,061)

T2=(0,004; 0,033; 15,206; 0,357)

T3=(0,004; 0,033; 16,654; 0,326)

T1=(0,004; 0,020; 0,004; 818,972)

mandelbrot n-body nsieve nsieve bits partial sum pidigits recursive spectral norm

T2=(0,004; 0,056; 32,685; 0,739)

Figura 5.8: Tempos de construcao, compilacao e execucao dos tracos na configuracaosmart JIT sem recompilacao. Ti representa o traco de numero i. Valoresem vermelho indicam tracos nao uteis.

Page 130: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

127

T1 T1 T1 T2 T1 T10,001%

0,01%

0,1%

1%

10%

100%

ConstruçãoCompilaçãoExecução

T1=(0,005; 0,006; 0,212; 0,055) T1=(0,004; 0,010; 2,016; 0,372)

T2=(0,006; 0,004; 123,302; 0,014)

T1=(0,034; 0,004; 0,005; 1473,366) T1=(0,005; 0,070; 20,659; 0,305) T1=(0,004; 0,021; 4,690; 0,372)

append hanoi nreverse quicksort tak

T1 T2 T1 T2 T3 T4 T1 T2 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T110,001%

0,01%

0,1%

1%

10%

100%

ConstruçãoCompilaçãoExecução

T2=(0,010; 0,158; 55,728; 0,183)

T1=(0,078; 0,338; 58,998; 0,756)

T2= (0,008; 0,190; 4,804; 4,411)

T1=(0,005; 0,181; 268,706; 0,237)

T2= (0,004; 0,118; 35,863; 1,168)

T3= (0,008; 0,053; 25,178; 0,821)

T1= (641,179; 0,442; 54,691; 120879,278) T2= (312,669; 2,330; 11,464; 283104,998)

T3=(179,205; 1,254; 1,083; 1716446,449) T4= (240,227; 1,494; 3,360; 741276,185)

T5= (112,213; 1,282; 7,189; 162675,149) T6=(91,306; 1,288; 7,260; 131416,610)

T7=(202,111; 1,066; 1,793; 1167844,436) T8=( 339,606; 0,268; 0,077; 45361580,801)

T9=(245,695; 0,012; 0,004; 632914585,253) T10=(145,444; 0,480; 0,045; 33561116,722)

T11=(126,750; 0,254; 0,034; 38487969,858)

binary trees fannkuch fasta k nucleotide

T4=(0,004; 0,059; 0,176; 122,363)

T1=(0,244; 0,041; 0,830; 20,843)

T1 T1 T1 T2 T1 T2 T1 T1 T2 T1 T2 T3 T1 T2 T30,001%

0,01%

0,1%

1%

10%

100%

ConstruçãoCompilaçãoExecução

T1=(0,006; 0,222; 35,393; 0,237)

T1=(0,020; 0,081; 44,020; 0,104)

T1= (0,044; 0,112; 33,456; 1,119)

T2=(0,007; 0,168; 193,793; 0,217)

T2=(0,005; 0,266; 77,642; 0,297)

T1=(0,090; 0,164; 0,647; 33,397)

T1=(0,005; 0,048; 60,497; 0,054)

T1= (0,004; 0,068; 9,006; 0,553)

T2=(0,006; 0,069; 60,097; 0,087)

T1=(0,220; 0,020; 49,327; 0,730)

T2=(0,054; 0,021; 40,115; 0,283)

T3=(0,006; 0,140; 56,426; 0,388)

T2= (0,156; 0,208; 15,255; 3,658)

T3= (0,143; 0,174; 16,475; 2,955)

T1=(0,455; 0,244; 0,076; 1411,250)

mandelbrot n-body nsieve nsieve bits partial sum pidigits recursive spectral norm

Figura 5.9: Tempos de construcao, compilacao e execucao dos tracos na configuracaosmart JIT com recompilacao. Ti representa o traco de numero i. Valoresem vermelho indicam tracos nao uteis.

Alem das barras, essas figuras apresentam, para cada traco, uma quadrupla da forma

Ti(W, X, Y , Z), em que i representa o numero do traco relativo ao programa, W, X,

Page 131: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

128

Y representam, respectivamente, o tempo de construcao, compilacao e execucao (em

segundos) e Z o nıvel de nao utilidade do traco. Em especıfico, este ultimo valor foi

calculado pela Formula 5.3 e indica o nıvel de utilidade do traco, isto e, o quanto o traco

e importante para o desempenho do programa. Basicamente, quanto mais proximo de

zero e o nıvel de nao utilidade do traco, maior o tempo em que o fluxo de execucao

mantem executando-o e, consequentemente, maior e a sua efetividade para obtencao de

ganhos de desempenho. Analogamente, quanto maior for o nıvel de nao utilidade do

traco (geralmente, maior do que 1 para o modo sem recompilacao ou maior do que 20

para o modo com recompilacao), maior e a dominancia das outras tarefas (construcao ou

compilacao) e menor e a sua eficiencia na execucao de codigo nativo.

Nıvel de n~ao-utilidade =Tempoconstruindo + Tempocompilando

Tempoexecutando× Tempototal (5.3)

Tempo de execuc~ao util = Tempoexecutando - Tempoconstruindo - Tempocompilando (5.4)

Outra formula utilizada, mas com valores nao implicitamente representados, e a

formula 5.4, que calcula o tempo de execucao util dos tracos ou, em outras palavras,

quanto tempo restou executando o traco depois que o mesmo foi construıdo e compilado.

Um resultado negativo nesta ultima formula indica que o tempo de execucao nao foi

suficiente para amenizar o custo da construcao e compilacao do traco. Tracos com este

tipo de comportamento sao classificados como tracos nao uteis e sao identificados na

Figura - 5.8 e na Figura - 5.9 com suas respectivas quadruplas marcadas em vermelho.

Alem disso, tracos com um tempo de execucao util menor que o nıvel de nao-utilidade

tambem possuem valores marcados em vermelho, por terem sido executados por muito

pouco tempo (na maioria das vezes, menos que 1 segundo).

Primeiramente, em respeito a quantidade de tracos na configuracao sem recompilacao,

em media, foi construıdo 1 traco para os kernels de Prolog e 3 tracos para os programas

do shootout. Dentre todos os programas, hanoi, binary trees, n-body, nsieve, partial

sum e recursive foram os unicos programas que obtiveram desempenho executando todos

os tracos uteis. Os programas nreverse, fannkuch, fasta e spectral norm, apesar de

tambem obterem ganho de desempenho, tiveram ainda um traco nao util construıdo.

Isso mostra que o ganho de desempenho nao e dependente da execucao de tracos uteis

unicamente, mas pode ser otimo se tracos nao uteis puderem ser evitados, principalmente

Page 132: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

129

tracos com nıvel de nao-utilidade muito alto, como, por exemplo, o primeiro traco

dos programas nreverse e spectral norm. Nesse sentido, a recompilacao foi muito

importante pois, alem de alcancar um desempenho melhor em geral, pode tambem evitar

que tracos nao uteis fossem construıdos para alguns programas. Esta tecnica detecta

a condicao de saıda de um traco e recompila-o com o novo fluxo de execucao tomado,

permitindo que o fluxo de execucao mantenha mais tempo em codigo nativo. Dentre

os programas avaliados, os programas quicksort e mandelbrot, por exemplo, puderam

obter desempenho devido a eliminacao de tracos nao uteis.

Contudo, mesmo a recompilacao nao foi suficiente para todos os casos. No caso

mais crıtico, que se refere ao programa k nucleotide, por exemplo, a recompilacao nao

evitou a maioria dos tracos nao uteis e mesmo alcancando desempenho sobre o modo

sem recompilacao, nao foi suficiente para superar o modo somente interpretar. Por

essa razao, empregar analise global tambem neste caso pode garantir que mais tracos nao

uteis sejam evitados para outros programas. Com analise global, e possıvel investigar

a estrutura do codigo Prolog e entao presumir a partir de qual iteracao uma estrutura

mudara o seu tipo (por exemplo, quando uma lista se tornara nula), que e uma condicao

para tornar um traco invalido, e entao, verificar a quantidade de iteracoes realizadas ate

a construcao do traco e, a partir disso, definir se compensa compila-lo ou nao.

Outro ponto importante a considerar, em respeito a comparacao entre o modo sem

recompilacao e o modo com recompilacao, e que neste ultimo o aumento do tempo de

construcao e compilacao dos tracos nao prejudicou o desempenho dos programas que

antes tinham alcancado desempenho no modo sem recompilacao (sobre o modo somente

interpretar), mostrando que o custo da recompilacao e mınimo, no caso de programas

com desempenho melhorado. A unica excecao a esta regra e o programa hanoi, mas para

este, o caso se refere as excecoes trataveis unicamente pelo interpretador. Por outro lado,

a compilacao e, principalmente, a construcao dos tracos sao os principais fatores para o

alto tempo de execucao nos casos em que houve queda de desempenho.

De fato, o alto custo de Construtor de Tracos, visivelmente apresentado no programa

k nucleotide no modo com recompilacao, e consequencia tambem do alto custo do

Interpretador Instrumentado. Alem disso, programas com muitos tracos construıdos mos-

traram que o mecanismo de selecao de clausulas principais nao e otimo. O caso para

os tracos que poderiam ser evitados indicam que estes comecaram a ser construıdos no

final de uma cadeia de invocacoes, onde o traco resultante costuma ser menor. Quando

a execucao continua e uma clausula no inıcio da cadeia de invocacoes se torna crıtica, o

traco anteriormente construıdo e descartado, porque neste momento ele fara parte de um

traco maior.

Page 133: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

130

Outra situacao que ocorre ainda para o programa k nucleotide (brevemente descrita

na Secao 5.3.2) e a sua alta dinamicidade, que afeta ate mesmo grandes tracos. Esta

dinamicidade tem relacao com a mudanca dos tipos dos termos e clausulas de destino

referenciadas apos a execucao de instrucoes de indexacao e infelizmente nao pode ser

detectada com o mecanismo atual de construcao de tracos implementado. Esse fator

tambem foi responsavel pela alta desaceleracao deste programa em todos os modos, pois

ele invalida tracos anteriormente construıdos, fazendo com que o fluxo de execucao retorne

ao interpretador sempre que esta situacao ocorre.

Adicionalmente, outro problema e que, no sistema desenvolvido, a construcao de tracos

otimos (somente) nao e garantia de desempenho para programas com alta concentracao

de tempo na manipulacao de excecoes. Isso pode ser comprovado a partir da Figura -

5.10 (que mostra a proporcao do tempo em que cada programa necessita para realizar

certas tarefas trataveis unicamente em codigo interpretado, normalmente relacionadas a

manipulacao das regioes de memoria do YAP), que demonstra o porque que determinados

programas, como hanoi e tak, nao puderam alcancar melhoria em todos os modos de

execucao avaliados, mesmo tendo todos os tracos uteis construıdos. Esta figura tambem

demonstra que o alto tempo dessas tarefas para os programas binary tress e spectral

norm foi tambem outro fator que impediu que tais programas nao alcancassem maiores

ganho de desempenho.

appe

ndhan

oi

nreve

rse

quick

sort tak

zebr

a

binar

y tre

es

fannku

chfa

sta

k nucle

otide

mande

lbrot

n-bod

y

nsieve

nsieve

bits

parti

al su

m

pidigi

ts

recu

rsive

spec

tral n

orm

0 %

10 %

20 %

30 %

40 %

50 %

60 %

70 %

80 %

90 %

100 %

Figura 5.10: Taxas do fluxo de execucao na manutencao das areas de memoria dosistema sobre o tempo total de execucao de cada programa avaliado. Osvalores sao praticamente os mesmos em todos os modos de execucao..

Por fim, baseado nos problemas identificados, uma tarefa importante e modificar o

sistema para que o mesmo trate as tarefas de manipulacao das areas de memoria tambem

em codigo nativo, a fim de minimizar este problema e garantir uma execucao eficiente

de todos os programas, desde que todos os tracos construıdos sejam uteis. A tarefa de

Page 134: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

131

evitar tracos nao uteis funciona para alguns casos no sistema desenvolvido, desde que a

recompilacao esteja ativada, mas pode ser aprimorada pelo uso de analise global e/ou

online profiling, a fim de detectar clausulas de partida de tracos que estejam no inıcio de

uma cadeia de invocacoes.

Baseado nos resultados obtidos a partir da execucao dos programas avaliados, o uso das

tecnicas supracitadas pode ser suficientes para alcancar maiores ganhos de desempenho.

Entretanto, no caso do programa k nucleotide, em especıfico, e necessario desenvolver

uma tecnica que identifique as mudancas relativas a dinamicidade inerente de Prolog e

usar isso a favor do Construtor de Tracos para que este gere tracos validos por mais tempo.

5.5 Consideracoes Finais

Os modos de execucao de codigo misto desenvolvidos permitiram alcancar um dos

objetivos propostos neste trabalho, pois alcancaram desempenho sobre o modo somente

interpretar para a maioria dos programas. Nesse aspecto, a recompilacao foi muito

importante pois, alem de obter o melhor tempo de execucao, em media, pode tambem

evitar que tracos nao uteis fossem construıdos para alguns programas. Entretanto, o

modo somente compilar requer uma atencao especial em trabalhos futuros, pois este

nao alcancou desempenho em nenhum programa avaliado. A deficiencia deste ultimo

modo e a carencia de profilers no sistema, os quais permitiram coletar informacoes uteis

que auxiliassem a geracao de codigo.

Alem do primeiro objetivo, a construcao (e utilizacao) dos predicados nativos para

coletar perfis de execucao mostraram ser suficientes para avaliar os casos apresentados

neste capıtulo. Com as informacoes coletadas, foi possıvel identificar a eficiencia dos

tracos de execucao em respeito a quantidade por programa e desempenho na execucao. No

melhor caso, 13 dentre todos os programas avaliados obtiveram ganho de desempenho em

modo de execucao com codigo misto, em comparacao a um modo que somente interpreta,

1 nao teve traco construıdo/compilado e 4 nao apresentaram ganho de desempenho.

A principal causa para a perda de desempenho de alguns programas e devido a alta

concentracao do fluxo de execucao no Interpretador Instrumentado que, em media, e 11

vezes mais lento que o Interpretador YAP. Basicamente, a principal razao para essa alta

concentracao e devido a dois importantes fatores: (1) a baixa precisao do sistema em

identificar clausulas iniciais em uma cadeia de invocacoes, onde os tracos construıdos

a partir delas sao maiores e (2) a incapacidade do Construtor de Tracos em identificar

mudancas do comportamento dos programas em tempo de execucao, que invalida qualquer

traco anteriormente construıdo. Alem disso, outra causa para a queda no desempenho

Page 135: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

132

(ou obstaculo para maiores ganhos no desempenho) e a execucao obrigatoria em codigo

interpretado para realizacao de tarefas relacionadas a manipulacao das regioes de memoria

do YAP.

Por fim, no decorrer deste capıtulo, diversas ideias para aprimorar o sistema de-

senvolvido foram propostas, sendo as principais a construcao de um novo conjunto de

instrucoes, que permita enviar blocos basicos aos Construtor de Tracos somente

quando necessario, o uso de analise global e o tratamento de excecoes tambem em codigo

nativo. O proximo capıtulo apresenta a conclusao deste trabalho e uma visao mais

detalhada destes e outros trabalhos a serem desenvolvidos futuramente.

Page 136: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

133

6

Conclusoes e Trabalhos Futuros

Desde o desenvolvimento do primeiro interpretador Prolog conhecido (Colmerauer e

Roussel, 1996), diversas tecnicas para melhorar a execucao da linguagem foram pro-

postas (Diaz et al., 2012; Hermenegildo et al., 2012; Hickey e Mudambi, 1989; Marien,

1988; Meier, 1990; Taylor, 1996; Turk, 1986; Van Roy, 1989, 1990; Van Roy et al.,

1987). Algumas delas sao aplicaveis aos interpretadores que surgiram posteriormente,

os quais consistem da maioria das implementacoes existentes atualmente, mas certamente

a geracao de codigo nativo juntamente com a analise global e a tecnica que alcanca melhor

desempenho conhecido.

A analise global aplicada a coleta de informacoes para especializar a geracao de codigo

foi considerada util para implementacoes Prolog a partir dos trabalhos de Mellish em

1981 e 1985 (Mellish, 1981, 1985) e tambem de Warren et al. (1988). Depois disso, os

resultados apresentados serviram como uma motivacao para os trabalhos de Van Roy, com

o sistema Aquarius (Van Roy, 1990; Van Roy e Despain, 1992), e Taylor, com Parma

(Taylor, 1996), confirmando a eficiencia da analise global em derivar tipos e consequente

geracao de codigo de boa qualidade, que serviram para convergir nos otimos resultados

obtidos por estes sistemas.

Infelizmente, apesar dos resultados, Aquarius e Parma foram descontinuados porque

analise global e geracao de codigo representam alta complexidade na manutencao dos

sistemas. Por outro lado, YAPc (Silva e Costa, 2007) surgiu como uma proposta de

compilador JIT simples de manter, que substitui o uso da analise global por informacoes

coletadas dinamicamente, enquanto ainda compila codigo para regioes de codigo frequen-

tes utilizando esse tipo de informacoes. Esse compilador foi um prova de conceito de que

vale o custo de investir nesse tipo de estrategia na implementacao de sistemas Prologmais

Page 137: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

134

eficientes e embora nao tenha sido acoplado a qualquer interpretador em uso atualmente,

este serviu como a principal motivacao para o desenvolvimento deste trabalho.

A proxima secao apresenta as motivacoes que levaram ao projeto e implementacao

deste trabalho. Logo depois, sao apresentados uma sıntese do trabalho, uma breve

discussao sobre os resultados alcancados, os trabalhos futuros e as consideracoes finais.

6.1 Motivacoes

YAPc foi desenvolvido como modelo conceitual de compilacao JIT para Prolog e mostrou

que e possıvel alcancar melhorias de desempenho sem o uso de analise global. Contudo, no

que se refere o uso de tecnicas de compilacao JIT, YAPc e muito limitado: a selecao de

unidades e baseada em regioes e a quantidade de otimizacoes de codigo e muito reduzido.

Alem disso, o alocador de registradores e baseado em coloracao de grafo, que nao e

indicado no desenvolvimento de compiladores JIT devido ao seu alto custo.

Somado a isso, sao conhecidas poucas implementacoes de compilacao JIT para Prolog.

Na verdade, apenas YAPc e conhecido pela comunidade cientıfica e todos os demais com-

piladores JIT existentes foram projetados para linguagens essencialmente nao declarativas.

Isso significa que toda pesquisa imposta na busca de tecnicas de compilacao JIT mais

eficientes nao sao garantidas ate que as tais sejam efetivamente empregadas no contexto

desejado. Portanto, nao somente YAPc com suas caracterısticas e limitacoes se tornou

motivacao para a realizacao deste trabalho, mas tambem a necessidade de direcionar as

pesquisas realizadas no campo da linguagem Prolog.

Portanto, em respeito a primeira motivacao, o fato de projetar o sistema deste trabalho

com diversas configuracoes possıveis, como diversos modos de execucao e parametros de

frequencia, e pela limitacao das pesquisas no campo de compilacao JIT para Prolog,

conforme citado anteriormente. Por outro lado, a ultima motivacao e o que justifica

os predicados implementados neste trabalho, pois os mesmos facilitam, por meio de

experiencias realizadas, a identificar a melhor configuracao do sistema (no sentido de

alcancar o melhor desempenho possıvel), alem de facilitar a depuracao de codigo.

6.2 A Nova Geracao do YAP

A arquitetura da nova geracao do YAP consiste de diversos modulos independentes

que se inter-relacionam para a manutencao de um sistema que compila codigo em

tempo de execucao. O sistema desenvolvido prove quatro modos de execucao: somente

Page 138: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

135

interpretar, somente compilar, compilac~ao contınua e smart JIT, dos quais, os dois

ultimos suportam execucao em codigo misto.

Alem de suportar execucao em codigo misto, os modos smart JIT e compilac~ao

contınua empregam um interpretador especial, o qual e capaz de emitir blocos basicos

recem executados para outro modulo especıfico, chamado Construtor de Tracos, que

constroi os tracos de execucao dos programas para que codigo nativo sejam gerados para

eles. Por outro lado, o modo somente compilar trata como unidades de compilacao uma

clausula recem-invocada porque, para este, nao ha como construir tracos de execucao.

A vantagem dos modos de execucao com codigo unico (somente interpretar e

somente compilar) e que estes nao possuem o custo adicional de invocar o Monitor,

o que nao ocorre com modos de execucao de codigo misto, nos quais este componente

e necessario para detectar clausulas crıticas. As clausulas crıticas sao pontos iniciais

dos tracos, onde o Construtor de Tracos comeca a tratar os blocos basicos emitidos pelo

interpretador. Os tracos sao construıdos como um grafo de fluxo de controle, cujos nos

sao compostos somente de blocos basicos efetivamente executados. Outra vantagem dos

modos de execucao de codigo unico e que tambem nao e necessario invocar o Interpretador

Instrumentado, embora o modo somente compilar, em especıfico, uma maior atencao seja

necessaria para reduzir sua baixa eficiencia demonstrada.

6.3 Resultados Alcancados

Um dos objetivos deste trabalho foi alcancado ao demonstrar que todos os programas

que construıram somente tracos uteis obtiveram ganho de desempenho sobre o modo

somente interpretar. Na verdade, as unicas excecoes sao para os programas append,

hanoi e tak que so nao alcancaram desempenho devido a grande quantidade de dados

manipulada e ao alto tempo gasto no coletor de lixo (exceto em um ou outro modo

de execucao) que, no sistema implementado e tratado unicamente no interpretador (no

Interpretador Instrumentado nos modos de codigo misto e Interpretador YAP nos demais

modos). O conceito de tracos nao uteis foi apresentado na Secao 5.4 e a execucao destes

foi responsavel para que alguns programas, como quicksort, k nucleotide, mandelbrot

e nsieve bits, obtivessem altos ındices de desaceleracao.

Nesse aspecto, a recompilacao se mostrou muito importante na execucao dos pro-

gramas pois, alem de executar os programas de forma mais eficiente (tanto no modo

Smart JIT como compilac~ao contınua) foi tambem capaz de evitar que tracos nao uteis

fossem construıdos para alguns programas, como foi para o programa mandelbrot, que

Page 139: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

136

pode variar o tempo de execucao de 405, 2 segundos (sem recompilacao) para apenas 35, 4

segundos em smart JIT, por exemplo.

Por fim, o custo relacionado a criacao de tracos nao uteis e atribuıdo ao Interpretador

Instrumentado, que apesar de permitir a criacao de tracos pela emissao de blocos, tem um

alto custo em relacao ao Interpretador YAP, que e padrao no sistema. Na verdade, isso e

consequencia de outros problemas, que estao relacionados a construcao de tracos que se

iniciam em clausulas no final de uma cadeia de invocacoes ou na falta de mecanismos que

possibilitem identificar a mudanca de comportamento dos programas.

Dessa forma, a proxima secao apresenta propostas de trabalhos futuros que tem como

principal objetivo melhorar o desempenho da proposta desenvolvida neste trabalho, por

meio da resolucao dos problemas identificados. Portanto, todas as propostas sao baseadas

em ideias de implementacao discutidas no decorrer do Capıtulo 5.

6.4 Trabalhos Futuros

Como visto nos resultados apresentados no Capıtulo 5, os programas append, hanoi,

quicksort, tak, k nucleotide, mandelbrot, nsieve, nsieve bits e pidigits apre-

sentaram uma perda de desempenho nos modo de execucao smart JIT e compilac~ao

contınua (quicksort, mandelbrot e nsieve bits so tiveram perda na configuracao sem

recompilacao). Alem disso, todos os programas apresentaram perda de desempenho no

modo somente compilar. No decorrer do Capıtulo 5 varias ideias foram introduzidas com

o proposito de que o sistema alcance desempenho para todos os programas, independente

do modo de execucao ativo.

A Figura - 6.1 apresenta uma extensao da arquitetura proposta a fim de suportar novas

funcionalidades, que poderao ser implementadas como trabalhos futuros. O objetivo

desta segunda geracao consiste em melhorar os perfis de execucao apresentados nos

resultados e obter desempenho para possivelmente todos os programas em todos os modos

de execucao desenvolvidos. Em seguida, sao apresentadas as propostas para trabalhos

futuros. Primeiramente, sao apresentadas as modificacoes a serem realizadas nos modulos

ja existentes. Em seguida, sao apresentados os novos componentes.

6.4.1 Gerente de Codigo

No sistema desenvolvido, o Gerente de Codigo e o componente responsavel por gerenciar

as areas de codigo, interagir com o Compilador JIT e enviar a versao correta de codigo para

o Motor de Execucao executar. Uma nova proposta consiste em estender este componente

Page 140: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

137

Gerentede código

Motor de Execução

Monitor

Compilador JIT

Fila de Compilação

Arquitetura YAPCódigoYAAM

CódigoInterm.

Códigonativo

Áreas de código

Áreas de código

Inicialização das áreas decódigo e do sistema em geral

Código compilado

Requisição decompilação e

código compilado

Versão correta decódigo para executar

Gerenciamento das áreasde código (busca e inserção)

Início da interpretação

Bibliotecas Engine Compilador

InterpretadorYAP Construtor

de Traços

Blocosbásicos

Traços deexecução

Instrumentaçãodas cláusulas

OfflineProfiler

OnlineProfiler

Cache

Informações coletadasem tempo de execução

Informações coletadasem tempo de compilação ou carga

Informaçõescoletadas

Código nativopara armazenar

Código nativopara armazenar

Informações coletadaspara armazenar

Bibliotecas Engine Compilador

Gerentede código

Motor de Execução

Compilador JIT

Construtorde Traços

OfflineProfiler

OnlineProfiler

Cache

Figura 6.1: Arquitetura proposta para trabalhos futuros.

para que, no final da execucao, ele envie os tracos (ou clausulas) contidos dentro da Area

de Codigo Nativo para a Cache.

6.4.2 Compilador JIT

O Compilador JIT e responsavel por gerar codigo nativo em quatro etapas distintas:

pre-processamento, traducao, analises e transformacoes de codigo e geracao de codigo.

Dentre elas, a traducao transforma codigo intermediario por meio de um parser externo.

Embora nao tenha um impacto significativo no tempo de execucao final, uma das

propostas e descartar o uso deste parser e construir outro que seja capaz de traduzir o

codigo YAAM dos tracos diretamente para codigo LLVA, que e a representacao de entrada

para a etapa de analises e transformacoes de codigo). Uma consequencia disso e a troca

da Area de Codigo Intermediario pela Area de Armazenamento de Tracos, cuja funcao e

armazenar os tracos de execucao construıdos. A principal razao para o uso dessa estrategia

esta relacionado simplesmente a elegancia do sistema, e nao ao desempenho.

Neste contexto, outro trabalho futuro e aprimorar o Compilador JIT para que este

gere codigo nativo de maior qualidade. Portanto, outra proposta consiste em aprimorar

este componente integrando a ele um sistema de compilacao adaptativa, similar a Jikes

Page 141: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

138

RVM (Arnold et al., 2000; Burke et al., 1999). Um sistema de compilacao adaptativa

permite que o compilador selecione automaticamente o conjunto de otimizacoes de codigo

mais adequado para o programa em execucao. A diferenca para com Jikes RVM, e

que, em vez de criar um conjunto pre-determinado de otimizacoes para aplicar aquele

mais adequado para o programa em execucao, a proposta original e capacitar o sistema

para que ele ative e desative otimizacoes individuais, e ordene da melhor maneira possıvel

aquelas que precisam ser aplicadas durante a geracao de codigo. Pesquisas nesse campo

ainda sao recentes e a maioria delas requerem que os programa sejam executados ao menos

uma vez para que um padrao adequado de otimizacoes seja definido (Agakov et al., 2006;

Cavazos e O’Boyle, 2005, 2006; Hoste et al., 2010; Triantafyllis et al., 2003). Contudo,

tais trabalhos demonstraram que a correta escolha das otimizacoes que eram aplicadas

ocasionaram ganhos de desempenho.

6.4.3 Motor de Execucao

O Motor de Execucao da segunda geracao pode ser modificado para suportar as alteracoes

descritas ao longo do Capıtulo 5. Essa modificacao consiste em retirar o Interpretador

Instrumentado e modificar o Interpretador YAP para que este ultimo tambem emita os

blocos basicos ao Construtor de Tracos. A ideia consiste em executar as instrucoes YAAM

padrao do sistema ate que alguma clausula crıtica seja detectada. A partir deste ponto, o

program counter (registrador P) e incrementado com um deslocamento adicional para que

as instrucoes da clausula crıtica, bem como de todas as clausulas invocadas por ela, sejam

executadas como instrucoes profiled, que sao instrumentadas com macros que emitem

os blocos basicos executados. Ao compilar o traco, o deslocamento e desconsiderado,

garantindo que toda excecao ocorrida em codigo nativo seja tratado nas instrucoes YAAM

padrao.

Outro trabalho importante estaria relacionado ao tempo de espera para que as

clausulas do programa se tornem crıticas. Idealmente isso pode ser feito considerando,

primeiramente, a seguinte heurıstica: se um programa leva t segundos para ser compilado,

entao um programa com o dobro do tamanho levaria o dobro do tempo para ser

compilado, considerando as mesmas otimizacoes de codigo. A heurıstica estabelecida

pode nao ser intuitiva em alguns (ou todos os) casos, mas nao deixa de ser uma ideia

valida. Depois disso, o sistema poderia utilizar calculo amostral (Cochran, 2007) e,

em conjunto com a heurıstica anteriormente citada, predizer o tempo de compilacao

de qualquer programa. Calculo amostral permite determinar os valores medios (neste

caso, o tempo de compilacao) para uma dada populacao (todos os programas), baseado

Page 142: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

139

em uma pequena amostra (poucos programas), que possuam as mesmas caracterısticas

(os mesmos tamanhos medios). Isso conduziria o sistema proposto para um sistema

adaptativo com o tempo, com a possibilidade de realizar melhores previsoes na medida em

que os programas sao executados. Como vantagem, isso poderia, por exemplo, determinar

o limite de tempo ideal para interpretar uma clausula quando oMonitor estiver configurado

para utilizar fracao de tempo para detectar clausulas crıticas (e quentes). Alem disso, o

Monitor poderia ser integrado com outros dois tipos de parametros de frequencia, que

sao crossover e balance (que foram apresentados na Secao 2.3.2), visto que os mesmos

requerem, como parametro, o tempo de compilacao das unidades.

Por fim, outras propostas consistem em aprimorar o modo de execucao somente

compilar para que este suporte manipulacao de excecao no codigo nativo, que atualmente

e feita no interpretador, permitir a emissao de blocos basicos relativos aos trechos de codigo

que manipulam o coletor de lixo, atualmente realizada tambem no interpretador, para

todos os modos, e integrar dois novos modos de execucao: anotador e compile-quente.

Anotador

No modo de execucao anotador, os programas sao interpretados do inıcio ao fim. O Com-

pilador JIT e desabilitado e um novo componente, o Online Profiler, monitora a execucao

dos programas para coletar informacoes em tempo de execucao. Essas informacoes

sao armazenadas no arquivo contendo o codigo Prolog do programa executado e sao

posteriormente recuperadas no modo de execucao compile-quente.

Compile-Quente

No modo compile-quente as informacoes coletadas no modo anotador sao recuperadas

e utilizadas para gerar codigo especializado na primeira invocacao das clausulas. Embora

todas as informacoes possam ser utilizadas em uma unica especializacao, a ideia original

e permitir que o usuario escolha quais informacoes recuperar e utilizar.

6.4.4 Offline Profiler

O Offline Profiler e um componente a ser implementado em versoes posteriores, como um

modulo para aplicar analise global aos programas que serao executados. Analise global

foi mencionada no decorrer de todo o Capıtulo 5 como uma tecnica primordial para que

o sistema alcance desempenho para todos os programas executados. Ela pode ser util nos

seguintes casos:

Page 143: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

140

• Encontrar uma clausula dentro de uma cadeia de chamadas que possibilita o sistema

construir, a partir de tal clausula, o maior traco de execucao possıvel (traco otimo);

• Inferir as instrucoes de indexacao que serao invocadas entre uma clausula e outra.

Isso retiraria a necessidade de manter tais instrucoes no corpo dos tracos ou, no

mınimo, possibilitaria a emissao de blocos basicos para elas.

• Inferir, em tempo de carga do programa, a quantidade de vezes que determinada

clausula sera invocada de acordo com o tamanho da entrada do programa. Essa

tatica funciona em programas onde a condicao de parada de uma cadeia de in-

vocacoes e dependente de uma instrucao condicional que contem, como um dos

operandos, a entrada do programa.

• Inferir, em tempo de carga do programa, a quantidade de vezes que determinada

clausula sera invocada de acordo com os tipos das estruturas. Essa tatica funciona

em programas onde a condicao de parada de uma cadeia de invocacoes e dependente

de uma estrutura que, com o tempo, certamente mudara o seu tipo, por exemplo,

uma estrutura do tipo lista que, apos algumas iteracoes se tornara nula.

• Inferir, em tempo de compilacao ou carga, traco(s) de execucao uteis quando o modo

de execucao ativo for somente compilar.

6.4.5 Online Profiler

O Online Profiler, assim como o Offline Profiler, tem por objetivo encontrar uma clausula

dentro de uma cadeia de chamadas cujo traco de execucao seja maior se construıdo a

partir dela. Em modos de execucao com codigo misto isto se torna possıvel ao investigar

o fluxo de execucao antes de qualquer clausula se tornar crıtica. Usando essa mesma

abordagem, o Online Profiler pode descobrir quais instrucoes de indexacao sao invocadas

entre as clausulas, tornando possıvel que a emissao de blocos tambem ocorra para eles.

Em casos melhores isso permitiria eliminar instrucoes de indexacao dentro do corpo dos

tracos construıdos.

Alem de tais informacoes serem uteis em modos de execucao com codigo misto, estas

podem ser coletadas no modo anotador e recuperadas no modo compile-quente. Outras

informacoes coletadas, porem somente no modo anotador, sao:

• Tipos de variaveis. Programas Prolog podem variar os tipos das variaveis em tempo

de execucao, o que significa que todas as instrucoes YAAM sao projetadas para

Page 144: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

141

suportar todos os tipos existentes. O uso de informacoes sobre os tipos de variaveis

permite que as instrucoes YAAM sejam especializadas para um tipo especıfico;

• Existencia de variaveis e sucesso na desreferenciacao. Algumas instrucoes YAAM

verificam a existencia de variaveis e saltam para uma instrucao em modo de escrita

quando a operacao de desreferenciacao e executada com sucesso. Tais informacoes,

portanto, evitam que algumas checagens sejam ignoradas;

• Realizacao de corte. Quando uma operacao de corte tem sucesso, determinadas

instrucoes YAAM que estruturam a clausula nao sao executadas. Saber se uma

operacao de corte tera sucesso permite que o compilador gere codigo menor ao

remover as instrucoes que nao serao executadas.

• Tempo de compilacao. Coletar o tempo de compilacao de determinadas clausulas

(ou tracos) oferece outra possibilidade de configurar o Monitor para usar crossover

e balance, sem necessitar empregar calculo amostral.

E importante notar que, como Prolog permite a criacao de programas nao-determinısticos,

todas as informacoes coletadas podem ser facilmente modificadas durante a execucao.

Na pratica, isso reflete a uma modificacao constante em algumas informacoes coletadas,

como os tipos das variaveis e o modo de execucao ativo. Portanto, e importante no

desenvolvimento do Online Profiler incluir um mecanismo para verificar a validade das

informacoes coletadas. Descobrir que uma informacao mudou indica que um traco (ou

clausula) especializado(a) se tornou invalido(a) e precisa ser recompilado(a) com a nova

informacao.

Alem disso, outra funcao deste componente e realizar a tarefa que, no sistema

desenvolvido, cabe ao Profiler.

6.4.6 Cache

Com uma Cache o sistema pode ser capaz de armazenar as clausulas anteriormente

compiladas em disco, para que estas sejam reutilizadas em execucoes posteriores do

sistema. As clausulas compiladas sao mantidas em memoria ate o final de execucao,

quando sao entao armazenadas no disco rıgido. Com este componente, e possıvel eliminar

o custo relacionado as etapas anteriores de compilacao, isto e, instrumentacao de codigo,

execucao em modo interpretado e profiling, buscando diretamente o codigo nativo no inıcio

da execucao do programa.

A ideia basica por tras da Cache e simples: toda clausula ou traco compilado e

instrumentado(a) com um cabecalho que contem duas informacoes: uma flag que indica de

Page 145: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

142

onde o codigo nativo foi proveniente (de clausula ou traco) e uma estrutura que armazena

a estrutura do codigo. Se o codigo foi proveniente de um traco compilado, essa estrutura

armazena os blocos basicos perfilados (e consequentemente compilados). Por outro lado,

se o codigo foi proveniente de uma clausula inteira (no caso do modo de execucao somente

compilar), essa estrutura armazena as instrucoes YAAM que compoem a clausula.

Dessa forma, nao importa se duas clausulas possuem um nome diferente, desde que a

clausula em execucao possua a mesma estrutura de outra ja armazenada em disco, a

clausula armazenada sera recuperada e imediatamente executada. Vale ressaltar que, em

vista disso, e necessario que o programa seja executado pelo menos uma vez no modo

interpretado para que a sua estrutura seja verificada.

Alem de eliminar o custo relacionado a interpretacao, profiling e compilacao, outra

vantagem da Cache e a possibilidade de compartilhar clausulas comuns entre os programas.

Programas que ainda nao foram executados podem se beneficiar da execucao nativa

imediata se sua composicao conter clausulas ja compiladas durante a execucao de outros

programas.

6.5 Consideracoes Finais

O primeiro trabalho relacionado a compilacao JIT surgiu em 1960 com McCarthy sobre

a linguagem LISP (McCarthy, 1960), em que foi verificado as primeiras possibilidades de

gerar codigo nativo em tempo de execucao a partir de um interpretador. Depois disso,

Dakin e Poole (1973) foi o primeiro trabalho a apresentar um sistema de compilacao JIT

de codigo misto, que foi baseado em medidas empıricas anteriormente apresentadas por

Knuth (1971), que afirmava que a maior parte da execucao de um programa se concentrava

em uma pequena parcela de codigo.

Mais tarde, Hansen (1974) formulou tres fundamentos basicos que formam um com-

pilador JIT eficiente. Dentre eles, a forma de selecao de unidades quentes de codigo, bem

como da estrutura de tais unidades, foram largamente estudadas ao longo dos anos e,

atualmente, diversos trabalhos acerca de tais assuntos sao conhecidos. Contudo, dentre

os princıpios apresentados por Hansen, a forma de como as unidades quentes devem ser

compiladas (ou seja, quais otimizacoes devem ser aplicadas), ainda carece de estudos. O

que comprova essa afirmacao e o fato de que a maioria dos sistemas de compilacao JIT

conhecidos aplicam otimizacoes de codigo de forma estatica. Alem disso, outro fato que

comprova e o fato de que sistemas que utilizam compilacao adaptativa, a exemplo, Jikes

RVM (Arnold et al., 2000; Burke et al., 1999), alcancam melhor desempenho na execucao

Page 146: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

143

quando otimizacoes de codigo sao aplicadas conforme o comportamento dos programas

durante a execucao.

Outro ponto consideravel, que indica a permanencia dos estudos acerca de compilacao

JIT e o surgimento de maquinas com capacidade de computacao paralela, que leva

as pesquisas na area a outro nıvel, principalmente quanto a forma que as tecnicas ja

desenvolvidas devem ser empregadas no sistema a fim de que a capacidade de computacao

desse tipo de maquina seja aproveitada da melhor forma possıvel. Atualmente, poucos

sistemas de compilacao JIT recorrem ao paralelismo (Arnold et al., 2000; Paleczny et

al., 2001; Suganuma et al., 2004), os quais seguem o modelo apresentado por (Plezbert e

Cytron, 1997). Contudo, um modelo teorico mais recente sobre o assunto foi publicado

somente em 2011, por Kulkarni.

Com relacao a Prolog, tambem e valido dizer que as pesquisas precisam nao somente

permanecer, como tambem serem aperfeicoadas, pelo fato de que a maioria das publicacoes

produzidas ate o momento tiveram foco na implementacao de linguagens imperativas.

Afinal, os resultados apresentados neste trabalho, bem como no seu antecessor (Silva

e Costa, 2007), mostraram que empregar compiladores JIT em interpretadores Prolog

realmente geram desempenho (embora nem para todos os programas). De fato, se tecnicas

elaboradas nao forem utilizadas, dificilmente os resultados alcancados serao compatıveis

com aqueles obtidos em sistemas para linguagens imperativas devido, principalmente, a

estrutura e organizacao diferenciadas de Prolog, que limitam diversas especializacoes de

codigo sem o uso de informacoes especıficas.

Page 147: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

144

REFERENCIAS

Abrams, P. S. An APL Machine. Tese de Doutoramento, Stanford, CA, USA, 1970.

Adve, V.; Lattner, C.; Brukman, M.; Shukla, A.; Gaeke, B. LLVA: A

Low-level Vitual Instruction Set Architecture. In: Proceedings of the 36th annual

IEEE/ACM International Symposium on Microarchitecture (MICRO-36), San Diego,

California: IEEE Computer Society, 2003, p. 205–216.

Agakov, F.; Bonilla, E.; Cavazos, J.; Franke, B.; Fursin, G.; O’Boyle, M.

F. P.; Thomson, J.; Toussaint, M.; Williams, C. K. I. Using Machine Learning

to Focus Iterative Optimization. In: Proceedings of the International Symposium on Code

Generation and Optimization, Washington, DC, USA: IEEE Computer Society, 2006, p.

295–305.

Aho, A. V.; Johnson, S. C.; Ullman, J. D. Code Generation for Expressions with

Common Subexpressions. Journal of the ACM, v. 24, p. 146–160, 1977.

Aho, A. V.; Sethi, R.; Ullman, J. D. Compilers: Principles, Techniques, and

Tools. Boston, MA, USA: Addison-Wesley Longman Publishing Co., Inc., 1986.

Ancona, D.; Ancona, M.; Cuni, A.; Matsakis, N. D. RPython: a Step Towards

Reconciling Dynamically and Statically Typed OO Languages. In: Proceedings of the

Symposium on Dynamic Languages, Montreal, Quebec, Canada: ACM, 2007, p. 53–64.

Arnold, K.; Gosling, J.; Holmes, D. The Java(TM) Programming Language (4th

Edition). Addison-Wesley Professional, 2005.

Arnold, M.; Fink, S.; Grove, D.; Hind, M.; Sweeney, P. F. Adaptive Optimiza-

tion in the Jalapeno JVM. In: Proceedings of the ACM Conference on Object-Oriented

Programming, Systems, Languages, and Applications, Minneapolis, Minnesota, United

States: ACM, 2000, p. 47–65.

Page 148: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

145

Arnold, M.; J., F. S.; D., G.; M., H.; F., S. P. A Survey of Adaptive Optimization

in Virtual Machines. In: Proceedings of the IEEE. Special Issue on Program Generation,

Optimization, and Adaptation, 2004.

Aıt-Kaci, H. Warren’s Abstract Machine – A Tutorial Reconstruction. Cambridge:

MIT Press, 1991.

Aycock, J. A Brief History of Just-In-Time. ACM Computing Surveys, v. 35,

p. 97–113, 2003.

Bacon, D. F.; Graham, S. L.; Sharp, O. J. Compiler Transformations for

High-Performance Computing. ACM Computing Surveys, v. 26, p. 345–420, 1994.

Bala, V.; Duesterwald, E.; Banerjia, S. Dynamo: a Transparent Dynamic

Optimization System. In: Proceedings of the ACM Conference on Programming Language

Design and Implementation, Vancouver, British Columbia, Canada: ACM, 2000, p. 1–12.

Bolz, C. F.; Cuni, A.; Fijalkowski, M.; Rigo, A. Tracing the Meta-Level:

PyPy’s Tracing JIT Compiler. In: Proceedings of the Workshop on the Implementation,

Compilation, Optimization of Object-Oriented Languages and Programming Systems,

Genova, Italy: ACM, 2009, p. 18–25.

Bonzini, P. GNU Lightning. Disponıvel em http://www.gnu.org/s/lightning/

manual/lightning.html. Acesso em: 13 set. 2012, ????

Brandis, M. M.; Mossenbock, H. Single-pass Generation of Static

Single-Assignment Form for Structured Languages. ACM Transactions on Programming

Languages and Systems, v. 16, p. 1684–1698, 1994.

Brown, P. J. Throw-Away Compiling. Software: Practice and Experience, v. 6, n. 3,

p. 423–434, 1976.

Bruening, D.; Duesterwald, E. Exploring Optimal Compilation Unit Shapes

for an Embedded Just-In-Time Compiler. In: Proceedings of the ACM Workshop on

Feedback-Directed and Dynamic Optimization, Monterey, California, 2000, p. 13–20.

Burke, M. G.; Choi, J.-D.; Fink, S.; Grove, D.; Hind, M.; Sarkar, V.;

Serrano, M. J.; Sreedhar, V. C.; Srinivasan, H.; Whaley, J. The Jalapeno

Dynamic Optimizing Compiler for Java. In: Proceedings of the ACM Conference on Java

Grande, San Francisco, California, United States: ACM, 1999, p. 129–141.

Page 149: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

146

Campanoni, S.; Agosta, G.; Reghizzi, S. C. A Parallel Dynamic Compiler for CIL

Bytecode. SIGPLAN Notices, v. 43, p. 11–20, 2008.

Campanoni, S.; Agosta, G.; Reghizzi, S. C.; Di Biagio, A. A Highly Flexible,

Parallel Virtual Machine: Design and Experience of ILDJIT. Software–Practice &

Experience, v. 40, p. 177–207, 2010.

Campanoni, S.; Sykora, M.; Agosta, G.; Reghizzi, S. C. Dynamic Look Ahead

Compilation: A Technique to Hide JIT Compilation Latencies in Multicore Environment.

In: Proceedings of the International Conference on Compiler Construction: Held as Part

of the Joint European Conferences on Theory and Practice of Software, Berlin, Heidelberg:

Springer-Verlag, 2009, p. 220–235.

Carlsson, M. Freeze, Indexing, and Other Implementation Issues in the WAM. In:

Proceedings of the International Conference on Logic Programming, MIT Press, 1987, p.

40–58.

Carlsson, M. On the Efficiency of Optimising Shallow Backtracking in Compiled

Prolog. In: Proceedings of the International Conference on Logic Programming, Lisbon,

Portugal: MIT Press, 1989, p. 3–16.

Carlsson, M.; Mildner, P. SICSTUS Prolog – The First 25 Years. Theory and

Practice of Logic Programming, v. 12, n. 1-2, p. 35–66, 2012.

Casanova, M. A.; Giorno, F. A. C.; Furtado, A. L. Programacao em Logica e

a Linguagem Prolog. 1 ed. Sao Paulo, Brasil: Edgard Blucher LTDA, 1987.

Cavazos, J.; O’Boyle, M. F. P. Automatic Tuning of Inlining Heuristics. In:

Proceedings of the ACM/IEEE Conference on Supercomputing, Washington, DC, USA:

IEEE Computer Society, 2005, p. 14–24.

Cavazos, J.; O’Boyle, M. F. P. Method-Specific Dynamic Compilation Using

Logistic Regression. In: Proceedings of the ACM Conference on Object-oriented

Programming Systems, Languages, and Applications, Portland, Oregon, USA: ACM, 2006,

p. 229–240.

Chambers, C.; Ungar, D. Customization: Optimizing Compiler Technology for

SELF, a Dynamically-Typed Object-Oriented Programming Language. In: Proceedings

of the ACM Conference on Programming language Design and Implementation, Portland,

Oregon, United States: ACM, 1989, p. 146–160.

Page 150: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

147

Chambers, C.; Ungar, D. Iterative Type Analysis and Extended Message Splitting:

Optimizing Dynamically-Typed Object-Oriented Programs. In: Proceedings of the

Conference on Programming Language Design and Implementation, 1990, p. 150–164.

Chambers, C. D. The Design and Implementation of the SELF Compiler, an Opti-

mizing Compiler for Object-Oriented Programming Languages. Tese de Doutoramento,

Department of Computer Science, Stanford, CA, USA, 1992.

Chang, M.; Smith, E.; Reitmaier, R.; Bebenita, M.; Gal, A.; Wimmer, C.;

Eich, B.; Franz, M. Tracing for Web 3.0: Trace Compilation for the Next Generation

Web Applications. In: Proceedings of the ACM International Conference on Virtual

Execution Environments, Washington, DC, USA: ACM, 2009, p. 71–80.

Chen, W.; Warren, D. S. Query Evaluation under the Well-founded Semantics.

In: Proceedings of the ACM SIGACT-SIGMOD-SIGART Symposium on Principles of

Database Systems, Washington, D.C., United States: ACM Press, 1993, p. 168–179.

Cierniak, M.; Lueh, G.-Y.; Stichnoth, J. M. Practicing JUDO: Java Under

Dynamic Optimizations. In: Proceedings of the ACM Conference on Programming

language Design and Implementation, Vancouver, British Columbia, Canada: ACM, 2000,

p. 13–26.

Cochran, W. G. Sampling Techniques. 3 ed. Wiley India Pvt. Limited, 2007.

Colmerauer, A. An introduction to prolog iii. Commun. ACM, v. 33, n. 7, p. 69–90,

1990.

Colmerauer, A.; Roussel, P. History of programming languages. New York, NY,

USA: ACM, 331–367 p., 1996.

Conway, T.; Henderson, F.; Somogyi, Z. Code Generation for Mercury. In:

Proceedings of International Logic Programming Symposium, Portland, Oregon, USA,

1995, p. 242–256.

Disponıvel em citeseer.nj.nec.com/conway94code.html

Costa, V. S. Optimising Bytecode Emulation for Prolog. In: Proceedings of the

International Conference on Principles and Practice of Declarative Programming, London,

UK, UK: Springer-Verlag, 1999, p. 261–277.

Page 151: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

148

Costa, V. S. On Just in Time Indexing of Dynamic Predicates in Prolog. In:

Proceedings of the Portuguese Conference on Artificial Intelligence: Progress in Artificial

Intelligence, Berlin, Heidelberg: Springer-Verlag, 2009, p. 126–137.

Costa, V. S.; Rocha, R.; Damas, L. The YAP Prolog System. Theory and Practice

of Logic Programming, v. 12, n. 1-2, p. 5–34, 2012.

Costa, V. S.; Sagonas, K.; Lopes, R. Demand-driven Indexing of Prolog Clauses.

In: Proceedings of the International Conference on Logic Programming, Porto, Portugal:

Springer-Verlag, 2007, p. 395–409.

Cramer, T.; Friedman, R.; Miller, T.; Seberger, D.; Wilson, R.; Wolczko,

M. Compiling Java Just in Time. IEEE Micro, v. 17, p. 36–43, 1997.

Cytron, R.; Ferrante, J.; Rosen, B. K.; Wegman, M. N.; Zadeck, F. K.

Efficiently Computing Static Single Assignment Form and the Control Dependence Graph.

ACM Transactions on Programming Languages and Systems, v. 13, p. 451–490, 1991.

Dakin, R. J.; Poole, P. C. A Mixed Code Approach. The Computer Journal, v. 16,

n. 3, p. 219–222, 1973.

Deutsch, L. P.; Schiffman, A. M. Efficient Implementation of the Smalltalk-80

System. In: Proceedings of the ACM Symposium on Principles of Programming

Languages, Salt Lake City, Utah, United States: ACM, 1984, p. 297–302.

Diaz, D.; Abreu, S.; Codognet, P. On the Implementation of GNU Prolog. Theory

and Practice of Logic Programming, v. 12, n. 1-2, p. 253–282, 2012.

Flynt, C. Tcl/Tk: A Developer’s Guide. 1 ed. New York, USA: Elsevier Science,

2012.

Gal, A.; Eich, B.; Shaver, M.; Anderson, D.; Mandelin, D.; Haghighat,

M. R.; Kaplan, B.; Hoare, G.; Zbarsky, B.; Orendorff, J.; Ruderman,

J.; Smith, E. W.; Reitmaier, R.; Bebenita, M.; Chang, M.; Franz, M.

Trace-Based Just-In-Time Type Specialization for Dynamic Languages. In: Proceedings

of the ACM Conference on Programming language Design and Implementation, Dublin,

Ireland: ACM, 2009, p. 465–478.

Gal, A.; Probst, C. W.; Franz, M. HotpathVM: an Effective JIT Compiler

for Resource-Constrained Devices. In: Proceedings of the International Conference on

Virtual Execution Environments, Ottawa, Ontario, Canada: ACM, 2006, p. 144–153.

Page 152: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

149

Goldberg, A.; Robson, D. Smalltalk-80: the Language and its Implementation.

Boston, MA, USA: Addison-Wesley Longman Publishing Co., Inc., 1983.

Gupta, G. Multiprocessor Execution of Logic Programs. Norwell, MA, USA: Kluwer

Academic Publishers, 1994.

Hank, R. E.; Hwu, W.-M. W.; Rau, B. R. Region-Based Compilation: an

Introduction and Motivation. In: Proceedings of the International Symposium on

Microarchitecture, Ann Arbor, Michigan, United States: IEEE Computer Society Press,

1995, p. 158–168.

Hansen, G. J. Adaptive Systems for the Dynamic Run-Time Optimization of Programs.

Tese de Doutoramento, Pittsburgh, PA, USA, 1974.

Haygood, R. C. Native Code Compilation in SICStus Prolog. 1 ed. New York, USA:

MIT Press, 1994.

Henderson, F.; Somogyi, Z. Compiling Mercury to High-Level C Code. In:

Proceedings of the International Conference on Compiler Construction, London, UK:

Springer-Verlag, 2002, p. 197–212.

Hermenegildo, M. V.; Bueno, F.; Carro, M.; Lıpez-Garcıa, P.; Mera, E.;

Morales, J. F.; Puebla, G. An Overview of CIAO and its Design Philosophy.

Theory and Practice of Logic Programming, v. 12, n. 1-2, p. 219–252, 2012.

Hickey, T.; Mudambi, S. Global Compilation of Prolog. Journal of Logic

Programming, v. 7, n. 3, p. 193–230, 1989.

Holzle, U. Adaptive Optimization for SELF: Reconciling High Performance with

Exploratory Programming. Tese de Doutoramento, Stanford, CA, USA, 1995.

Holzle, U.; Ungar, D. A Third-Generation SELF Implementation: Reconciling

Responsiveness with Performance. In: Proceedings of the ninth annual Conference on

Object-oriented Programming Systems, Language, and Applications, Portland, Oregon,

United States: ACM, 1994, p. 229–243.

Homescu, A.; Suhan, A. HappyJIT: a Tracing JIT Compiler for PHP. In:

Proceedings of the 7th Symposium on Dynamic Languages, Portland, Oregon, USA: ACM,

2011, p. 25–36.

Page 153: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

150

Horn, A. On Sentences Which are True of Direct Unions of Algebras. Journal of

Symbolic Logic, v. 16, n. 1, p. 14–21, 1951.

Hoste, K.; Georges, A.; Eeckhout, L. Automated Just-In-Time Compiler

Tuning. In: Proceedings of the 8th annual IEEE/ACM International Symposium on

Code Generation and Optimization, Toronto, Ontario, Canada: ACM, 2010, p. 62–72.

Ishizaki, K.; Takeuchi, M.; Kawachiya, K.; Suganuma, T.; Gohda, O.;

Inagaki, T.; Koseki, A.; Ogata, K.; Kawahito, M.; Yasue, T.; Ogasawara,

T.; Onodera, T.; Komatsu, H.; Nakatani, T. Effectiveness of Cross-Platform Op-

timizations for a Java Just-in-time Compiler. In: Proceedings of the ACM Conference on

Object-oriented Programing, Systems, Languages, and Applications, Anaheim, California,

USA: ACM, 2003, p. 187–204.

Kotzmann, T.; Wimmer, C.; Mossenbock, H.; Rodriguez, T.; Russell, K.;

Cox, D. Design of the Java HotSpot Client Compiler for Java 6. ACM Transactions

on Architecture and Code Optimization, v. 5, p. 1–32, 2008.

Kowalski, R. A. The Early Years of Logic Programming. Communications of the

ACM, v. 31, p. 38–43, 1988.

Krintz, C. Coupling On-Line and Off-Line Profile Information to Improve Program

Performance. In: Proceedings of the International Symposium on Code Generation and

Optimization: Feedback-Directed and Runtime Optimization, San Francisco, California:

IEEE Computer Society, 2003, p. 69–78.

Kulkarni, P. A. JIT Compilation Policy for Modern Machines. In: Proceedings of

the ACM International Conference on Object Oriented Programming Systems Languages

and Applications, Portland, Oregon, USA: ACM, 2011, p. 773–788.

Kulkarni, P. A.; Arnold, M.; Hind, M. Dynamic Compilation: the Benefits of

Early Investing. In: Proceedings of the International Conference on Virtual Execution

Environments, San Diego, California, USA: ACM, 2007, p. 94–104.

Kumar, K. V. S. When and What to Compile/Optimize in a Virtual Machine? ACM

SIGPLAN Notices, v. 39, p. 38–45, 2004.

Lattner, C.; Adve, V. LLVM: A Compilation Framework for Lifelong Program

Analysis & Transformation. In: Proceedings of the International Symposium on Code

Generation and Optimization, Palo Alto, California: IEEE Computer Society, 2004, p.

75–86.

Page 154: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

151

Lee, S.-W.; Moon, S.-M.; Kim, S.-M. Enhanced Hot Spot Detection Heuristics for

Embedded Java Just-In-Time Compilers. In: Proceedings of the ACM Conference on

Languages, Compilers, and Tools for Embedded Systems, Tucson, AZ, USA: ACM, 2008,

p. 13–22.

Lindholm, T.; Yellin, F. Java Virtual Machine Specification. 2nd ed. Boston,

MA, USA: Addison-Wesley Longman Publishing Co., Inc., 1999.

Lloyd, J. W. Foundations of logic programming; (2nd extended ed.). New York, NY,

USA: Springer-Verlag New York, Inc., 1987.

Lloyd, J. W. Practical Advantages of Declarative Programming. In: Proceedings of

the Joint Conference on Declarative Programming, 1994, p. 1–15.

Lopes, R. N. d. S. Execucao de Prolog com Alto Desempenho. Dissertacao de

Mestrado, Universidade do Minho, Braga, Portugal, 1996.

Lougher, R. Jam Virtual Machine. Disponıvel em http://jamvm.sourceforge.net/.

Acesso em: 13 set. 2012, ????

Lutz, M.; Ascher, D. Aprendendo Python. Porto Alegre, PR, Brasil: Bookman,

2007.

Marien, A. An Optimal Intermediate Code for Structure Creation in a WAM-based

Prolog Implementation. Relatorio Tecnico T1988:01, Katholicke Universiteit Leuven,

Heverlee, Belgium, 1988.

Martins, A. L.; Silva, A. F. d. Benchmarking Prolog Interpreters. IEEE Latin

America Transactions, v. 9, n. 7, p. 1079–1086, 2011.

McCarthy, J. Recursive Functions of Symbolic Expressions and Their Computation

by Machine, Part I. Communications of the ACM, v. 3, n. 4, p. 184–195, 1960.

Meier, M. Compilation of Compound Terms in Prolog. In: Proceedings of the North

American Conference on Logic Programming, Austin, Texas, United States: MIT Press,

1990, p. 63–79.

Mellish, C. S. The Automatic Generation of Mode Declarations for Prolog Programs.

Logic programming for Intelligent Systems, v. 13, n. 2-3, p. 103–179, 1981.

Mellish, C. S. Some Global Optimizations for a Prolog Compiler. Journal of Logic

Programming, v. 1, p. 43–66, 1985.

Page 155: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

152

Mitchell, J. G.; Perlis, A. J.; Van Zoeren, H. R. LC2: A Language for

Conversational Computing. In: Proceedings of 1967 ACM Symposium, New York, NY,

USA: Academic Press, 1968.

Morales, J.; Carro, M.; Hermenegildo, M. Improved Compilation of Prolog to

C Using Moded Types and Determinism Information. In: Proceedings of the Colloquium

on Implementation of Constraint and Logic Programming Systems, 2003, p. 197–212.

Disponıvel em citeseer.nj.nec.com/henderson01compiling.html

Muchnick, S. S. Advanced Compiler Design and Implementation. San Francisco, CA,

USA: Morgan Kaufmann Publishers, 1997.

Muthukumar, K.; Hermenegildo, M. Compile-time Derivation of Variable

Dependency Using Abstract Interpretation. Journal of Logic Programming, v. 13, n.

2-3, p. 315–347, 1992.

Namjoshi, M. A.; Kulkarni, P. A. Novel Online Profiling for Virtual Machines.

In: Proceedings of the ACM International Conference on Virtual Execution Environments,

Pittsburgh, Pennsylvania, USA: ACM, 2010, p. 133–144.

Nassen, H. Optimizing the SICStus Prolog Virtual Machine Instruction Set. Relatorio

Tecnico T2000:01, Intelligent Systems Laboratory, Uppsala University, Uppsala, Sweden,

2001.

Paleczny, M.; Vick, C.; Click, C. The Java Hotspot Server Compiler. In:

Proceedings of the Java Virtual Machine Research and Technology Symposium, Monterey,

CA, USA, 2001, p. 1–12.

Pall, M. LuaJIT. Disponıvel em http://luajit.org. Acesso em: 13 set. 2012, ????

Patterson, D. A.; Hennessy, J. L. Organizacao e projeto de computadores: Interface

hardware e software. 3 ed. Rio de Janeiro: Campus, 800 p., 2005.

Pettersson, M.; Sagonas, K. F.; Johansson, E. The HiPE/x86 Erlang Compiler:

System Description and Performance Evaluation. In: Proceedings of the International

Symposium on Functional and Logic Programming, London, UK: Springer-Verlag, 2002,

p. 228–244.

Plezbert, M. P.; Cytron, R. K. Does “Just In Time” = “Better Late than Never”?

In: Proceedings of the ACM Symposium on Principles of Programming Languages, Paris,

France: ACM, 1997, p. 120–131.

Page 156: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

153

Puebla, G.; Albert, E.; Hermenegildo, M. Abstract Interpretation with

Specialized Definitions. In: Proceedings of the International Conference on Static

Analysis, Berlin, Heidelberg: Springer-Verlag, 2006, p. 107–126.

Puebla, G.; de la Banda, M. J. G.; Marriott, K.; Stuckey, P. J. Optimization

of Logic Programs with Dynamic Scheduling. In: Proceedings of the International

Conference on Logic Programming, Cambridge: MIT Press, 1997, p. 93–107.

Puebla, G.; Hermenegildo, M. Implementation of Multiple Specialization in Logic

Programs. In: Proceedings of the ACM SIGPLAN Symposium on Partial Evaluation and

Semantics-based Program Manipulation, La Jolla, California, United States: ACM, 1995,

p. 77–87.

Quintano, L.; Rodrigues, I. Using a Logic Programming Framework to Control

Database Query Dialogues in Natural Language. In: Proceedings of the International

Conference on Logic Programming, Seattle, WA: Springer-Verlag, 2006, p. 406–420.

Ramakrishnan, C. R.; Ramakrishnan, I. V.; Warren, D. S. Deductive

Spreadsheets Using Tabled Logic Programming. In: Proceedings of the International

Conference on Logic Programming, Seattle, WA: Springer-Verlag, 2006, p. 391–405.

Reinholtz, K. Java will be Faster than C++. ACM SIGPLAN Notices, v. 35,

p. 25–28, 2000.

Rigo, A.; Pedroni, S. PyPy’s Approach to Virtual Machine Construction. In:

Proceedings of the ACM Symposium on Object-oriented Programming Systems, Languages,

and Applications, Portland, Oregon, USA: ACM, 2006, p. 944–953.

Ritchie, D. M. The Development of the C Language. In: The second ACM SIGPLAN

Conference on History of Programming Languages, Cambridge, Massachusetts, USA:

ACM, 1993, p. 201–208.

Rocha, R.; Silva, F. M. A.; Costa, V. S. On a Tabling Engine That Can Exploit

Or-Parallelism. In: Proceedings of the International Conference on Logic Programming,

London, UK, UK: Springer-Verlag, 2001, p. 43–58.

Romer, T. H.; Lee, D.; Voelker, G. M.; Wolman, A.; Wong, W. A.; Baer,

J.-L.; Bershad, B. N.; Levy, H. M. The Structure and Performance of Interpreters.

In: Proceedings of the International Conference on Architectural Support for Programming

Languages and Operating Systems, Cambridge, Massachusetts, USA: ACM Press, 1996,

p. 150–159.

Page 157: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

154

Saglam, H.; Gallagher, J. P. Approximating Constraint Logic Programs Using

Polymorphic Types and Regular Descriptions. Relatorio Tecnico CSTR-95-17, Depart-

ment of Computer Science, University of Bristol, Bristol, UK, UK, 1995.

Sagonas, K. F.; Swift, T.; Warren, D. S. The XSB Programming System. In:

Proceedings of the Workshop on Programming with Logic Databases, Vancouver, British

Columbia, Canada, 1993, p. 164–195.

Santos, H. N.; Alves, P.; Costa, I.; Quintao Pereira, F. M. Just-in-time Value

Specialization. In: Proceedings of the International Symposium on Code Generation and

Optimization, Washington, DC, USA: IEEE Computer Society, 2013, p. 1–11.

Scott, M. L. Programming languages pragmatics. San Francisco, CA, USA: Morgan

Kaufmann Publishers, 2009.

Sebesta, R. W. Concepts of programming languages. San Francisco, CA, USA:

Addison Wesley, 2009.

Serrano, M. Inline Expansion: When and How? In: Proceedings of the Interna-

tional Symposium on Programming Languages: Implementations, Logics, and Programs,

London, UK: Springer-Verlag, 1997, p. 143–157.

Shiflett, C. HTTP Developer’s Handbook. 1 ed. New York, USA: Smas Publishing,

2003.

Shootout The Computer Language Benchmarks Game. Disponıvel em http://

benchmarksgame.alioth.debian.org/. Acesso em: 29 jan. 2013, ????

Silva, A. F. d. Projeto e Implementacao do Compilador YAPc: Um Compilador

Otimizador para Linguagens de Programacao em Logica. Tese de Doutoramento,

Universidade Federal do Rio de Janeiro, Rio de Janeiro, RJ, Brasil, 2006.

Silva, A. F. d.; Costa, V. S. Our Experiences with Optimizations in Sun’s Java

Just-In-Time Compilers. Journal of Universal Computer Science, v. 12, n. 7, p. 788–810,

2006.

Silva, A. F. d.; Costa, V. S. Design, Implementation, and Evaluation of a Dynamic

Compilation Framework for the YAP System. In: Proceedings of the International

Conference on Logic Programming, Porto, Portugal: Springer-Verlag, 2007, p. 410–424.

Page 158: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

155

Silva, S. M. HTML 5 - A Linguagem de Marcacao que Revolucionou. 1 ed. Rio de

Janeiro, Brasil: NOVATEC, 2011.

Sreedhar, V. C.; Ju, R. D.-C.; Gillies, D. M.; Santhanam, V. Translating Out

of Static Single Assignment Form. In: Proceedings of the International Symposium on

Static Analysis, London, UK: Springer-Verlag, 1999, p. 194–210.

Stallings, W. Arquitetura e organizacao de computadores. 8 ed. Porto Alegre:

Prentice Hall, 640 p., 2005.

Sterling, L.; Shapiro, E. The Art of Prolog: Advanced Programming Techniques.

2 ed. Cambridge, MA, USA: MIT Press, 1994.

Stroustrup, B. Princıpios e Praticas de Programacao C++. 1 ed. Porto Alegre,

Brasil: Bookman, 2011.

Suganuma, T.; Ogasawara, T.; Kawachiya, K.; Takeuchi, M.; Ishizaki, K.;

Koseki, A.; Inagaki, T.; Yasue, T.; Kawahito, M.; Onodera, T.; Komatsu,

H.; Nakatani, T. Evolution of a Java Just-In-Time Compiler for IA-32 Platforms.

IBM Journal of Research and Development, v. 48, p. 767–795, 2004.

Suganuma, T.; Ogasawara, T.; Takeuchi, M.; Yasue, T.; Kawahito, M.;

Ishizaki, K.; Komatsu, H.; Nakatani, T. Overview of the IBM Java Just-in-time

Compiler. IBM Systems Journal, v. 39, p. 175–193, 2000.

Suganuma, T.; Yasue, T.; Nakatani, T. A Region-Based Compilation Technique for

a Java Just-In-Time Compiler. In: Proceedings of the ACM Conference on Programming

Language Design and Implementation, San Diego, California, USA: ACM, 2003, p.

312–323.

Suganuma, T.; Yasue, T.; Nakatani, T. A Region-Based Compilation Technique

for Dynamic Compilers. ACM Transactions on Programming Languages and Systems,

v. 28, p. 134–174, 2006.

Swift, T.; Warren, D. S. Compiling OLDT Evaluation: Background and Overview.

Relatorio Tecnico 92/04, SUNY Stony Brook, 1992.

Swift, T.; Warren, D. S. Performance of Sequential SLG Evaluation. In:

Proceedings of the Symposium on Logic Programming, MIT Press, 1993, p. 219–238.

Page 159: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

156

Swift, T.; Warren, D. S. XSB: Extending Prolog with Tabled Logic Programming.

Theory and Practice of Logic Programming, v. 12, n. 1-2, p. 157–187, 2012.

Tanenbaum, A. S. Modern Operating Systems. 3 ed. Upper Saddle River, NJ, USA:

Prentice Hall Press, 2007.

Tarau, P. A Compiler and a Simplified Abstract Machine for the Execution of Binary

Metaprograms. In: Proceedings of the Logic Programming Conference, London, UK, UK:

Springer-Verlag, 1991, p. 119–128.

Taylor, A. Parma – Bridging the Performance GAP Between Imperative and Logic

Programming. Journal of Logic Programming, v. 29, n. 1-3, p. 5–16, 1996.

Triantafyllis, S.; Vachharajani, M.; Vachharajani, N.; August, D. I. Com-

piler optimization-Space Exploration. In: Proceedings of the International Symposium

on Code Generation and Optimization: Feedback-Directed and Runtime Optimization, San

Francisco, California: IEEE Computer Society, 2003, p. 204–215.

Troncon, R.; Janssens, G.; Demoen, B.; Vandecasteele, H. Fast Frequent

Querying with Lazy Control Flow Compilation. Theory and Practice of Logic Program-

ming, v. 7, n. 4, p. 481–498, 2007.

Turk, A. K. Compiler Optimizations for the WAM. In: Proceedings of the

International Conference on Logic Programming, London, UK, UK: Springer-Verlag, 1986,

p. 657–662.

Tyma, P. Why Are We Using Java Again? Communications of the ACM, v. 41,

p. 38–42, 1998.

Van Roy, P. A Prolog Compiler for the PLM. Relatorio Tecnico UCB/CSD 84/203,

University of California, Berkeley, California, USA, 1984.

Van Roy, P. An Intermediate Language to Support Prolog’s Unification. In:

Proceedings of North American Conference on Logic Programming, Cleveland, Ohio, USA:

MIT Press, 1989, p. 1148–1164.

Van Roy, P. Can Logic Programming Execute as Fast as Imperative Programming?

Tese de Doutoramento, Berkeley, California, USA, 1990.

Van Roy, P. 1983-1993: The Wonder Years of Sequential Prolog Implementation.

”Journal of Logic Programming”, v. 29, n. 1-3, p. 5–16, 1994.

Page 160: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

157

Van Roy, P.; Demoen, B.; Willems, Y. D. Improving the Execution Speed of

Compiled Prolog with Modes, Clause Selection, and Determinism. In: Proceedings of

the Theory and Practice of Software Development, v. 250, Springer Berlin Heidelberg, p.

111–125, 1987.

Van Roy, P.; Despain, A. M. High-Performance Logic Programming with the

Aquarius Prolog Compiler. IEEE Computer, v. 25, n. 1, p. 54–68, 1992.

Vaucheret, C.; Bueno, F. More Precise Yet Efficient Type Inference for Logic

Programs. In: Proceedings of the International Symposium on Static Analysis, London,

UK, UK: Springer-Verlag, 2002, p. 102–116.

Warren, D. H. D. Implementing Prolog - Compiling Predicate Logic Programs.

Relatorio Tecnico 39-40, Department of Artificial Intelligence, University of Edinburgh,

1977.

Warren, D. H. D. An Abstract Prolog Instruction Set. Relatorio Tecnico 309,

Artificial Intelligence Center, SRI International, Menlo Park, U.S.A, 1983.

Warren, R.; Hermenegildo, M. V.; Debray, S. K. On the Practicality of Global

Flow Analysis of Logic Programs. In: Proceedings of the International Conference and

Symposium on Logic Programming, Seattle, Washington, USA, 1988, p. 684–699.

Whaley, J. Partial Method Compilation Using Dynamic Profile Information. In: Pro-

ceedings of the ACM Conference on Object-oriented Programming, Systems, Languages,

and Applications, Tampa Bay, FL, USA, 2001, p. 166–179.

Wielemaker, J. An Overview of the SWI-Prolog Programming Environment.

In: Proceedings of the International Workshop on Logic Programming Environments,

Heverlee, Belgium: Katholieke Universiteit Leuven, 2003, p. 1–16.

Wielemaker, J.; Schrijvers, T.; Triska, M.; Lager, T. Swi-Prolog. Theory

and Practice of Logic Programming, v. 12, n. 1-2, p. 67–96, 2012.

Wilkinson, T.; Mehlitz, P. The Kaffe Virtual Machine. Disponıvel em http:

//kaffe.org. Acesso em: 13 set. 2012, ????

Zend PHP and Zend Engine. Disponıvel em http://www.zend.com/en/community/

php/. Acesso em: 13 set. 2012, ????

Page 161: A Nova Gerac¸˜ao do YAP Prolog: Um ambiente experimental de …mestrado/diss/2013/souzaoliveira.pdf · 2013. 10. 7. · acarreta um melhor ganho de desempenho. Baseado neste contexto,

158

Zhao, C.; Wu, Y.; G., J.; Amza, C. Lengthening Traces to Improve Opportunities

for Dynamic Optimization. In: Proceedings of the Workshop on Interaction Between

Compilers and Computer Architectures, Salt Lake City, UT, 2008, p. 1–10.