Mapeamentos de recursos do hardware local para o Google Cloud

Neste documento, você verá como encontrar os mapeamentos de recursos certos do hardware local para o Google Cloud. Em um cenário em que seus aplicativos estão sendo executados em servidores bare-metal e você quer migrá-los para o Google Cloud, considere as seguintes questões:

  • Como os núcleos físicos (pCPUs) são mapeados para CPUs virtuais (vCPUs) no Google Cloud? Por exemplo, como mapear quatro núcleos físicos de Xeon E5 bare-metal para vCPUs no Google Cloud?
  • Como você explica as diferenças de desempenho entre plataformas de CPU e gerações de processadores diferentes? Por exemplo, o Sandy Bridge de 3,0 GHz é 1,5 vez mais rápido do que o Skylake de 2,0 GHz?
  • Como dimensionar os recursos corretamente com base nas suas cargas de trabalho? Por exemplo, como otimizar um aplicativo com uso intenso de memória e linha de execução única em um servidor de vários núcleos?

Soquetes, CPUs, núcleos e linhas de execução

Os termos soquete, CPU, núcleo e linhas de execução costumam ser usados alternadamente, o que pode causar confusão durante a migração entre ambientes diferentes.

Simplificando, um servidor pode ter um ou mais soquetes. Um soquete (também chamado de soquete de CPU ou slot de CPU) é o conector da placa-mãe que hospeda um chip de CPU e proporciona conexões físicas entre a CPU e a placa de circuito.

A CPU é ocircuito integrado (IC, na sigla em inglês) real. A operação fundamental de uma CPU é executar uma sequência de instruções armazenadas. Em um nível superior, as CPUs seguem as etapas de busca, decodificação e execução, conhecidas em conjunto como ciclo de instruções. Em CPUs mais complexas, várias instruções podem ser buscadas, decodificadas e executadas simultaneamente.

Cada chip de CPU pode ter um ou mais núcleos. Um núcleo consiste basicamente em uma unidade de execução que recebe instruções e executa ações com base nelas. Em um sistema com hiperprocessamento, um núcleo de processador físico permite que os recursos próprios sejam alocados como vários processadores lógicos. Em outras palavras, cada núcleo de processador físico é apresentado como dois núcleos virtuais (ou lógicos) para o sistema operacional.

O diagrama a seguir mostra uma visualização de alto nível de uma CPU quad-core com hiperprocessamento ativado.

Uma CPU quad-core com hiperprocessamento ativado.

No Google Cloud, cada vCPU é implementada como um único hiperprocessador em uma das plataformas de CPU disponíveis.

Para encontrar o número total de vCPUs (CPUs lógicas) no sistema, use esta fórmula:

vCPUs = linhas de execução por núcleo físico × núcleos físicos por soquete × número de soquetes

O comando lscpu coleta informações que incluem o número de soquetes, CPUs, núcleos e linhas de execução. Ele também inclui informações sobre cache de CPU e compartilhamento de cache, família, modelo e BogoMips. Veja alguns resultados típicos:

...
Architecture:           x86_64
CPU(s):                 1
On-line CPU(s) list:    0
Thread(s) per core:     1
Core(s) per socket:     1
Socket(s):              1
CPU MHz:                2200.000
BogoMIPS:               4400.00
...

Ao mapear os recursos da CPU entre o ambiente atual e o Google Cloud, verifique se você sabe quantos núcleos físicos ou virtuais o servidor tem. Para mais informações, consulte a seção Como mapear recursos.

Velocidade do clock da CPU

Para que um programa seja executado, ele precisa ser dividido em um conjunto de instruções que o processador entenda. Considere o programa C abaixo que adiciona dois números e exibe o resultado:

#include <stdio.h>
int main()
{
        int a = 11, b = 8;
        printf("%d \n", a+b);
}

Na compilação, o programa é convertido no seguinte código de montagem:

