• Nenhum resultado encontrado

Emprego do Perf na medição e análise do tempo de resposta de tarefas no Linux

N/A
N/A
Protected

Academic year: 2021

Share "Emprego do Perf na medição e análise do tempo de resposta de tarefas no Linux"

Copied!
110
0
0

Texto

(1)

PROGRAMA DE PÓS-GRADUAÇÃO EM ENGENHARIA DE AUTOMAÇÃO E SISTEMAS

Benhur Tessele

EMPREGO DO PERF NA MEDIÇÃO E ANÁLISE DO TEMPO DE RESPOSTA DE TAREFAS NO LINUX

Florianópolis (SC) 2019

(2)
(3)

EMPREGO DO PERF NA MEDIÇÃO E ANÁLISE DO TEMPO DE RESPOSTA DE TAREFAS NO LINUX

Dissertação submetida ao Programa de Pós-Graduação em Engenharia de Automação e Sistemas para ob-tenção do grau de “Mestre em En-genharia de Automação e Sistemas”.

Orientador: Prof. Dr. Rômulo Silva de Oliveira, UFSC.

Coorientador: Prof. Dr. Cristian

Koliver, UFSC.

Florianópolis (SC) 2019

(4)
(5)

EMPREGO DO PERF NA MEDIÇÃO E ANÁLISE DO TEMPO DE RESPOSTA DE TAREFAS NO LINUX

Esta dissertação foi julgada aprovada para a obtenção do grau de “Mestre em Engenharia de Automação e Sistemas” e aceita em sua forma final pelo Programa de Pós-Graduação em Engenharia de Auto-mação e Sistemas.

Florianópolis (SC), 01 de Março de 2019.

Prof. Dr. Werner Kraus Junior

Coordenador do Programa de Pós-Graduação em Engenharia de Automação e Sistemas

Prof. Dr. Rômulo Silva de Oliveira UFSC

Orientador

Prof. Dr. Cristian Koliver UFSC

Co-orientador

Banca Examinadora:

Prof. Dr. Marcelo Ricardo Stemmer UFSC

Profa. Dra. Patricia Della Méa Plentz

UFSC

Prof. Dr. Rafael Rodrigues Obelheiro UDESC

(6)
(7)
(8)

A minha família pelo apoio, incentivo e compreensão. Aos meus amigos e colegas pelo companheirismo e amizade. Ao meu orientador, Prof. Dr. Rômulo Silva de Oliveira, pela orientação, paciência e conhecimentos transmitidos durante a realização do trabalho.

Ao meu coorientador, Prof. Dr. Cristian Koliver, pelas sugestões e conselhos durante a realização do trabalho.

Ao Programa de Pós-Graduação em Automação e Sistemas, pela oportunidade, experiências e conhecimentos absorvidos durante essa jornada.

(9)

vêm com o trabalho. Não faço as coisas pela metade, pois daí só po-derei esperar resultados pela metade.

(10)

Este trabalho apresenta um estudo sobre a ferramenta perf, que é uma ferramenta de análise, depuração e monitoramento do Linux. Foi realizado um detalhamento sobre as principais funcionalidades do perf, juntamente com exemplos de uso da ferramenta. Também foram realizados estudos de caso com base em aplicações que representam situações reais e complexas no dia a dia dos desenvolvedores, em es-pecial aplicações com requisitos temporais. As técnicas utilizadas nos estudos de caso foram capazes de coletar dados estatísticos e validar o comportamento das aplicações, no que diz respeito aos seus tempos de resposta, e também do sistema operacional. Os resultados obtidos comprovaram a eficácia da ferramenta perf, bem como apontaram al-gumas limitações em determinados cenários de teste. Ao final deste trabalho, foram apresentadas dicas e recomendações sobre a utilização do perf para usuários e desenvolvedores.

Palavras-chave: Perf, Linux, sistemas de tempo real, sistemas

(11)

This work presents a study on the perf tool, which is a profiling and analysis tool for Linux. Some of the main perf’s features were detailed along this work, as well as usage examples. This work also introduces some case studies based on applications that represent real situations, specially real time applications. The analysis techniques used in the case studies allowed to collect statistics data in order to evaluate the applications behavior and its response times, as well as the operating system behavior. The obtained results were able of verify the potential and effectiveness of the perf tool. At the end of this work, some recommendations were provided in order to help developers to use the perf tool.

Keywords: Perf, Linux, real time systems, embedded systems,

(12)

2.1 Estrutura das distribuições Linux. . . 9

2.2 Estrutura interna do kernel. . . . 10

2.3 Estrutura dos sistemas embarcados. . . 16

3.1 Caption for LOF . . . 18

4.1 Fluxograma da rotina netio_task. . . . 45

4.2 Fluxograma da rotina netio_thread. . . . 46

4.3 Histograma de 10.000 execuções da rotina netio_task, com eixo Y em escala logarítmica. . . 48

4.4 Janela de amostras referente às 10.000 execuções da fun-ção netio_task. . . . 49

4.5 Histograma de espaçamento das execuções atípicas refe-rente às 10.000 execuções da função netio_task. . . . 49

4.6 Histograma dos tempos de resposta da função send, recv, encrypt_now e das funções fopen e fprintf juntas, com eixo Y em escala logarítmica. . . 52

4.7 Histograma dos tempos de resposta da função netio_task sem as funções fopen e fprintf, referente a 10.000 execu-ções e com eixo Y em escala logarítmica. . . 53

4.8 Histograma dos tempos de resposta da função safe_write referente a 1.000 execuções, com eixo Y em escala loga-rítmica. . . 54

4.9 Histograma de espaçamentos das execuções atípicas de-tectadas referentes à Figura 4.8. . . 55

4.10 Gráfico de janela de amostras dos eventos sched_switch, jbd2_start_commit, block_rq_issue, mmc_request_start e da rotina safe_write, respectivamente. . . . 56

4.11 Gráfico de janela de amostras dos eventos sched_switch, jbd2_start_commit, block_rq_issue, mmc_request_start e da rotina safe_write, respectivamente. . . . 58

(13)

referentes aos tempos de resposta da função pthread_mutex_lock,

com eixo Y em escala logarítmica. . . 64

4.13 Conjunto de amostras dos tempos de resposta da função

pthread_mutex_lock referente a 8 threads. . . . 65

4.14 Histograma de 100 execuções do Algoritmo 6. . . 67

4.15 Histograma de 1.000 execuções do Algoritmo 4 com 4

threads realizando 1.000 iterações cada, com eixo Y em

escala logarítmica. . . 68 4.16 Histograma de 1.000 execuções do Algoritmo 5 com 4

threads realizando 1.000 iterações cada, com eixo Y em

escala logarítmica. . . 69

4.17 Representação da memória de um processo no Linux. . . 71

4.18 Arena gerenciada pelo do procedimento malloc. . . . 72

4.19 Gráfico com três janelas de amostras: quantidade de

by-tes requisitados em kilo, número de páginas alocadas e o

tempo consumido na rotina do Algoritmo 8, respectiva-mente. . . 80 4.20 Gráfico com janelas de amostras das violações page faults

e dos tempos de resposta da rotina random_calc_task. . 82

4.21 Gráfico com janelas de amostras das L1D cache-misses, dTLB misses e dos tempos de resposta da rotina

(14)

3.1 Eventos de hardware predefinidos nas arquiteturas a

par-tir da Intel Core Duo. . . 20

3.2 Eventos de hardware genéricos das arquiteturas ARMv7

e ARMv8. . . 20

3.3 Eventos de software. . . . 22

3.4 Descrição dos principais grupos de eventos disponíveis

do tipo tracepoints do kernel. . . . 23

3.5 Subcomandos genéricos da ferramenta perf. . . 28

3.6 Lista de opções disponíveis do perf record. . . . 30

3.7 Configuração do gerenciador de frequências do Linux. . 41

4.1 Especifiações da plataforma Raspberry Pi 3 . . . 44

4.2 Eventos capturados com o perf em um cenário de

con-tenção. . . 62

4.3 Funções do kernel utilizadas associadas aos algoritmos

de alocação . . . 74

4.4 Eventos de 1 KB de alocação de memória. . . 76

4.5 Eventos capturados com o perf em um cenário de

con-tenção. . . 77

4.6 Eventos capturados com o perf em um cenário de

(15)

ID Identificador . . . i

CPU Cetral Processing Unit . . . i

I/O Input and Output . . . i

PMU Performance Monotiring Unit . . . i

PMC Performance Monotiring Counters . . . . i

PID Process Identifier . . . i

GDB GNU Debugger . . . . i

GCC GNU C Compiler . . . i

(16)

Listagens

3.1 Relação de grupo e quantidade de eventos com base no

kernel versão 4.9, arquitetura x86. . . . 22

3.2 Especificação da chamada perf_event_open. . . . 25

3.3 Lista resumida dos eventos disponíveis do perf list . . . 26

3.4 Exemplo de uso genérico do perf stat com o comando date. 27

3.5 Exemplo de uso do perf stat com o comando date e

even-tos selecionados. . . 29

3.6 Exemplo de uso do perf stat com eventos de diferentes

fontes e com o comando sleep 5. . . . 29

3.7 Exemplo de uso do perf record durante a execução da

aplicação tar e do perf report. . . . 31

3.8 Exemplo de uso do perf script e do perf record durante

a execução da aplicação tar com eventos de interrupção selecionados. . . 32

3.9 Assinatura do evento net_xmit_format. . . . 33

3.10 Exemplo de uso do perf record com a opção de filtro. . . 33

3.11 Sintaxe para definição de tracepoints dinâmicos. . . . 35

3.12 Sintaxe para definição das variáveis dos tracepoints di-nâmicos. . . 35 3.13 Exemplo de uso do perf probe para listagem das variáveis

da função selecionada. . . 36

3.14 Exemplo de uso do perf record com tracepoints dinâmicos selecionados. . . 36 3.15 Exemplo de uso do perf record com tracepoints dinâmicos

selecionados. . . 38 3.16 Exemplo de uso do perf record com definição de grupo

de eventos. . . 38

4.1 Número de eventos de troca de contexto e chamadas

fu-tex de 1.000 execuções do Algoritmo 4. . . . 67

4.2 Número de eventos de troca de contexto e chamadas

(17)

1 Introdução 1 1.1 Contextualização . . . 1 1.2 Objetivos . . . 4 1.2.1 Objetivo geral . . . 4 1.2.2 Objetivos específicos . . . 4 1.3 Organização do trabalho . . . 5 2 Conceitos básicos 6 2.1 Linux . . . 6 2.1.1 História . . . 6 2.1.2 Características do Linux . . . 7 2.1.3 Estrutura do Linux . . . 8 2.1.4 Estrutura do kernel . . . 9

2.2 Sistemas de tempo real . . . 11

2.2.1 Definição . . . 11

2.2.2 Conceitos básicos . . . 13

2.3 Sistemas embarcados . . . 14

2.3.1 Definição . . . 14

2.3.2 Estrutura dos sistemas embarcados . . . 15

2.3.3 Características dos sistemas embarcados . . . 15

3 A ferramenta Perf 17 3.1 Definição . . . 17 3.2 Eventos . . . 17 3.2.1 Eventos de hardware . . . . 19 3.2.2 Eventos de software . . . 21 3.2.3 Tracepoints estáticos . . . . 22 3.2.4 Tracepoints dinâmicos . . . . 24

3.3 Design da ferramenta de coleta de eventos . . . . 24

3.4 Exemplos de uso . . . 26

(18)

3.5 Diretrizes para instalação e configuração do perf . . . . 39

3.5.1 Configuração do kernel . . . 39

3.5.2 Bibliotecas do espaço usuário . . . 40

3.5.3 Instalação do perf . . . 40

3.5.4 Escala de frequência da CPU . . . 40

4 Estudos de Caso 43 4.1 Plataforma Alvo . . . 43 4.1.1 Hardware . . . 43 4.1.2 Sistema Operacional . . . 44 4.2 Aplicação netio . . . . 44 4.2.1 Descrição . . . 44 4.2.2 Resultados . . . 46

4.2.3 Análise detalhada dos tempos da netio_task . . 50

4.2.4 Implementação de thread para escrita . . . 51

4.2.5 Exploração das execuções atípicas da safe_write 54 4.2.6 Conclusão . . . 57

4.3 Análise da implementação mutex para exclusão mútua . 58 4.3.1 Mutex . . . . 59

4.3.2 Cálculo de Pi . . . 60

4.3.3 Resultados . . . 61

4.3.4 Overhead de eventos . . . . 63

4.3.5 Conclusão . . . 69

4.4 Análise do gerenciamento de memória . . . 70

4.4.1 Memória de processos . . . 70

4.4.2 Alocação dinâmica de memória . . . 71

4.4.3 Implementação da gerência de memória . . . 72

4.4.4 Testes e resultados . . . 74 4.4.5 Conclusão . . . 83 5 Conclusões 85 5.1 Sugestões de uso . . . 87 5.2 Trabalhos futuros . . . 88 Referências 89

(19)

Capítulo 1

Introdução

1.1.

Contextualização

A crescente utilização do sistema Linux no mercado de com-putadores é notória. De acordo com [W3COOK, 2016], no mercado de servidores web, cerca de 96% dos computadores integram o Linux como sistema operacional. Já no cenário dos supercomputadores, se-gundo [TOP500, 2018], dos 500 supercomputadores mais poderosos do mundo, 498 utilizam o Linux. No contexto de sistemas embarcados, o Linux está presente na indústria automotiva, sistemas de controle de tráfego, videogames, smart TVs e outros setores [ZINOUNE, 2012].

Os motivos pelas quais o Linux representa essa considerável par-cela nos sistemas computacionais estão relacionados às suas caracterís-ticas. O fato do Linux ser open source torna-o bastante atrativo para as empresas, o que resulta em popularidade. Outros aspectos importante são a portabilidade e a escalabilidade. Essas características permitem que as soluções computacionais de mercado evoluam, migrem para ou-tras plataformas, e possuam mais funcionalidades sem retrabalho no sistema operacional. Adicionalmente, a comunidade que apoia o Linux está presente no mundo todo, o que facilita a obtenção de informações para desenvolvimento e suporte de soluções e aplicações.

Ao passo que a popularidade e a utilização do Linux aumen-tam, as aplicações e soluções desenvolvidas para esse sistema opera-cional também crescem. Em alguns casos, os softwares desenvolvidos envolvem tarefas complexas, podendo até possuir requisitos temporais. Nesse contexto, as aplicações submetidas a requisitos temporais, tam-bém chamadas de sistemas de tempo real, possuem requisitos que va-riam muito com relação ao tamanho, à complexidade e à criticalidade. Logo, durante o ciclo de vida de desenvolvimento de software, é

(20)

funda-mental submetê-lo a intensivos processos de teste, os quais permitem analisar seu tempo de execução e recursos que consome do sistema.

Felizmente, existe um grande esforço por parte de diversas co-munidades de software para o desenvolvimento de ferramentas que per-mitem a análise, a depuração e o monitoramento de tarefas no Linux. Assim, é possível obter informações de qualquer parte do sistema ope-racional, bem como analisar o comportamento das aplicações que estão executando. Algumas ferramentas são facilmente manuseadas e podem fornecer informações genéricas que ajudam a depurar o sistema, como, por exemplo:

• top: é a ferramenta de monitoração em tempo real mais clássica do Linux. Com ela, é possível verificar o consumo de memória, CPU e informações individuais de processos que estão execu-tando no Linux;

• strace: esta ferramenta é utilizada junto a execução de um pro-cesso. A sua principal funcionalidade é depurar as chamadas de sistema que ocorreram durante a sua execução;

• iostat: é uma ferramenta que coleta estatísticas relacionadas às entradas e saídas do sistema e fornece informações sobre dispo-sitivos, sistema de arquivos e rede;

• dstat: é uma evolução do iostat que agrega outras funcionali-dades. Através do uso dessa ferramenta, é possível analisar o consumo de memória, CPU e atividade de entrada e saída [WI-EERS, 2016];

• tcpdump: essa ferramenta realiza a análise de pacotes que tra-fegam na rede. Ela oferece um rico conjunto de filtros e funcio-nalidades para coletar informações da rede;

• ftrace: é uma ferramenta que coleta eventos que estão estatica-mente alocados em diferentes partes do kernel. Junto aos even-tos, é possível coletar outras informações como timestamps, pro-cessos envolvidos, parâmetros das chamadas de funções do kernel e o ID da CPU associado ao evento.

As ferramentas citadas acima são facilmente instaladas no Li-nux, algumas inclusive já estão disponíveis no sistema por padrão, e possuem informações detalhadas nos seus manuais que estão disponí-veis em [KERRISK, 2017]. Embora muito úteis para análise genérica do sistema e de processos, algumas limitações surgem quando é necessário coletar informações mais específicas, como, por exemplo, o número de ciclos contados na execução de um programa, ou encontrar que parte do código do usuário está demandando mais tempo de CPU.

(21)

po-dem entregar tais funcionalidades. Por exemplo, a ferramenta OProfile permite contar quantos ciclos um programa precisou para executar, por meio da leitura dos contadores de performance da CPU (PMCs), ou até mesmo analisar a pilha de chamadas de funções (call stack) [LEVON, 2004]. Também é possível analisar o assembly do código compilado. Entretanto, existem algumas limitações associadas a esta ferramenta, como, por exemplo, a usabilidade. Em [HAAS, 2012], o autor reportou algumas dificuldades na interface da ferramenta com o usuário, bem como para portá-la para outras arquiteturas.