...
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    $11, -8(%rbp)
        movl    $8, -4(%rbp)
        movl    -8(%rbp), %edx
        movl    -4(%rbp), %eax
        addl    %edx, %eax
        movl    %eax, %esi
        movl    $.LC0, %edi
        movl    $0, %eax
        call    printf
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
...

Cada instrução de montagem do resultado anterior corresponde a uma única instrução para a máquina. Por exemplo, a instrução pushq indica que o conteúdo do registro RBP deve ser enviado para a pilha do programa. Durante cada ciclo de CPU, ela pode executar uma operação básica, como buscar uma instrução, acessar o conteúdo de um registro ou gravar dados. Para percorrer cada estágio do ciclo para adicionar dois números, consulte este simulador de CPU.

Observe que cada instrução de CPU pode exigir vários ciclos de clock para ser executada. O número médio de ciclos de clock necessários por instrução de um programa é definido por ciclos por instrução (CPI), da seguinte forma:

ciclos por instrução = número de ciclos de CPU usados / número de instruções executadas

A maioria das CPUs modernas pode executar várias instruções por ciclo de clock com o pipeline de instrução. O número médio de instruções executadas por ciclo é definido por instruções por ciclo (IPC), da seguinte forma:

instruções por ciclo = número de instruções executadas / número de ciclos de CPU usados

A velocidade do clock da CPU define o número de ciclos de clock que o processador consegue executar por segundo. Por exemplo, um processador de 3,0 GHz pode executar três bilhões de ciclos de clock por segundo. Isso significa que cada ciclo de clock leva cerca de 0,3 nanossegundos para ser executado. Durante cada ciclo de clock, a CPU pode executar uma ou mais instruções, conforme definido pelo IPC.

A velocidade do clock geralmente é usada para comparar o desempenho dos processadores. Seguindo a definição literal (número de ciclos executados por segundo), você poderia concluir que um número maior de ciclos de clock significa que a CPU pode trabalhar mais e, portanto, ter um desempenho melhor. Essa conclusão seria válida ao comparar CPUs com a mesma geração de processador. No entanto, a velocidade do clock não deve ser usada como um único indicador de desempenho ao comparar CPUs com diferentes famílias de processadores. Uma CPU de nova geração pode oferecer melhor desempenho, mesmo quando executada a uma velocidade de clock menor do que as CPUs de gerações anteriores.

Velocidade do clock e desempenho do sistema

Para entender melhor o desempenho de um processador, é importante observar não só o número de ciclos de clock, mas também a quantidade de trabalho que uma CPU consegue realizar por ciclo. O ambiente de execução total de um programa limitado pela CPU não depende só da frequência, mas também de outros fatores, como número de instruções a serem executadas, ciclos por instrução ou instruções por ciclo, arquitetura do conjunto de instruções, programação e algoritmos de expedição e linguagem de programação usada. Esses fatores podem variar significativamente de uma geração de processador para outra.

Para entender como a execução da CPU pode variar em duas implementações diferentes, considere o exemplo de um programa fatorialsimples. Um dos programas a seguir é escrito em C e outro em Python. Perf (uma ferramenta de criação de perfis para Linux) é usada para coletar algumas métricas de CPU e kernel.

Programa em C

#include <stdio.h>
int main()
{
    int n=7, i;
    unsigned int factorial = 1;
    for(i=1; i<=n; ++i){
            factorial *= i;
    }

    printf("Factorial of %d = %d", n, factorial);
}

Performance counter stats for './factorial':

...
0             context-switches       #    0.000 K/sec
0             cpu-migrations         #    0.000 K/sec
45            page-faults            #    0.065 M/sec
1,562,075     cycles                 #    1.28 GHz
1,764,632     instructions           #    1.13  insns per cycle
314,855       branches               #    257.907 M/sec
8,144         branch-misses          #    2.59% of all branches
...

0.001835982 seconds time elapsed

Programa em Python

num = 7
factorial = 1
for i in range(1,num + 1):
  factorial = factorial*i
print("The factorial of",num,"is",factorial)

Performance counter stats for 'python3 factorial.py':