A ferramenta PAPI apresenta um método muito eficiente de ler contadores da CPU e calcular os índices de performance de aplicações [TERPSTRA et al., 2010]. Segundo [WEAVER, 2013], a ferramenta possui um baixo overhead associado às leituras dos PMCs que armaze-nam as informações sobre a CPU. Entretanto, a ferramenta não fornece uma interface amigável com o usuário. Suas funcionalidades estão dis-poníveis por meio da utilização da sua biblioteca, que é implementada para linguagem C. Logo, para realizar uma análise com o PAPI, deve-se implementar no código fonte as funções predefinidas da biblioteca para ter acesso às informações da CPU. Outra desvantagem do PAPI decorre do fato dos eventos disponíveis para observação estarem limi-tados à CPU somente.

Existe uma ferramenta chamada SystemTap que possui um rico conjunto de funcionalidades, como, por exemplo, depuração de cha-madas de sistemas, eventos estáticos e dinâmicos dos espaços kernel e usuário. A utilização dessa ferramenta se baseia na criação de scripts em uma linguagem de alto nível específica. Os scripts devem possuir informações do evento a ser coletado, bem como os parâmetros rela-cionados ao evento [DOMINGO; COHEN, 2013]. Devido ao fato da ferramenta ser desenvolvida para análise do espaço kernel e usuário, as informações dos contadores da CPU não são disponibilizadas para o usuário.

Já a ferramenta perf está entre as mais populares do Linux, de-vido à sua capacidade de realizar análise e monitoramento de todo sistema, incluindo aplicações do usuário, espaço kernel, e os eventos da CPU. Isso torna o perf extremamente útil, pois sua utilização permite observar todo sistema sem a necessidade de uma ferramenta externa. Outra vantagem do perf é o fato dele estar junto ao código fonte do Linux, o que faz com que a ferramenta seja constantemente aprimorada e evoluída.

O perf foi introduzido na versão 2.6.31 do kernel do Linux como uma ferramenta de análise e depuração que abstrai diferenças de

(22)

hard-ware com base em uma ferramenta genérica [ERANIAN et al., 2015].

Ele coleta informações através de eventos predefinidos. Os eventos

mensuráveis pelo perf estão presentes em diversas partes do sistema operacional, bem como contadores da CPU e programas do usuário. A utilização da ferramenta é baseada na linha de comando, onde há o comando padrão perf, junto a diversos subcomandos que possuem diferentes funcionalidades, como, por exemplo, perf list e perf stat.

Poucos artigos tratam deste tema. Por exemplo, em [WEAVER, 2013], o autor comparou o overhead do perf em relação a outras fer-ramentas, como o PAPI, no que diz respeito à tarefa de leitura dos PMCs. Também foram realizados testes com diferentes versões do

ker-nel. Os resultados desse trabalho mostraram que o perf possui um

desempenho inferior ao PAPI na leitura dos PMCs, e que as versões do

kernel também impactaram nesse desempenho. Em [CALAFIURA et

al., 2012], os autores desenvolveram uma interface gráfica para analisar os dados coletados pelo perf. Os dados são processados e dispostos em diversas informações, como, por exemplo, gráfico de chamadas de funções e número de ciclos que cada função necessitou para executar. Em [SHENDE, 1999], é realizado uma contextualização sobre algumas técnicas de depuração e monitoramento presentes no Linux. O trabalho comenta sobre a depuração por meio da leitura dos PMCs. Todavia, esse trabalho não aborda a utilização do perf.

1.2.

Objetivos

1.2.1.

Objetivo geral

Esse trabalho tem como objetivo explorar a utilização da ferra-menta perf em soluções para verificação de aplicações executando sobre o sistema operacional Linux. Adicionalmente, realizar a monitoração do sistema durante os testes realizados, coletar dados estatísticos e vali-dar o comportamento das aplicações, no aspecto temporal, e do sistema operacional. Em particular, aplicações com requisitos temporais serão consideradas especialmente importantes.

1.2.2.

Objetivos específicos

Os seguintes objetivos específicos deverão ser atendidos:

• Realizar um estudo detalhado sobre o sistema Linux e a ferra-menta perf;

(23)

• Implementar aplicações em uma plataforma alvo, a qual é com-posta do Linux somado a um sistema de hardware;

• Realizar análises que envolvem dados estatísticas através do perf, e validar o comportamento das aplicações e do sistema;

• Sugerir dicas de uso do perf aos desenvolvedores, para facilitar a tarefa de desenvolvimento e testes de software.

1.3.

Organização do trabalho

Esse trabalho possui cinco capítulos. No Capítulo 2, é realizada a revisão de conceitos básicos que são importantes e fazem parte do escopo desse trabalho. Esse capítulo aborda assuntos sobre o Linux, sistemas de tempo real e sistemas embarcados.

O Capítulo 3 introduz os conceitos associados ao perf, detalha o design do perf, no que diz respeito à forma como ele interage com o sistema operacional, e apresenta exemplos de uso da ferramenta e algumas diretrizes para sua instalação e manuseio.

No Capítulo 4 são apresentados os estudos de caso deste traba-lho, os quais envolvem uma série de análises e testes com diferentes aplicações. As aplicação implementadas envolvem uma tarefa com re-quisitos temporais, um processo multi-thread em um cenário de disputa por um recurso, bem como tarefas que utilizam as rotinas de alocação de memória padrões do Linux. Em todas as seções desse capítulo, são apresentados dados estatísticos que validam o comportamento indivi-dual das aplicações.

Por fim, o Capítulo 5 apresenta a conclusão do trabalho, onde são apresentadas informações que validam as funcionalidades da ferramenta perf bem como o estudo de caso realizado.

(24)

Capítulo 2

Conceitos básicos

Este capítulo realiza uma contextualização sobre assuntos que fazem parte do escopo deste trabalho. São apresentados conceitos sobre o Linux, no que diz respeito a sua definição e suas características, bem como os conceitos sobre sistemas de tempo real e sistemas embarcados.

2.1.

Linux

Linux pode ser definido como um sistema operacional compatível com as mais diversas arquiteturas de hardware presentes no mercado, e totalmente open source, dispondo do seu código fonte para qualquer pessoa utilizar ou realizar implementações agregadas ao código. Comu-mente, a palavra Linux é designada ao sistema operacional completo, que contempla o kernel somado ao conjunto de pacotes, programas e ferramentas GNU. Existem diversas comunidades no mundo que dis-ponibilizam sistemas operacionais personalizados que são baseados no GNU/Linux, os quais são caracterizam como distribuições do Linux.

2.1.1.

História

De acordo com [TANEBAUM; BOS, 2014], em meados da dé-cada de 1960, a indústria de computadores cresceu rapidamente, ao passo que começaram a emergir dois grandes problemas, portabilidade e reciclagem de software. Os softwares eram projetados para servir a propósitos específicos para as mais diversas aplicações do mercado e academia. Como resultado, os sistemas não possuíam portabilidade e o código tinha que ser reescrito para outras máquinas e aplicações. Esse problema dificultava muito a rotina dos usuários, dos desenvolvedores e dos fabricantes. Com base nisso, em 1969, um grupo de

(25)

desenvol-vedores do centro de pesquisa Bell Labs, que fazia parte da empresa AT&T, lançou o UNIX, um sistema operacional com recursos para ser utilizado em diversos computadores da época, resultando em um sis-tema portável, modular e reciclável. Entretanto, o código do UNIX era proprietário, o que restringia seu uso e distribuição mas também resul-tou na motivação para o desenvolvimento de software livre. Richard Stallman, um dos precursores a adotar a ideologia do software livre, em 1985 divulgou o projeto GNU, que continha um conjunto de aplicações e ferramentas compatíveis com o UNIX. No entanto, o projeto carecia de um kernel. Em 1987, Andrew S Tanebaum, autor do livro Operating

Systems: Design and Implementation, teve a oportunidade de

imple-mentar um sistema operacional baseado no UNIX com o propósito de exemplificar os conceitos abordados em seu livro. Seu sistema operaci-onal, batizado de MINIX, foi disponibilizado gratuitamente pelo autor e foi muito utilizado em projetos acadêmicos.

Com a grande popularidade e utilização do UNIX no mercado, a IEEE, em 1988, reconheceu o sistema, e padronizou sua API de co-mandos com o nome POSIX. Nesse década também ocorreu a revolução dos microcomputadores, onde grandes empresas começaram a fabricar e disponibilizar computadores e sistemas operacionais para uso pessoal, como a Apple e a Microsoft, que anunciaram o Macintosh e o Windows, respectivamente.

Finalmente, em 1991, Linus Torvalds, que era um acadêmico de ciências da computação pela Universidade de Helsinki, começou a im-plementar um sistema operacional para um projeto da faculdade. Ele começou a desenvolver o código em um sistema MINIX, e escolheu o GCC como compilador oficial. Adicionalmente, foram adotados os pa-drões POSIX e outras ferramentas GNU. No final desse trabalho, Linus nomeou seu sistema como Linux. Especialmente devido ao aspecto open

source, o Linux adquiriu rápida popularidade, e após dois anos do seu

lançamento, já haviam mais de 1200 usuários utilizando o sistema. Com o passar do tempo, o sistema foi adquirindo funcionalidades, robustez e confiabilidade, resultando no seu atual cenário.

2.1.2.

Características do Linux

Um dos principais motivos da grande popularidade e utilização do Linux está relacionado às suas características, listadas abaixo:

• Open source: o Linux possui Licença Pública GNU, que define sua principal característica, tornando-o disponível para qualquer pessoa que queira utilizá-lo, contribuir, implementar

(26)

funcionali-dades próprias e redistribuí-lo para terceiros;

• Portabilidade: existem documentações de diversas comunidades na web que mostram o processo de compilação do Linux para as diversas arquiteturas de hardware presentes na indústria; • Escalabilidade: é uma característica muito importante do Linux,

pois um sistema escalável pode ser utilizado em um espectro di-versificado de aplicações. No contexto do Linux, ele é aplicável desde sistemas embarcados, que utilizam pequenos chips de baixo consumo de potência, até grandes clusters e servidores para pro-cessamento de dados;

• Segurança: o Linux herdou as características de segurança do

UNIX, o qual é conhecido pela robustez e qualidade. Logo,

componentes de segurança como firewall e MMU são aspectos importantes nessa característica;

• Robustez: o Linux foi projetado para estar sempre executando. Ele possui um controle do escalonador de processos bem como um gerenciamento de memória muito eficiente, possibilitando ao usuário realizar as tarefas necessárias ao passo que o sistema se mantém funcional.

2.1.3.

Estrutura do Linux

As distribuições Linux possuem estrutura semelhante a um sis-tema operacional tradicional, como mostra a Figura 2.1. São definidas camadas e interfaces dentro do sistema operacional, permitindo um meio de comunicação entre o usuário e as funcionalidades do sistema.

Dentro dessa estrutura de camadas, existem uma série de compo-nentes que são essenciais para manter o sistema operacional funcional. Tais componentes são:

• Bootloader : é a parte do sistema operacional que gerencia a ini-cialização do mesmo. Para isso, ele deve conhecer os endereços dos demais componentes e carregá-los na memória principal. O GNU disponibiliza o GRUB, que é uma aplicação que realiza a incialização do Linux;

• Kernel: é a peça mais importante de todo sistema operacional. O kernel realiza a interface entre aplicações do usuário e o hard-ware. Ele é responsável por gerenciar todos recursos do sistema, como CPU, memória, rede, periféricos e disco;

• Serviços ou daemons: são aplicações que mantêm os recursos funcionando, como áudio, rede, interface gráfica. Normalmente são inicializados junto com o resto do sistema;

(27)

Modo Kernel Modo Usuário Interface de Bibliotecas Interface de Chamadas de Sistemas Interface do Usuário Hardware

(CPU, disco, memória, periféricos) Sistema operacional Linux

(gerenciamento de memória, processos, I/O, energia) Usuários

Programas e Utilitários (shell, editores, browsers) Conjunto de Bibliotecas Padrão

(open, close, read, fork, kill)

Figura 2.1: Estrutura das distribuições Linux.

• Shell: é o processo que realiza a interface com o usuário, aceita comandos em forma texto, interpreta-os e retorna o resultado para o usuário;

• Ambiente gráfico: É o lugar onde o usuário pode interagir com as funcionalidades do sistema. Permite navegar em janelas e aceita comandos através de uma interface gráfica;

• Aplicações: representa a camada de mais alto nível do sistema operacional. As aplicações existem para suprir todas necessida-des que o usuário possui.

2.1.4.

Estrutura do kernel

O kernel é o componente do sistema operacional o qual perma-nece na camada mais próxima ao hardware, interagindo com dispositi-vos I/O, memória física bem como discos e outros periféricos.

Conforme mostra a Figura 2.2, a estrutura do kernel compreende diferentes componentes. O componente de mais baixo nível contém os tratadores de interrupções de hardware e as rotinas despachantes. As interrupções ocorrem devido aos sinais e mensagens provenientes dos dispositivos físicos. Diante de uma interrupção, os processos do usuá-rio são imediatamente suspensos até a rotina de interrupção terminar. Por outro lado, as rotinas despachantes são responsáveis pela comuni-cação com os dispositivos físicos, e normalmente são implementadas na linguagem assembly pois são específicas das diferentes arquiteturas de

(28)

No nível intermediário, existem três principais componentes do

kernel: componente I/O, gerenciamento de memória e o gerenciamento

de processos. O componente I/O é responsável pelo gerenciamento de dispositivos e comunicação através de operações I/O. No nível mais baixo desse componente estão presentes os drivers do sistema. O sis-tema de arquivos, interface de rede e os terminais fazem parte do com-ponente I/O e possuem um tratamento específico por parte do kernel devido às suas características e funcionalidades. Entretanto, do ponto de vista do usuário, as três partes são abstraídas por meio do sistema de arquivos virtual, o qual permite acessar todos os dispositivos I/O por meio de arquivos.

Gerenciador de Sinais Criação e Terminação de Processos Escalonador de CPU Cache de Páginas Reposição de Páginas Memória Virtual Escalonador I/O Drivers de Bloco Camada de Bloco Sistema de arquivos Drivers de Rede Protocolos de Rede Char Drivers Terminais Gerenciamento de Processos Gerenciamento de Memória Componente I/O Interrupções Despachantes Chamadas de Sistemas

Sistema de Arquivos Virtual

Figura 2.2: Estrutura interna do kernel.

O gerenciamento de memória no Linux tem como função fornecer um conjunto de endereços virtuais para os processos do usuário, realizar mapeamento de endereços virtuais para endereços físicos, e realizar o controle de acesso nas diferentes seções de memória existentes. Para realizar essas tarefas, o Linux utiliza como base de memória páginas de 4 Kbytes (esse valor é o padrão, entretanto algumas arquiteturas suportam valores maiores).

Já o gerenciamento de processos está relacionado à criação, à terminação, à sinalização e ao escalonamento de processos e threads. Do ponto de vista do kernel, threads e processos são tratados como entidades semelhantes, pois ambos são criados por meio da chamada

(29)

interna clone. Contudo, threads possuem seções de memória compar-tilhada com o processo pai, ao passo que processos recebem um novo espaço de endereçamento igual ao do processo pai. Adicionalmente, todo processo ou thread deve possuir um valor de prioridade e uma política de escalonamento, pois estes são atributos essenciais para o escalonador do Linux.

Por fim, na camada de mais alto nível e próxima do usuário, está a interface de chamadas de sistema. Essa interface representa o meio de comunicação entre o usuário e o kernel. Nela são definidas as fun-ções POSIX, as quais os processos do usuário utilizam para requisitar funcionalidades e recursos do sistema operacional. Dentre o conjunto de funções POSIX, destacam-se as funções open, read, write, fork, kill, que são frequentemente invocadas por programas e serviços do usuário.

2.2.

Sistemas de tempo real

Embora o Linux seja apresentado como um sistema operacional de propósito geral, existem comunidades de desenvolvedores que reali-zam um esforço na implementação do suporte a tarefas de tempo real no Linux. O projeto Xenomai, por exemplo, envolve a construção de um sistema que integra um kernel adicional, o qual oferece suporte a aplicações com requisitos temporais, junto ao kernel do Linux [GE-RUM, 2019]. Também existe o projeto PREEMPT_RT, o qual consiste na adaptação do kernel do Linux para suportar tempo real [MCKEN-NEY, 2005]. Portanto, devido ao fato dos sistemas de tempo real fa-zerem parte das soluções propostas pelo Linux, é necessário realizar uma contextualização sobre esses sistemas, no que diz respeito aos seus conceitos e suas características.

2.2.1.

Definição

A expressão sistemas de tempo real é uma forma reduzida para

sistemas computacionais com requisitos de tempo real. Os sistemas de tempo real estão submetidos a requisitos de natureza temporal, ou seja, possuem a função de desempenhar uma tarefa em um prazo ou período. Por exemplo, problemas que envolvem um prazo máximo para a execução de uma dada tarefa, um período no qual dada tarefa deve ser sempre executada ou um intervalo máximo de tempo entre duas ações se caracterizam como sistemas de tempo real. [OLIVEIRA, 2018].

O principal objetivo de um sistema de tempo real é resolver um problema dentro do intervalo de tempo disponível. Quem define o

(30)