...
7              context-switches      #    0.249 K/sec
0              cpu-migrations        #    0.000 K/sec
908            page-faults           #    0.032 M/sec
144,404,306    cycles                #    2.816 GHz
158,878,795    instructions          #    1.10  insns per cycle
38,254,589     branches              #    746.125 M/sec
945,615        branch-misses         #    2.47% of all branches
...

0.029577164 seconds time elapsed

O resultado destacado mostra o tempo total gasto para executar cada programa. O programa escrito em C foi executado cerca de 15 vezes mais rápido que o programa escrito em Python (1,8 milissegundo x 30 milissegundos). Veja mais algumas comparações:

  • Alternâncias de contexto. Quando o programador do sistema precisa executar outro programa ou uma interrupção aciona uma execução contínua, o sistema operacional salva o conteúdo do registro da CPU do programa em execução e o configura para a execução do novo programa. Não ocorreu nenhuma alternância de contexto durante a execução do programa em C, já na execução do programa em Python ocorreram sete.

  • Migrações de CPU. O sistema operacional tenta manter o equilíbrio da carga de trabalho entre as CPUs disponíveis em sistemas com vários processadores. Esse balanceamento é realizado periodicamente e sempre que uma fila de execução da CPU está vazia. Durante o teste, nenhuma migração de CPU foi observada.

  • Instruções. O programa em C resultou em 1,7 milhão de instruções executadas em 1,5 milhão de ciclos de CPU (IPC = 1,13, CPI = 0,88), enquanto o programa em Python resultou em 158 milhões de instruções executadas em 144 milhões de ciclos (IPC = 1,10, CPI = 0,91). Os dois programas preencheram o pipeline, permitindo que a CPU executasse mais de uma instrução por ciclo. Mas, em comparação com o programa em C, o número de instruções geradas na versão em Python é cerca de 90 vezes maior.

  • Falhas da página. Cada programa tem uma fração de memória virtual que contém todas as instruções e dados. Em geral, não é eficiente copiar todas essas instruções na memória principal de uma só vez. Uma falha de página ocorre sempre que um programa precisa que parte do conteúdo da memória virtual seja copiada na memória principal. Uma falha de página é sinalizada pela CPU por meio de uma interrupção.

    Como o executável intérprete de Python é muito maior do que o de C, a sobrecarga adicional é evidente em termos de ciclos de CPU (1,5 milhão para C e 144 milhões para Python) e falhas de página (45 para C e 908 para Python).

  • Ramificações e perdas de ramificações. Com instruções condicionais, a CPU tenta prever o caminho de execução antes mesmo de avaliar a condição da ramificação. Essa etapa é útil para manter o pipeline de instruções preenchido. Esse processo é chamado de execução especulativa. A execução especulativa teve sucesso nas execuções anteriores: o previsor da ramificação estava errado apenas 2,59% do tempo no programa em C e 2,47% do tempo no programa em Python.

Fatores diferentes da CPU

Até agora, você analisou vários aspectos das CPUs e o impacto delas sobre o desempenho. No entanto, é raro um aplicativo manter a execução na CPU 100% do tempo. Como um exemplo simples, considere o seguinte comando tar, que cria um arquivo a partir do diretório home de um usuário no Linux:

$ time tar cf archive.tar /home/"$(whoami)"

A saída é assim:

real  0m35.798s
user  0m1.146s
sys   0m6.256s

Os valores de saída são definidos da seguinte maneira:

tempo real
Tempo real (real) é o tempo que a execução leva do início ao fim. Esse tempo decorrido inclui frações de tempo usadas por outros processos e o período em que o processo fica bloqueado, por exemplo, enquanto aguarda a conclusão das operações de E/S.
tempo do usuário
Tempo do usuário (user) é o tempo que a CPU gasta para executar o código do espaço do usuário no processo.
tempo do sistema
Tempo do sistema (sys) é a quantidade de tempo de CPU gasta executando o código do espaço do kernel no processo.

No exemplo anterior, o tempo do usuário é de 1 segundo, enquanto o tempo do sistema é de 6,3 segundos. A diferença de aproximadamente 28 segundos entre o tempo real e os tempos user + sys aponta para o tempo de off-CPU gasto pelo comando tar.

Um tempo de off-CPU elevado em uma execução indica que o processo não está vinculado à CPU. Costuma-se dizer que a computação está vinculada a algo quando esse recurso é o gargalo para alcançar o desempenho esperado. Ao planejar uma migração, é importante ter uma visão holística do aplicativo e considerar todos os fatores que podem ter um impacto significativo sobre o desempenho.

Papel da carga de trabalho de destino na migração

Para encontrar um ponto de partida razoável para a migração, é importante comparar os recursos de base. É possível fazer o benchmarking do desempenho de várias formas:

  • Carga de trabalho de destino real: implante o aplicativo no ambiente de destino e faça benchmark do desempenho dos indicadores principais de desempenho(KPIs). Os KPIs de um aplicativo da Web podem incluir, por exemplo:

    • Tempo de carregamento do aplicativo;
    • Latências do usuário final para transações de ponta a ponta;
    • Conexões encerradas;
    • Número de instâncias exibidas com tráfego baixo, médio e alto;
    • Utilização de recursos (CPU, RAM, disco, rede) das instâncias exibidas;

    No entanto, a implementação de um aplicativo de destino completo (ou um subconjunto dele) pode ser complexa e demorada. Para uma comparação preliminar, em geral, é preferível usar benchmarks baseados em programas.

  • Benchmarks baseados em programas: concentram-se nos componentes individuais do aplicativo, e não no fluxo completo dele. Esses benchmarks executam uma mistura de perfis de testes, em que cada perfil é direcionado a um componente do aplicativo. Por exemplo, os perfis de teste da implementação de uma pilha LAMP podem incluir Apache Bench, usado no benchmarking do desempenho do servidor da Web, e Sysbench, usado no benchmarking do MySQL. Normalmente, a configuração desses testes é mais fácil do que as cargas de trabalho de destino reais. Eles também têm uma alta capacidade de portabilidade entre sistemas operacionais e ambientes distintos.

  • Benchmarks de kernel ou sintéticos: para testar os principais aspectos de computação de programas reais, use benchmarks sintéticos como fatoração matricialou FFT. Normalmente, esses testes são executados durante a fase inicial do projeto do aplicativo. Eles são mais adequados para o benchmarking de determinados aspectos de uma máquina, como estresse da VM e da unidade, sincronização de E/S e sobrecarga de cache.

Entenda seu aplicativo

Muitos aplicativos são limitados por CPU, memória, E/S de disco e de rede ou uma combinação desses fatores. Por exemplo, se o aplicativo estiver passando por uma lentidão devido à contenção de discos, talvez o fornecimento de mais núcleos para os servidores não melhore o desempenho.

Manter a observabilidade dos aplicativos em ambientes grandes e complexos pode ser difícil. Existem sistemas de monitoramento especializados que conseguem monitorar todos os recursos distribuídos no sistema. Por exemplo, no Google Cloud, é possível usar o Cloud Monitoring para ter visibilidade total do código, dos aplicativos e da infraestrutura. Um exemplo do Cloud Monitoring será discutido mais adiante nesta seção, mas primeiro é bom entender como funciona o monitoramento de recursos típicos de um sistema em um servidor independente.

Muitos utilitários, como top, IOStat, VMStat e iPerf, fornecem uma visualização de alto nível dos recursos do sistema. Por exemplo, executar top em um sistema Linux produz um resultado como este:

top - 13:20:42 up 22 days,  5:25,         18 users,        load average: 3.93 2.77,3.37
Tasks:  818 total,        1 running,      760 sleeping,    0 stopped,       0 zombie
Cpu(s): 88.2%us,          0.0%sy,         0.0%ni,          0.3%id,          0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem:    49375504k total,  6675048k used,  42700456k free,  276332k buffers
Swap:   68157432k total,  0k used,        68157432k free,  5163564k cached