intervalo de tempo disponível, ou os requisitos temporais, é o ambiente, ou seja, os sistemas computacionais de tempo real devem ser projetados de tal forma que respeitem os requisitos temporais do ambiente ou

o meio físico em que estão expostos. Assim, os sistemas de tempo

real devem estar corretos tanto no aspecto temporal quanto no aspecto lógico.

Os requisitos temporais englobam conceitos que são tipicamente utilizados na caracterização de sistemas de tempo real. Tais conceitos são:

• Período: esse conceito é utilizado quando o sistema de tempo real deve desempenhar uma tarefa repetidamente. Assim, define-se que o sistema de tempo real é periódico;

• Deadline: diz respeito ao prazo máximo em que a tarefa deve terminar. O deadline relativo de uma tarefa está relacionado ao intervalo de tempo a partir da sua chegada, enquanto que o

deadline absoluto diz respeito ao instante no qual a tarefa deve

terminar;

• Freshness: esse conceito está relacionado à atualidade dos da-dos do sistema. Algumas aplicações exigem que os dada-dos sejam recentes para que sejam tomadas as decisões certas;

• Data fusion: esse conceito está relacionado à instrumentação de múltiplas variáveis e grandezas dentro de um intervalo de tempo máximo para que as funcionalidades do sistema não sejam comprometidas.

Com base nesses conceitos, os sistemas de tempo real podem ser classificados como críticos e não-críticos. Os sistemas de tempo real críticos são aqueles em que o não cumprimento dos requisitos temporais resulta em uma catástrofe. Em outras palavras, os sistemas críticos devem sempre cumprir seus deadlines, caso contrário o resultado será negativo para o sistema e catastrófico. Sistemas de controle aviônicos e automotivos, controle de temperatura e pressão de caldeiras e controle de processos petroquímicos são exemplos clássicos de sistemas de tempo real críticos.

Por outro lado, nos sistemas de tempo real não-críticos, as perdas de deadline podem ocorrer sem resultar em catástrofes. Entretanto, o não cumprimento dos requisitos de tempo poderá resultar na perda parcial ou total de funcionalidades. Exemplos dessa classe de sistemas de tempo real são as videoconferências, reprodutores digitais de som, videogames, etc.

Os sistemas de tempo real estão presentes em diversas áreas da indústria e do mercado. Como exemplo, pode-se citar os sistemas

(31)

au-tomatizados de manufatura das indústrias, comunicação entre rede de sensores sem fio, as unidades eletrônicas de automóveis, o setor aeroes-pacial, telecomunicações e até o mercado financeiro.

2.2.2.

Conceitos básicos

Na subseção 2.2.1, foram introduzidos alguns conceitos associa-dos aos requisitos de tempo. Todavia, os sistemas de tempo real pos-suem outras propriedades e conceitos que são utilizados na sua cons-trução e implementação. Alguns dos principais conceitos são:

• Tarefa: do ponto de vista dos sistemas operacionais, uma tarefa pode ser definida como um processo ou thread que executa no processador. Para um sistema de tempo real, uma tarefa é um programa em execução que possui uma sequência lógica para resolver um determinado problema. Os sistemas de tempo real podem possuir uma ou várias tarefas em seu contexto;

• Tipos de deadlines: os sistemas de tempo real sempre possuem

deadlines associados a eles, e os deadlines podem ser

classifica-dos conforme a consequência de seu não cumprimento em: hard

deadlines estão associados aos sistemas de tempo real críticos; firm deadlines e soft deadlines estão relacionados aos sistemas

de tempo real não-críticos. Os dois últimos tipos toleram even-tuais perdas de deadline. Entretanto, em sistemas com deadlines tipo firm, a perda de um deadline resulta na ausência de todas funcionalidade do sistema. Já nos sistemas com deadlines tipo

soft, resulta na degradação de desempenho;

• Previsibilidade: previsibilidade temporal (predictability) é uma propriedade que define a garantia do processamento lógico e cum-primento temporal dos sistemas de tempo real. A previsibilidade pode ser determinista, onde há a certeza de que todos deadlines serão cumpridos, ou estimada, onde existe uma probabilidade dos deadlines serem cumpridos;

• Escalonamento: no cenário onde o sistema de tempo real é com-posto de várias tarefas, deve existir um componente que defina a sequência de execução das tarefas. No contexto dos sistemas ope-racionais, o componente responsável por essa função é o escalona-dor. Alguns sistemas utilizam escalonadores estáticos, os quais pré-definem a sequência de execução de tarefas e essa sequência não é modificada ao longo do tempo. Outros sistemas utilizam escalonadores dinâmicos, que definem dinamicamente a sequên-cia de execução de tarefas com base em regras internas;

(32)

• Recorrência das tarefas: é a propriedade que define o

compor-tamento das execuções das tarefas ao longo do tempo. Uma

tarefa pode possuir recorrência periódica, esporádica ou aperió-dica. Uma tarefa é periódica quando suas execuções são sempre previsíveis a cada intervalo fixo de tempo. Já as tarefas esporádi-cas são aquelas onde seus instantes de chegada não são conheci-dos, mas existe um intervalo de tempo conhecido até que a tarefa solicite executar novamente. Por fim, as tarefas aperiódicas não possuem nenhuma informação sobre o instante de chegada, nem mesmo sobre possíveis chegadas futuras;

• Tempo de execução: é a quantidade de tempo em que uma tarefa utiliza os recursos do sistema computacional (processador, bar-ramento e periféricos) para executar sua sequência de instruções; • Tempo de resposta: é o intervalo de tempo entre a chegada da tarefa e sua conclusão. Nota-se que o tempo de resposta é sempre maior ou igual ao tempo de execução, pois, em alguns casos, durante a execução da tarefa pode haver interferência do sistema operacional, o que não altera seu tempo de execução, mas sim o tempo de resposta.

2.3.

Sistemas embarcados

Segundo [BIRD, 2018], o sistema Linux possui suporte a diversas plataformas embarcadas, como, por exemplo, BeagleBone, Raspberry Pi, Jeston e UDOO. Adicionalmente, existe o projeto ARM Linux que consiste na construção de drivers e o suporte do kernel do Linux para as arquiteturas ARM [KING, 2019]. Com base nesse cenário, é possível observar o grande esforço realizado para criar e manter o suporte do Linux em sistemas embarcados. Logo, nessa seção são detalhados os aspectos conceituais e as características desses sistemas.

2.3.1.

Definição

Sistema embarcado (embedded system), na definição mais clás-sica, é um dispositivo que combina hardware e software para desempe-nhar uma tarefa específica [SANKAR, 2017]. Também é muito comum os sistemas embarcados estarem associados aos sistemas de tempo real,

devido às aplicações onde eles atuam. Entretanto, os sistemas

em-barcados evoluíram bastante, e, atualmente, eles podem se assemelhar com sistemas computacionais de propósito geral, do ponto de vista do número de funcionalidades. Por exemplo, uma câmera fotográfica,

(33)

dispositivos de navegação GPS, uma lavadora de roupas com progra-mas de lavagem ou a central eletrônica de automóveis podem servir de exemplos clássicos de sistemas embarcados. Por outro lado, o mercado de smartphones, que também são considerados sistemas embarcados, evoluiu significativamente, tornando esses aparelhos ricos em funciona-lidades e até permitindo ser programáveis e reconfiguráveis pelo usuá-rio. Logo, devido à grande expansão tecnológica nos últimos anos, os sistemas embarcados atingiram um patamar onde são utilizados em di-versas aplicações, desde a de um dispositivo para desempenhar uma tarefa específica, até um sistema programável de propósito geral.

Outro fator muito importante no processo evolutivo dos sistemas embarcados é a portabilidade dos sistemas operacionais. O Linux, por exemplo, com sua grande popularidade, tornou-se portável às diversas arquiteturas embarcadas disponíveis no mercado, fato esse que facilitou o desenvolvimento e a construção desses sistemas.

2.3.2.

Estrutura dos sistemas embarcados

A estrutura de hardware dos sistemas embarcados é muito se-melhante aos sistemas computacionais, como mostra a Figura 2.3, pois ambos possuem componentes de memória, barramentos e periféricos que são interconectados com o microcontrolador ou microprocessador. Entretanto, tendo em vista o amplo espectro de aplicações dos siste-mas embarcados, é muito comum esses sistesiste-mas integrarem sensores e atuadores para desempenhar tarefas específicas, fato esse que difere dos sistemas computacionais de propósito geral [SANKAR, 2017].

Em relação ao software, é comum observar um ambiente multi-tarefas com requisitos temporais, pois o ambiente onde muitos sistemas embarcados estão inseridos possui requisitos de tempo real. Alguns

softwares são desenvolvidos especificamente para os hardwares alvo,