Se o sistema tiver uma carga alta e o percentual de tempo de espera for alto, é provável que você tenha um aplicativo limitado por E/S. Se um ou ambos os tempos de porcentagem do usuário ou de porcentagem do sistema forem muito altos, é provável que você tenha um aplicativo limitado pela CPU.

No exemplo anterior, as médias de carga (de uma VM de 4 vCPUs) nos últimos 5, 10 e 15 minutos são 3,93, 2,77 e 3,37, respectivamente. Se você combinar essas médias com a alta porcentagem de tempo do usuário (88,2%), tempo ocioso baixo (0,3%) e nenhum tempo de espera (0,0%), será possível concluir que o sistema é limitado pela CPU.

Embora essas ferramentas funcionem bem em sistemas independentes, em geral, elas não são projetadas para monitorar ambientes grandes e distribuídos. Para monitorar sistemas de produção, ferramentas como Cloud Monitoring, Nagios, Prometheus e Sysdig fornecem análises detalhadas do consumo de recursos relacionado aos aplicativos.

Monitoramento de desempenho do aplicativo permite coletar dados por um período suficiente por meio de várias métricas, como utilização da CPU, uso de memória, E/S de disco, E/S de rede, tempos de ida e volta, latências, taxas de erro e capacidade. Por exemplo, os gráficos do Cloud Monitoring abaixo mostram os níveis de utilização e carga da CPU, com uso de memória e disco de todos os servidores em execução em um grupo de instâncias gerenciadas do Google Cloud. Para saber mais sobre essa configuração, consulte a visão geral do agente do Cloud Monitoring.

Cargas de CPU, níveis de utilização e uso de memória e disco
de todos os servidores em execução em um grupo de instâncias gerenciadas.

Para a análise, o período de coleta de dados precisa ser longo o bastante para mostrar o uso máximo e mínimo dos recursos. Depois, é possível analisar os dados coletados para fornecer um ponto de partida para o planejamento de capacidade no novo ambiente de destino.

Mapear recursos

Nesta seção, mostramos como estabelecer o dimensionamento de recursos no Google Cloud. Primeiro, faça uma avaliação de dimensionamento inicial com base nos níveis de utilização de recursos existentes. Depois, execute testes de comparação de desempenho específicos para o aplicativo.

Dimensionamento baseado no uso

Siga estas etapas para mapear a contagem de núcleos existentes de um servidor para vCPUs no Google Cloud.

  1. Encontre a contagem de núcleos atual. Consulte o comando lscpu na seção anterior

  2. Descubra a utilização da CPU do servidor. O uso da CPU refere-se ao tempo que ela leva quando está no modo do usuário (%us) ou no modo do kernel (%sy). Bons processos (%ni) também pertencem ao modo do usuário, enquanto as interrupções de software (%si) e interrupções de hardware (%hi) são tratadas no modo do kernel. Se a CPU não estiver fazendo nada disso, pode ser que ela esteja inativa ou aguardando a conclusão da E/S. Quando um processo está esperando a conclusão da E/S, ele não contribui para os ciclos de CPU.

    Para calcular o uso atual da CPU de um servidor, execute o seguinte comando top:

    ...
    Cpu(s): 88.2%us,  0.0%sy,  0.0%ni,  0.3%id,  0.0%wa,  0.0%hi,  0.0%si, 0.0%st
    ...
    

    O uso da CPU é definido da seguinte maneira:

    CPU Usage = %us + %sy + %ni + %hi + %si
    

    Como alternativa, é possível usar qualquer ferramenta de monitoramento, como o Cloud Monitoring, para coletar o inventário e a utilização de CPU necessários. Para implantações de aplicativos que não têm escalonamento automático (ou seja, que são executados com um ou mais números fixos de servidores), recomendamos que você considere o pico de utilização para o dimensionamento da CPU. Essa abordagem protege os recursos do aplicativo contra interrupções quando as cargas de trabalho estiverem no pico de utilização. Para implantações com escalonamento automático (com base no uso da CPU), a utilização média da CPU é uma linha de base segura a se considerar para o dimensionamento. Nesse caso, lide com os picos de tráfego dimensionando o número de servidores para a duração do pico.

  3. Aloque buffer suficiente para acomodar picos. Ao dimensionar a CPU, inclua buffer suficiente para acomodar níveis de processamento não programados que possam causar picos inesperados. Por exemplo, é possível planejar a capacidade da CPU para que haja espaço adicional de 10 a 15% acima do pico de uso esperado e a utilização máxima geral da CPU não supere 70%.

  4. Use a fórmula abaixo para calcular a contagem de núcleos esperados no GCP:

    vCPUs no Google Cloud = 2 × TETO [(contagem de núcleos × % de utilização) / (2 × % do limite)]

    Esses valores são definidos da seguinte maneira:

    • contagem de núcleos: a contagem de núcleos existentes (conforme calculado na etapa 1).
    • % de utilização: a utilização da CPU do servidor (conforme calculado na etapa 2).
    • % do limite: o uso máximo da CPU permitido no servidor depois de considerar espaço suficiente (conforme calculado na etapa 3).

Para um exemplo concreto, pense em um cenário em que é necessário mapear a contagem de núcleos de um servidorXeon E5640 quad-core bare-metal em execução no local para vCPUs no Google Cloud. As especificações do Xeon E5640 estão disponíveis para o público, mas também é possível confirmá-las executando um comando como lscpu no sistema. Os números têm a seguinte aparência:

  • contagem de núcleos existente no local = soquetes (1) × núcleos (4) × linhas de execução por núcleo (2) = 8.
  • Suponha que a utilização da CPU (% de utilização) observada durante o pico de tráfego seja de 40%.
  • Foi provisionado um buffer adicional de 30%. Ou seja, a utilização máxima da CPU (% do limite) não deve ultrapassar 70%.
  • vCPUs no Google Cloud = 2 × TETO [(8 × 0,4)/(2 × 0,7)] = 6 vCPUs
    (ou seja, 2 × TETO [3,2/1,4] = 2 × TETO [2.28] = 2 × 3 = 6)

É possível fazer avaliações semelhantes para RAM, disco, E/S de rede e outros recursos do sistema.

Dimensionamento com base no desempenho

A seção anterior abordou detalhes do mapeamento de pCPUs para vCPUs com base nos níveis atuais e esperados de uso da CPU. Esta seção considera o aplicativo que está sendo executado no servidor.

Nesta seção, você vai executar um conjunto de testes padrão e geral (benchmarks baseados em programas) para avaliar o desempenho. Continuando com o cenário de exemplo, considere que você está executando um servidor MySQL na máquina Xeon E5. Nesse caso, é possível usar o Sysbench OLTP para comparar o desempenho do banco de dados.

Um simples teste de leitura e gravação no MySQL com o Sysbench produz a saída a seguir:

OLTP test statistics:
  queries performed:
    read:              520982
    write:             186058
    other:             74424
    total:             781464
  transactions:        37211 (620.12 per sec.)
  deadlocks:           2 (0.03 per sec.)
  read/write requests: 707040 (11782.80 per sec.)
  other operations:    74424 (1240.27 per sec.)

Test execution summary:
  total time:          60.0061s
  total number of events: 37211
  total time taken by event execution: 359.8158
  per-request statistics:
    min:            2.77ms
    avg:            9.67ms
    max:            50.81ms
    approx. 95 percentile: 14.63ms

Thread fairness:
  events (avg/stddev):         6201.8333/31.78
  execution time (avg/stddev): 59.9693/0.00

A execução desse benchmark permite comparar o desempenho em relação ao número de transações por segundo, total de leituras/gravações por segundo e tempo da execução completa no ambiente atual e no Google Cloud. Recomendamos executar várias iterações desses testes para excluir valores atípicos. Para observar as diferenças de desempenho sob diversos padrões de carga e tráfego, também é possível repetir esses testes com parâmetros diferentes, como níveis de simultaneidade, duração dos testes e número de usuários simulados ou diferentes taxas de incubação.