através de interfaces e linguagens específicas, como C, C++ e assembly. Por outro lado, existe uma tendência em aumentar a portabilidade de sistemas operacionais para sistemas embarcados, o que permite uma maior flexibilidade no desenvolvimento de aplicativos de software.

2.3.3.

Características dos sistemas embarcados

Nas aplicações mais comuns, as características presentes nos sis-temas embarcados são:

• Tarefa(s) específica(s): sistemas embarcados estão associados a desempenhar uma ou mais tarefas. As tarefas devem solucionar

(34)

Hardware Software

Micropro-cessador

Memória I/O Digitais

I/O Analógicos Tarefa 1 Tarefa 2 Periféricos Atuadores Sensores

Figura 2.3: Estrutura dos sistemas embarcados.

um ou mais problemas específicos que são conhecidos desde o início do projeto do sistema;

• Recursos restritos: o projeto de um sistema embarcado envolve a construção de um hardware e um software. Tendo em vista que as tarefas são projetadas para resolver problemas específicos, é muito comum os sistemas embarcados integrarem somente os re-cursos que são necessários para essas tarefas. Em alguns casos, a evolução de funcionalidades desses sistemas envolve a substi-tuição de hardware e software, devido às limitações impostas no projeto inicial;

• Sistemas com requisitos de tempo real: requisitos temporais e sis-temas embarcados estão fortemente acoplados em grande parte das aplicações. Isso se deve ao fato de que sistemas com re-quisitos temporais devem ser robustos e confiáveis para que de-sempenhem sua tarefa corretamente dentro dos deadlines. Logo, há casos onde existe a necessidade de projetar um dispositivo específico que cumpra com os requisitos temporais do sistema.

(35)

Capítulo 3

A ferramenta Perf

O capítulo anterior introduziu conceitos importantes que fazem parte do ambiente de desenvolvimento de aplicações e soluções no Li-nux. Com base na constante evolução, tanto do próprio Linux quanto das aplicações integradas a ele, nota-se uma grande necessidade de re-alizar a depuração e a análise desse sistema e das aplicações, no que diz respeito à identificação de eventuais falhas, gargalos de execução e recursos utilizados. O perf, que é a ferramenta de depuração oficial do Linux, é a potencial candidata para realizar essas tarefas, justamente devido a grande quantidade de funcionalidade e recursos disponíveis. Portanto, este capítulo tem como objetivo apresentar os conceitos, de-talhes e exemplos relacionados à ferramenta perf.

3.1.

Definição

O perf pode ser definido como um conjunto de ferramentas ba-seado no subsistema perf_events do kernel. Complementarmente, há um comando, cujo nome também é perf, que realiza a interface entre o usuário e o subsistema perf_events [ERANIAN et al., 2015]. O perf foi introduzido na versão 2.6.31 do kernel, no final de 2009. Deste então, a ferramenta passou por constantes evoluções e aprimoramentos até atin-gir um patamar robusto e confiável. Logo, devido ao seu rico conjunto de recursos e funcionalidades ele se tornou a ferramenta oficial do Linux para realizar análise de performance, monitoramento e instrumentação.

3.2.

Eventos

O perf é uma ferramenta de análise, monitoramento e depuração baseada em eventos, ou seja, os eventos devem ser predefinidos para

(36)

que seja possível coletá-los e processá-los durante o processo de análise. Os eventos mensuráveis pelo perf são provenientes de diversas fontes, estando presentes em grande parte dos componentes do kernel e do

hardware, como mostra a Figura 3.1. Eles podem ser classificados nos

seguintes grupos:

• Eventos de hardware: são contadores presentes no hardware que armazenam informações a respeito dos elementos da CPU, como número de ciclos, cache misses e instruções executadas;

• Eventos de software: estes eventos dizem respeito aos contado-res internos do kernel, que são incrementados na ocorrência de exceções page faults, migrações e troca de contexto, por exemplo; • Tracepoints estáticos: são eventos de software predefinidos no código do kernel e estão presentes em todos componentes do

kernel, como por exemplo eventos de mensagens TCP, driver de

bloco, escalonador, chamada de sistemas, etc;

• Tracepoints dinâmicos: também são eventos de software. Porém, estes possuem uma característica peculiar, pois são definidos di-namicamente pelo usuário através das interfaces kprobe e uprobe do kernel.

Figura 3.1: Eventos mensuráveis pelo perf no sistema.1

Vale ressalvar que o monitoramento de eventos possui limitações tanto em termos de precisão, principalmente por causa do overhead

(37)

troduzido diretamente pelo próprio monitoramento dos contadores de

hardware e pela interface usada para capturar as medidas. Está fora

dos objetivos do presente trabalho analisar esse overhead em detalhe, uma vez que que na literatura podem ser encontrados alguns trabalhos cujo escopo é exatamente tal análise. Por exemplo, [DEROSE, 2001] investigam variações e erros nas medidas dos contadores de desempe-nho em um sistema Power3 quando da inicialização e da parada. Em [WEAVER, 2015], o autor mostra que a interface perf_events pode ter uma sobrecarga grande, interferindo sobremaneira na acurácia das me-dições. Em [WEAVER; JONES, 2015], os autores realizam intensos testes na chamada de sistema perf_event_open e mostra que existem alguns bugs no kernel relacionados aos parâmetros dessa chamada.

Nas subseções seguintes, são detalhados os conceitos e caracte-rísticas de cada grupos de eventos.

3.2.1.

Eventos de hardware

Os eventos de hardware são disponibilizados pela Unidade de Monitoramento de Performance (PMU), que é um componente de de-puração e monitoramento dos processadores atuais. A PMU possui re-gistradores, os quais contam a ocorrência de diversos eventos dentro do processador, como, por exemplo, número de instruções executadas,

ca-che misses ou predição de branca-ches. Esses contadores são denominados

Contadores de Monitoramento de Performance (PMCs) ou Contadores de Instrumentação de Performance (PICs) [GREGG, 2018].

O gerenciamento da PMU no Linux é realizado pelo subsistema perf, que coleta informações sobre os eventos disponíveis, bem como configuração e leitura dos PMCs. Os eventos da PMU são específicos de cada arquitetura, o que significa que o número de eventos disponí-veis varia de acordo com o modelo e fabricante dos processadores. No entanto, algumas arquiteturas, como ARM, Intel, MIPS e ARC, dispo-nibilizam eventos predefinidos e genéricos, que são mapeados pelo perf e disponibilizados para o usuário.

De acordo com [INTEL CORPORATION, 2016], a sexta geração da família Intel Core possui eventos de hardware predefinidos os quais são mostrados na Tabela 3.1. No contexto ARM, segundo [ARM LI-MITED, 2014a] e [ARM LILI-MITED, 2014b], as arquiteturas ARMv7 e ARMv8 definem a presença de eventos genéricos de hardware, os quais são mostrados na Tabela 3.2.

A primeira e a segunda coluna das Tabelas 3.1 e 3.2 representam o código identificador de cada evento. Esse identificador é fornecido

(38)

Tabela 3.1: Eventos de hardware predefinidos nas arquiteturas a

par-tir da Intel Core Duo.

Máscara Número Nome Descrição

0x00 0x3C cycles Conta o número de ciclos de

clocks da CPU

0x00 0xC0 instructions Conta o número de

instru-ções executadas

0x01 0x3C bus-cycles Conta o número de clocks do

barramento da CPU

0x4F 0x2E cache-references Conta o número de acessos

à LLC

0x41 0x2E cache-misses Conta o número de cache

misses na LLC

0x00 0xC4 branches Conta o número de branches

preditos

0x00 0xC5 branch-misses Conta o número de branch

misses

Tabela 3.2: Eventos de hardware genéricos das arquiteturas ARMv7

e ARMv8.

Máscara Número Nome Descrição

0x00 0x11 cycles Conta o número de ciclos de

clocks da CPU

0x00 0x08 instructions Conta o número de

instru-ções executadas

0x00 0x04 cache-references Conta o número de acessos

cache L1 de dados

0x00 0x03 cache-misses Conta o número de misses

na cache L1 de dados

0x00 0x12 branches Conta o número de branches

preditos

0x00 0x10 branch-misses Conta o número de branch

misses

pelo fabricante por meio dos manuais dos processadores. Para os even-tos listados nas tabelas, o perf realiza o mapeamento do identificador e mostra para o usuário seus respectivos nomes, permitindo selecioná-los sem o identificador.

(39)

Por outro lado, a maioria das arquiteturas atuais fornece outros eventos além dos listados acima. O perf classifica estes como eventos de

cache de hardware, ou tracepoints da PMU. No contexto das

arquitetu-ras ARMv7 e ARMv8, são disponibilizados cerca de trinta eventos de

cache de hardware, como, por exemplo, eventos de acesso à memória, misses na cache L2, ciclos do barramento, etc. Já nas arquiteturas da