Os números de desempenho do ambiente atual e do Google Cloud ajudarão a simplificar ainda mais sua avaliação de capacidade inicial. Se os testes de benchmarking no Google Cloud gerarem resultados semelhantes ou melhores que o ambiente atual, será possível ajustar ainda mais a escala de recursos com base nos ganhos de desempenho. Por outro lado, se os benchmarks do ambiente atual forem melhores do que os do Google Cloud, faça o seguinte:

  • Revise a avaliação de capacidade inicial.
  • Monitore os recursos do sistema.
  • Encontre possíveis áreas de contenção (por exemplo, gargalos identificados na CPU e na RAM).
  • Redimensione os recursos adequadamente.

Depois de concluir, execute novamente os benchmarks específicos do aplicativo.

Benchmarking de desempenho completo

Até agora, você analisou um cenário simples que comparou apenas o desempenho do MySQL no Google Cloud e no local. Nesta seção, vamos considerar o aplicativo distribuído com três níveis abaixo.

Aplicativo distribuído de três níveis.

Como o diagrama mostra, provavelmente você executou vários benchmarks para conseguir uma avaliação razoável do seu ambiente atual e do Google Cloud. No entanto, pode ser difícil definir qual subconjunto de benchmarks estima o desempenho do aplicativo com mais precisão. Além disso, pode ser entediante gerenciar o processo do teste, da gestão de dependências até a instalação, a execução e a reunião dos resultados do teste em diferentes ambientes em nuvem ou não. Em cenários como esse, use o PerfKitBenchmarker. O PerfKit contém vários conjuntos de benchmarks para medir e comparar ofertas diferentes em várias nuvens. Ele também executa determinados benchmarks no local por meio de máquinas estáticas.

Suponha que você queira executar, no aplicativo de três níveis do diagrama anterior, testes para comparar o tempo de inicialização do cluster, a CPU e o desempenho da rede das VMs no Google Cloud. Com o PerfKitBenchmarker, é possível executar várias iterações de perfis de teste relevantes, que produzem os resultados abaixo:

  • Tempo de inicialização do cluster: apresenta uma visualização do tempo de inicialização da VM. É especialmente importante quando o aplicativo é elástico e espera que sejam adicionadas ou removidas instâncias durante o escalonamento automático. O gráfico a seguir mostra que os tempos de inicialização de uma instância n1-standard-4 do Compute Engine permanecem razoavelmente uniformes (até o percentil 99) entre 40 e 45 segundos.

    Tempos de inicialização de uma instância n1-standard-4 do Compute Engine.

  • Stress-ng: mede e compara o desempenho com uso intenso de computação ao pressionar o processador, o subsistema de memória e o compilador de um sistema. No exemplo abaixo, stress-ng executa vários testes de estresse, como bsearch, malloc, matrix, mergesort e zlib em uma instância n1-standard-4 do Compute Engine. Stress-ng mede a capacidade do teste de estresse usando operações falsas (bogo ops) por segundo. Se você normalizar as operações falsas em resultados de testes de estresse diferentes, terá o resultado abaixo, que mostra a média geométrica das operações executadas por segundo. Neste exemplo, as operações falsas variam de cerca de 8.000 por segundo no 50º percentil até aproximadamente 10.000 por segundo no 95º percentil. Em geral, as operações falsas são usadas somente para o benchmark do desempenho de CPUs independentes. Talvez essas operações não representem bem seu aplicativo.

    Média geométrica das operações executadas por segundo.

  • Netperf: mede a latência com testes de solicitação e resposta. Os testes de solicitação e resposta são executados na camada do aplicativo da pilha de rede. Esse método de teste de latência envolve todas as camadas da pilha e é uma opção melhor que os testes de ping para medir a latência de VM para VM. O gráfico abaixo mostra as latências de solicitação e resposta de TCP (TCP_RR, na sigla em inglês) entre um cliente e um servidor que estão sendo executados na mesma zona do Google Cloud. Os valores de TCP_RR variam de cerca de 70 microssegundos 50º percentil a aproximadamente 130 microssegundos no 90º percentil.

    Latências de solicitação e resposta de TCP entre cliente e servidor em execução na mesma zona do Google Cloud.

Dada a natureza da carga de trabalho de destino, é possível executar outros perfis de teste usando o PerfKit. Para mais detalhes, consulte benchmarks compatíveis com o PerfKit.

Práticas recomendadas no Google Cloud

Antes de configurar e executar um plano de migração no Google Cloud, recomendamos que você siga as práticas recomendadas de migração. Essas práticas são apenas um ponto de partida. Talvez seja necessário considerar muitos outros aspectos do seu aplicativo (como dissociar dependências, introduzir tolerância a falhas e garantir aumento e redução com base na carga de trabalho do componente) e como cada um desses aspectos é mapeado no Google Cloud.

  1. Conheça os limites e cotas do Google Cloud. Antes de começar a avaliação de capacidade formal, entenda algumas considerações importantes para o planejamento de recursos no Google Cloud, por exemplo:

    Liste os componentes de Infrastructure as a Service (IaaS) e Platform as a Service (PaaS) que serão necessários durante a migração e entenda bem quais são as cotas, os limites e os ajustes disponíveis em cada um dos serviços.

  2. Monitore os recursos continuamente. O monitoramento contínuo de recursos pode ajudar a identificar padrões e tendências no desempenho do sistema e dos aplicativos. Ele não ajuda só a estabelecer o desempenho da linha de base, mas também demonstra a necessidade de upgrades e downgrades de hardware ao longo do tempo. O Google Cloud disponibiliza várias opções para implantar soluções de monitoramento de ponta a ponta:

  3. Dimensione suas VMs. Identifique quando a VM tiver provisionamento em falta ou em excesso. A definição de ferramentas de monitoramento básicas, conforme discutido anteriormente, fornece esses insights de maneira fácil. O Google Cloud também oferece recomendações de dimensionamento baseadas no histórico de uso de uma instância. Além disso, com base na natureza da carga de trabalho, se os tipos de máquina predefinidos não atenderem às suas necessidades, será possível criar uma instância com configurações de hardware virtualizadas personalizadas.

  4. Use as ferramentas certas. Para ambientes de grande escala, implante ferramentas automatizadas para minimizar os esforços naturais, por exemplo:

Principais pontos

A migração de recursos de um ambiente a outro exige um planejamento cuidadoso. É importante não examinar os recursos de hardware isoladamente, mas ter uma visão completa do seu aplicativo. Por exemplo, em vez de focar apenas no fato de um processador Sandy Bridge de 3,0 GHz ser duas vezes mais rápido que um processador Skylake de 1,5 GHz, concentre-se em como os indicadores principais de desempenho do seu aplicativo mudam de uma plataforma de computação para outra.

Ao avaliar requisitos de mapeamento de recursos em ambientes diferentes, considere os seguintes aspectos:

  • Recursos do sistema que limitam seu aplicativo (por exemplo, CPU, memória, disco ou rede).
  • Impacto da infraestrutura de base (por exemplo, geração do processador, velocidade do clock, HDD ou SSD) sobre o desempenho do seu aplicativo.
  • Impacto das escolhas de software e design da arquitetura (por exemplo, cargas de trabalho com uma ou várias linhas de execução, implantações fixas ou com escalonamento automático) sobre o desempenho do aplicativo.
  • Níveis de utilização atual e esperado dos recursos de computação, armazenamento e rede.
  • Os testes mais adequados para representar seu aplicativo.

A coleta de dados dessas métricas por meio do monitoramento contínuo ajuda a determinar um plano de capacidade inicial. O acompanhamento pode ser realizado por meio do benchmarking adequado do desempenho para ajustar suas estimativas de tamanho iniciais.

A seguir