sexta geração da família Intel Core, existem mais de duzentos eventos de hardware disponíveis para utilizar.

Embora o subsistema perf reconheça os eventos de cache de

hard-ware, a aplicação perf que realiza a interface com o usuário não mapeia

todos esses eventos para o usuário. Logo, o acesso a esses eventos deve ser somente por meio dos identificadores que estão presentes nos ma-nuais.

Outra informação importante a respeito da PMU é o número de PMCs disponíveis. Embora a PMU possua vários eventos para depura-ção, seus contadores são limitados, fato esse que restringe a monitoração simultânea de eventos. Os processadores da sexta geração da família Intel Core possuem três PMCs fixos (só contam um tipo de evento) e dois de propósito geral. Em relação às arquiteturas ARMv7 e ARMv8, elas possuem, respectivamente, dois e seis PMCs disponíveis. Caso o número de eventos requisitados pelo usuário seja maior que o número de contadores disponíveis, o perf irá realizar a multiplexação temporal dos contadores. O perf implementa uma lista de eventos com base no algoritmo round-robin, o que permite que todos os eventos sejam con-tados. Vale ressaltar que utilizar mais eventos que contadores resulta em perda significativa da precisão e um overhead associado à multiple-xação. De acordo com [ERANIAN et al., 2015], o perf, tipicamente, utiliza como frequência de multiplexação um valor igual a 100 Hz ou 1000 Hz. Logo, a contagem de eventos multiplexados é uma aproxima-ção. Por esse motivo, é recomendável sempre utilizar uma quantidade de eventos menor ou igual ao número de contadores disponíveis.

3.2.2.

Eventos de software

Os eventos de software são caracterizados como contadores que o kernel utiliza para informar a ocorrência dos eventos e que são mos-trados na Tabela 3.3. Eles podem ser utilizados para propósito geral e estão presentes em todas versões do kernel a partir da 2.6.31.

(40)

Tabela 3.3: Eventos de software.

Nome Descrição

cpu-clock Evento de ciclos com base em timers internos

da CPU

task-clock Reporta o número de ciclos da tarefa que está

executando

page-fatuls Conta o número de violações page faults

context-switches Reporta a ocorrência de trocas de contexto

cpu-migrations Conta o número vezes que migrações de CPU

ocorreram

minor-faults São page faults sem inteferência do disco

major-faults Reporta a ocorrência de page faults que fazem

uso do disco

emulation-faults Instruções não implementadas do kernel

ge-ram emulation faults

alignment-faults Reporta as ocorrências de acessos a partes de

memória desalinhadas

dummy Contador não associado a nenhum evento

3.2.3.

Tracepoints estáticos

Os tracepoints estáticos, ou tracepoints do kernel, são baseados na interface ftrace de depuração. O perf utiliza essa interface para disponibilizar os recursos dos tracepoints do kernel. Ftrace é uma fer-ramenta de depuração interna do kernel, a qual compreende uma infra-estrutura de eventos estáticos localizados em diversas partes do kernel. Os eventos da ferramenta ftrace são disponibilizados através do sis-tema de arquivos tracefs, o qual é, normalmente, montado no diretório

/sys/kernel/debug/tracing.

Existe uma lista com inúmeros eventos, os quais são agrupados por componente do kernel. Por exemplo, os eventos associados ao es-calonador estão agrupados como sched, já os eventos de sockets são encontrados no grupo sock. A quantidade de eventos pode variar de acordo com a versão do kernel e a arquitetura. A Listagem 3.1 mostra a relação de grupos e quantidade de eventos disponíveis na versão do

kernel 4.9. A Tabela 3.5, por sua vez, mostra a lista com a descrição

dos principais grupos de eventos.

Listagem 3.1: Relação de grupo e quantidade de eventos com base

(41)

b l o c k 19 n a p i 1 c f g 8 0 2 1 1 150 net 10 c g r o u p 9 nmi 1 clk 14 oom 1 c o m p a c t i o n 14 p a g e _ i s o l a t i o n 1 c p u h p 3 p a g e m a p 2 drm 3 p o w e r 22 e x c e p t i o n s 2 p r i n t k 1 e x t 4 95 r a n d o m 15 f e n c e 8 ras 4 fib 3 r a w _ s y s c a l l s 2 f i b 6 1 rcu 1 f i l e l o c k 10 r e g m a p 15 f i l e m a p 2 rpm 4 f t r a c e 1 s c h e d 24 g p i o 2 s c s i 5 hda 5 s i g n a l 2 h d a _ c o n t r o l l e r 6 skb 3 h d a _ i n t e l 4 s o c k 2 h u g e _ m e m o r y 4 spi 7 i2c 8 s w i o t l b 1 i 9 1 5 39 s y s c a l l s 628 i o m m u 7 t a s k 2 irq 5 t h e r m a l 7 i r q _ v e c t o r s 22 t i m e r 13 j b d 2 16 tlb 1 k m e m 12 udp 1 kvm 66 v 4 l 2 6 k v m m m u 14 vb2 4 l i b a t a 6 v m s c a n 15 mce 1 v s y s c a l l 1 mei 4 w o r k q u e u e 4 m i g r a t e 2 w r i t e b a c k 30 mmc 2 x 8 6 _ f p u 14 m o d u l e 5 xen 33 mpx 5 xhci - hcd 9 msr 3

Tabela 3.4: Descrição dos principais grupos de eventos disponíveis do

tipo tracepoints do kernel.

Grupo Descrição

block Grupo de eventos associados ao driver de bloco

ext4 Grupo de eventos relacionados ao sistema de arquivos ext4

irq Grupo de eventos relacionado às interrupções do sistema

jbd2 Grupo de eventos associados ao sistema de arquivos journal

kmem Grupo de eventos associados ao gerenciamento de memória

mmc Grupo de eventos associados ao driver de barramento

net Grupo de eventos relacionado à camada IP

sched Grupo de eventos do escalonador do sistema

(42)

3.2.4.

Tracepoints dinâmicos

O perf fornece tracepoints dinâmicos, que são baseados nos me-canismos kprobes e uprobes de depuração do kernel. Esses meme-canismos permitem a adição de tracepoints em aplicações do usuário, por meio da interface uprobe, e também no código do próprio kernel, por meio da interface kprobe. Os tracepoints adicionados dinamicamente se com-portam como breakpoints, o que significa que uma interrupção é gerada quando a CPU executa um trecho de código onde foi cadastrado um

tra-cepoint. Uma vez cadastrados, os tracepoints dinâmicos são integrados

ao conjunto de eventos mensuráveis pelo perf, o que viabiliza a moni-toração destes durante as depurações. Entretanto, eles não são fixos como os tracepoints estáticos. Logo, eles permanecem visíveis enquanto o sistema está executando ou até o usuário removê-los.

3.3.

Design da ferramenta de coleta de eventos

Apesar do perf possuir um conjunto de ferramentas diversificado, a maioria das depurações de tarefas no Linux com o perf envolvem a utilização dos dois principais subcomandos de análise: perf stat e perf

record. Esses dois subcomandos têm como principal função a coleta de

eventos. O perf stat realiza a contagem de eventos durante a execução de um programa. Os eventos contados bem como o programa executado são parâmetros configurados pelo usuário. No final da execução, são mostrados para o usuário os dados estatísticos referentes aos eventos coletados.

O perf record, por sua vez, realiza a amostragem e a gravação de eventos durante a execução de um programa. Os eventos são gravados em um ring buffer no kernel, juntamente com o timestamp, símbolos, CPU e outras informações associadas à amostra. A técnica de amos-tragem utilizada pelo perf record pode assumir as seguintes opções:

• Período de contagem: é a opção que permite o usuário definir quantos eventos serão contados até ser amostrado e gravado; • Frequência: o usuário define a frequência em amostras por

se-gundo, a qual o perf utilizará para amostrar e gravar os eventos. Caso não houver nenhuma parametrização do usuário, o perf de-fine a frequência como sendo de 1000 amostras por segundo (esse valor pode variar de acordo com versão do kernel) para realizar a

amostra-gem dos eventos. Por outro lado, se o usuário definir um valor de

frequência ou período, o perf irá operar dentro dos limites do sistema para tentar atender à requisição do usuário. Isso implica que valores

(43)

de frequência maiores do que o poder computacional do sistema serão desconsiderados pelo kernel.

Após o término do programa, a aplicação perf realiza a leitura do ring buffer e escreve em um arquivo binário, o perf.data, todas in-formações coletadas. A partir disso, o usuário pode interagir com o arquivo através dos subcomandos perf report e perf script, e coletar as informações pertinentes à análise.

Apesar dos subcomandos perf stat e perf record possuirem suas peculiaridades, ambos utilizam a chamada de sistema perf_event_open, que é responsável por cadastrar no kernel o evento escolhido. A cha-mada perf_event_open, cuja especificação é mostrada na Listagem 3.2, retorna um file descriptor, o qual permite realizar outras chamadas como read e mmap para coletar as amostras que estão gravadas no

kernel.

Listagem 3.2: Especificação da chamada perf_event_open. i n t p e r f _ e v e n t _ o p e n ( s t r u c t p e r f _ e v e n t _ a t t r * attr ,

p i d _ t pid , i n t cpu , i n t g r o u p _ f d , u n s i g n e d l o n g f l a g s ) ;

Os argumentos pid e cpu da chamada perf_event_open formam uma combinação que pode assumir os seguintes valores:

• pid = 0 e cpu = -1: monitoração do processo que invocou em qualquer core da CPU;

• pid = 0 e cpu >= 0: monitoração do processo que invocou quando executado em um core específico;

• pid > 0 e cpu = -1: monitoração de um processo específico em qualquer core da CPU;

• pid > 0 e cpu >= 0: monitoração de um processo específico quando executado em um core específico;

• pid = -1 e cpu >= 0: monitoração de todos os processos em um

core específico.

O argumento group_fd permite que grupos de eventos sejam criados. Pela definição, um grupo de eventos deve conter um líder. O comportamento da amostragem, nesse caso, é orientado ao líder, ou seja, os eventos do grupo só são amostrados no instante da ocorrên-cia do evento líder. Para o evento líder, o perf deve realizar a cha-mada perf_event_open com o argumento group_fd igual a -1. Para os demais eventos que fazem parte do grupo, o perf deverá invocar a

perf_event_open com o argumento group_fd igual ao file descriptor

que a primeira chamada retornou.

O argumento attr é um ponteiro da estrutura perf_event_attr, a qual contém informações pertinentes ao evento. Essa estrutura possui

(44)

um conjunto de variáveis que caracterizam o evento selecionado. Dentre as variáveis presentes na estrutura perf_event_attr pode se destacar as seguintes:

• type: representa o tipo do evento (hardware, software, tracepoint, etc.);

• config: contém o nome do evento selecionado (cycles,

instructi-ons, etc.);

• sampling_period: armazena a informação do período de amos-tragem com base em contagem do evento;

• sampling_freq: armazena a informação da frequência de amos-tragem;

• inherit: bit que especifica se o evento é contado nos processos e

threads criados;

• exclude_user : quando setado, esse bit desabilita contagem do evento no espaço usuário;

• exclude_kernel: quando setado, esse bit desabilita contagem do evento no espaço kernel;

• clock_id: campo com a informação do id de clock a ser utilizado na coleta de timestamps.

3.4.

Exemplos de uso

O perf possui um abrangente conjunto de funcionalidades que é acessado através da aplicação de interface com o usuário. A utilização da aplicação perf é realizada através da linha de comando do terminal. Ela é composta por diferentes subcomandos, os quais possuem funções específicas. A lista com os principais subcomandos é mostrada na Ta-bela 3.5. Os casos de uso do perf apresentados nessa seção são baseados no Linux Debian 9 com kernel versão 4.9 e arquitetura x86 de 64 bits.

Listagem 3.3: Lista resumida dos eventos disponíveis do perf list L i s t of pre - d e f i n e d e v e n t s ( to be u s e d in - e ) : cpu - c y c l e s OR c y c l e s [ H a r d w a r e e v e n t ] i n s t r u c t i o n s [ H a r d w a r e e v e n t ] cache - r e f e r e n c e s [ H a r d w a r e e v e n t ] cache - m i s s e s [ H a r d w a r e e v e n t ] branch - i n s t r u c t i o n s OR b r a n c h e s [ H a r d w a r e e v e n t ] branch - m i s s e s [ H a r d w a r e e v e n t ] bus - c y c l e s [ H a r d w a r e e v e n t ] s ta ll e d - cycles - f r o n t e n d [ H a r d w a r e e v e n t ] s ta ll e d - cycles - b a c k e n d [ H a r d w a r e e v e n t ] ref - c y c l e s [ H a r d w a r e e v e n t ] cpu - c l o c k [ S o f t w a r e e v e n t ] task - c l o c k [ S o f t w a r e e v e n t ] page - f a u l t s OR f a u l t s [ S o f t w a r e e v e n t ]

(45)

c on te x t - s w i t c h e s OR cs [ S o f t w a r e e v e n t ] cpu - m i g r a t i o n s OR m i g r a t i o n s [ S o f t w a r e e v e n t ] minor - f a u l t s [ S o f t w a r e e v e n t ] major - f a u l t s [ S o f t w a r e e v e n t ] a l i g n m e n t - f a u l t s [ S o f t w a r e e v e n t ] e m u l a t i o n - f a u l t s [ S o f t w a r e e v e n t ] L1 - dcache - l o a d s [ H a r d w a r e c a c h e e v e n t ] L1 - dcache - load - m i s s e s [ H a r d w a r e c a c h e e v e n t ] L1 - dcache - s t o r e s [ H a r d w a r e c a c h e e v e n t ] [ . . . ] r N N N [ Raw h a r d w a r e e v e n t ] cpu / t1 = v1 [ , t2 = v2 , t3 . . . ] / m o d i f i e r [ Raw h a r d w a r e e v e n t ] mem : < addr >[: a c c e s s ] [ H a r d w a r e b r e a k p o i n t ] [ . . . ] s c h e d : s c h e d _ p r o c e s s _ e x e c [ T r a c e p o i n t e v e n t ] s c h e d : s c h e d _ p r o c e s s _ f o r k [ T r a c e p o i n t e v e n t ] s c h e d : s c h e d _ p r o c e s s _ w a i t [ T r a c e p o i n t e v e n t ] s c h e d : s c h e d _ w a i t _ t a s k [ T r a c e p o i n t e v e n t ] s c h e d : s c h e d _ p r o c e s s _ e x i t [ T r a c e p o i n t e v e n t ] [ . . . ]

Como introduzido na seção 3.2, o perf é uma ferramenta baseada em eventos, portanto o subcomando base para a depuração é o perf

list. A Listagem 3.3 mostra a saída resumida do comando perf list, pois

existem cerca de 1500 eventos disponíveis na arquitetura em questão.

3.4.1.

Uso do perf stat

A forma de uso mais simples do perf é através do perf stat. Esse subcomando realiza a contagem de eventos, como mostra a Listagem 3.4. Nesse exemplo, o perf stat é invocado com o comando date, e tendo em vista que não foi especificado nenhum evento, o perf reali-zou a contagem de alguns contadores genéricos de hardware bem como contadores de software que ocorreram durante a execução do comando.

Listagem 3.4: Exemplo de uso genérico do perf stat com o comando

date. d e b i a n :~ $ s u d o p e r f s t a t d a t e Thu Dec 6 2 2 : 1 2 : 0 0 -02 2 0 1 8 P e r f o r m a n c e c o u n t e r s t a t s for ’ date ’: 0 . 8 7 6 4 2 6 task - c l o c k ( m s e c ) # 0 . 0 5 5 C P U s u t i l i z e d 1 c on t ex t - s w i t c h e s # 0 . 0 0 1 M / sec 0 cpu - m i g r a t i o n s # 0 . 0 0 0 K / sec 62 page - f a u l t s # 0 . 0 7 1 M / sec 2 ,155 ,972 c y c l e s # 2 . 4 6 0 GHz 1 ,783 ,570 s t al le d - cycles - f r o n t e n d # 8 2 . 7 3 % f r o n t e n d c y c l e s i d l e 8 16 ,9 4 3 i n s t r u c t i o n s # 0 . 3 8 i n s n per c y c l e 1 66 , 64 7 b r a n c h e s # 1 9 0 . 1 4 4 M / sec 10 ,059 branch - m i s s e s # 6 . 0 4 % of all

Referências

Documentos relacionados

No Estado do Pará as seguintes potencialidades são observadas a partir do processo de descentralização da gestão florestal: i desenvolvimento da política florestal estadual; ii

de professores, contudo, os resultados encontrados dão conta de que este aspecto constitui-se em preocupação para gestores de escola e da sede da SEduc/AM, em

Por fim, na terceira parte, o artigo se propõe a apresentar uma perspectiva para o ensino de agroecologia, com aporte no marco teórico e epistemológico da abordagem

continua patente a ausência de uma estratégia de desenvolvimento sustentável, o que poderá ser consequência ser tão insignificante que tal preocupação ainda não se

The challenges of aging societies and the need to create strong and effective bonds of solidarity between generations lead us to develop an intergenerational

O relatório encontra-se dividido em 4 secções: a introdução, onde são explicitados os objetivos gerais; o corpo de trabalho, que consiste numa descrição sumária das

Os principais resultados obtidos pelo modelo numérico foram que a implementação da metodologia baseada no risco (Cenário C) resultou numa descida média por disjuntor, de 38% no