Palestra Windows Internals

Enquanto não sai o próximo post da série Inside the Machine, fiz uma apresentação sobre fundamentos de Windows Internals para alguns DBAs SQL Server.

Nessa palestra falei, entre outras coisas, sobre um pequeno segredo para gerar dumps “full” do SQL Server sem que se tenha que suspender o processo original do mesmo. Isso é bastante interessante em cenários onde você tem uma instância com um Buffer Pool relativamente grande (30 GB+) e não pode manter o processo parado enquanto gera um dump.

Pretendo (um dia haha) postar sobre isso, mas por enquanto veja nos slides para maiores informações. Vale ressaltar que essa funcionalidade não é documentada, não é suportada pela Microsoft e pode destruir o processo da sua instância SQL, corromper os bancos de dados, explodir o seu data center e ainda por cima matar alguns gatinhos! Não use em produção.

Segue o link para download do pdf: http://bit.ly/1KgXElG

Se você quer se aprofundar mais nos assuntos, recomendo dar uma olhadinha nas referências ao fim da apresentação e também o meu treinamento on-demand de Windows Internals na Sr. Nimbus.

No mais, fique à vontade para deixar seus comentários sobre o material!

Pin It

Hyper-Threading (SMT) e SQL Server

Semana passada postaram uma pergunta muito interessante na lista de SQL Server Nimbus Advanced, que participo. Pela própria natureza do assunto que o torna interessante para um grupo de pessoas além dos que participam da lista, e o fato de que a resposta que eu estava escrevendo acabou crescendo um pouco, acabei decidindo transformá-lo em um post. :)

Hyper-Threading (SMT) e SQL Server

Muito interessante o asssunto. Vamos por partes…

O principal fator que vai definir o impacto do HT no seu ambiente é o seu workload – tanto positivamente quanto negativamente.

Intel Core i7 logoA própria Intel limita o ganho teórico do HT a 30% [1]. Isso é, no melhor do melhor dos casos, o máximo de desempenho que você vai “ganhar” com HT é 30%. É pouco? Não acho. Mas o que eu acho é que HT é muitas vezes confundido como uma funcionalidade de desempenho quando na realidade é uma funcionalidade que visa melhorar a eficiência do seu processador. Ele vai utilizar alguns ciclos a mais que teriam sido perdidos caso não houvesse um “pipeline” substituto pronto para entrar em cena. Não há ganho, e sim “controle de perda”. :)

HT nada mais é do que a duplicação de alguns componentes do pipeline do núcleo, permitindo que esse, no melhor caso, não pare totalmente de trabalhar quando houver uma dependência ainda não disponível durante a execução, como um acesso de memória que resultou em cache miss, por exemplo.

Pipeline wih and w/o SMT

Pipeline (SMT)

Teoria e prática

Ok, mas saindo um pouco da teoria e indo para a parte prática, muitas coisas começam a influenciar na brincadeira.

O próprio escalonamento do Windows (e de tabela o do SQL Server) afeta o desempenho do sistema com o HT habilitado ou não. Por exemplo, se o algoritmo do scheduler não levar em conta o fato de dois “núcleos lógicos” (por falta de nome melhor) compartilharem os mesmos ALUs o seu desempenho vai piorar sensivelmente quando o scheduler escalonar duas threads no mesmo núcleo físico ao invés de núcleos físicos distintos.

Esse cenário era muito comum nos primórdios do Windows Server [2], quando este não fazia distinção entre núcleos físicos e lógicos. Ainda vemos algo parecido hoje nos processadores oriundos da microarquitetura Bulldozer da AMD, que utiliza uma tecnologia que também afeta o comportamento do pipeline, mas não é exatamente uma implementação do SMT. Os schedulers não estavam preparados para lidar com isso durante o lançamento dos processadores dessa microarquitetura, fazendo a AMD sofrer em alguns benchmarks [3].

Trocando em miúdos, existem muitos fatores e o impacto no desempenho final pode ser bem maior do que os 30% teóricos, tanto positivamente quanto negativamente.

Mito

Existe um mito que o Hyper-Threading é o mal encarnado para o SQL Server, devido a diversos fatores, incluindo os citados acima. Um dos causadores (não intencional) desse rumor foi o Slava Oks [4] (ex-time de produto, SQLOS), e se você quiser ver um ótimo exemplo de como fazer o HT não funcionar, sugiro que leia o seu post e execute os testes você mesmo.

Processadores

Agora vamos para a questão de desempenho de processadores…

Observando o processo do SQL Server (sqlservr.exe) podemos notar que ele possui callstacks bastante profundas, de pelo menos uns 8 níveis desde o início do processamento de uma consulta, e muitos branches ao longo da execução dessa consulta, mesmo simples. Servidores OLTP, em geral, costumam ter um working set de GBs de dados em memória e processar pequenas partes dessa massa à cada segundo, de forma “aleatória”. Na teoria [5], esses tipos de cenários são excelentes candidatos a fazer um bom uso do SMT e também são bastante influenciados pelo tamanho dos caches do processador, a latência de acesso da sua memória RAM e a eficiência do branch predictor. Esses fatores podem até mesmo influenciar mais que o próprio clock do seu processador… Nada de comprar processadores olhando apenas os GHz!

Workloads de OLAP e aplicações científicas , por outro lado, tendem a ser mais sensíveis à “força bruta” do processador.

Enfim… No final das contas, a única coisa que vai te dizer se o HT pode ou não beneficiar o seu ambiente é o teste. São fatores demais que influenciam no resultado final para fazer uma previsão para qualquer direção. Se você tiver um processador com HT, teste seu workload com e sem o HT habilitado e colete métricas que te dirão qual é preferível.

No caso do seu processador não possuir a funcionalidade, só posso dizer que não se preocupe com isso. Há formas mais práticas e diretas de influenciar o desempenho do seu ambiente.

Referências:

[1] http://en.wikipedia.org/wiki/Simultaneous_multithreading#Modern_commercial_implementations
[2] http://www.hardwaresecrets.com/article/Activating-the-Hyper-Threading/20
[3] http://www.hardwarecanucks.com/news/cpu/microsoft-tries-again-second-win-7-bulldozer-hotfix-now-available/
[4] http://blogs.msdn.com/b/slavao/archive/2005/11/12/492119.aspx
[5] http://www.cs.washington.edu/research/smt/papers/smtdatabase.pdf

Pin It

Windows Internals

MCTS Microsoft Certified Technology Specialist Windows Internals Logo

Microsoft Windows Internals Specialist

Não costumo fazer alarde em relação à certificações, mas acredito que essa vale um blog post. :)

Nesta semana realizei a prova de certificação Windows Internals e, com muito gosto, posso dizer que fui aprovado!

Quando soube a respeito dessa prova, ainda em 2011, fiquei bastante interessado. Segue a descrição do exame:

“This exam validates deep technical skills in the area of Windows Internals. Including troubleshooting operating systems that are not performing as expected or applications that are not working correctly, identifying code defects, and developing and debugging applications that run unmanaged code or that are tightly integrated with the operating system, such as Microsoft SQL Server, third party applications, antivirus software, and device drivers.”

Há alguns meses lançaram no Defrag Tools do Channel 9 um episódio falando do exame, e decidi que realmente era hora de tentar.

Esse exame marcou um fim de um ciclo para mim. Hoje estou me dedicando bastante a outras áreas de TI, relacionados ou não diretamente a Windows, mas tenho certeza que o conhecimento adquirido e a certificação ainda vão me auxiliar muito ao longo da minha carreira, além de dar mais pique para continuar gravando os meus treinamentos de Windows Internals pela Sr. Nimbus.

Os skills mensurados durante o exame foram basicamente:

  • Identifying Architectural Components (16%)
  • Designing Solutions (15%)
  • Monitoring Windows (14%)
  • Analyzing User Mode (18%)
  • Analyzing Kernel Mode (19%)
  • Debugging Windows (18%)

Para informações à respeito do que cai em cada tópico, esse post do blog MSDN NtDebugging lista o material e ferramentas que foram cobrados, e no episódio do Defrag Tools já mencionado acima algumas dessas ferramentas são demonstradas.

Pontos gerais da prova

A prova em si é bem prática, com muito debugging tanto em user mode quanto kernel mode. Cobrou bastante comandos do Windbg, e alguns parâmetros. Também caíram questões de desenvolvimento de soluções – drivers e apps Win32 – com direito a código-fonte em C e perguntas sobre parâmetros de APIs em algumas questões. Outro ponto que caiu bastante foi troubleshooting de drivers e aplicativos mal comportados com ferramentas Sysinternals e do WDK.

No geral, eu gostei da prova. Bastante prática e objetiva. As questões e cenários eram bem mais simples do que encontramos no dia a dia mas o suficiente, na minha opinião, para aferir se o profissional realmente conhece os conceitos do sistema operacional, kernel e API Win32, e se tem experiência real realizando trobleshooting, tuning e desenvolvimento nativo e baixo-nível.

EOL da versão 2008

O lado ruim, entretanto, é que a prova não estará mais disponível. Foi descontinuada no dia 31/07, um dia após o meu exame.

Infelizmente a Microsoft ainda não disponibilizou uma versão atualizada da prova para as novas versões do sistema operacional. Levando em conta que os livros Windows Internals do Server 2008 R2 (Client 7) acabaram de ser lançados e que os de 2012 ainda nem têm previsão, não acredito que teremos outra prova tão cedo, o que é uma pena.

O pessoal do Defrag Tools até tentou intervir junto ao time de certificações da Microsoft para que ela mantivesse o exame disponível por mais algum tempo, mas sem sucesso.

Na minha opinião, deveriam ter mantido essa prova, pelo menos até introduzir a versão atualizada. De qualquer maneira, isso me forçou a finalmente criar coragem e realizá-la depois de enrolar por muito tempo, caso contrário teria que esperar uma próxima versão em um futuro distante…

Que venham os próximos desafios!

Pin It

Introdução ao WinDbg

WinDbg

O WinDbg é uma interface de ferramenta de depuração (debugger ou depurador) sofisticado desenvolvido pela Microsoft distribuído gratuitamente com o SDK (e o DDK) do Windows. Ele pode ser utilizado tanto para depuração em user-mode ou kernel-mode. Apesar de não ser um depurador por si só – por baixo da interface gráfica o WinDbg utiliza os depurados de linha de comando cdb (user-mode) e kd (kernel-mode) – para os nossos propósitos vamos tratá-lo como tal no restante desse post.

Símbolos

Durante a compilação de um software com as ferramentas do Visual Studio, através de parâmetros ao compilador é possível gerar arquivos .pdb que são bancos de símbolos do módulo que está sendo compilado. Sendo menos abstrato, o arquivo .pdb mapeia endereços de memória do módulo – ininteligíveis aos seres humanos – aos seus nomes originais, no código-fonte. Dessa forma é possível observar os nomes das funções, classes, métodos, parâmetros, tipos, entre diversas outras informações à respeito do módulo executável mesmo sem possuirmos acesso ao código-fonte original, desde que o software tenha sido compilado com os parâmetros para a geração do pdb e que tenhamos acesso aos símbolos.

A Microsoft, por sua vez, compila (quase) todos os seus módulos (inclusive os de SQL Server!) com símbolos e os distribui gratuitamente na internet para que os profissionais que tiverem necessidade (ou interesse) pela utilização desses símbolos tenham acesso a eles e possam utilizá-los nas suas sessões de depuração (entre outras coisas que são possíveis através dos símbolos, mas falarei sobre isso em outro post :)).

Símbolos privados e públicos

Nem tudo são flores, infelizmente.

Existem dois tipos de símbolos, os chamados de privados, que podem ser utilizados juntamente do código-fonte do software para debugging por parte do desenvolvedor do mesmo e contém todas as informações à respeito do módulo, e os símbolos públicos, que são símbolos que contém um número bem menor de informações e que são distribuídos ao público geral.

Os símbolos públicos não contém informações bastante relevantes como tipagem de dados, parâmetros, entre outras coisas, mas já fornecem informação o suficiente para possibilitar o uso do WinDbg na depuração de problemas ou para ganhar um insight no funcionamento interno (interno mesmo!) do software.

Servidor de símbolos

Qualquer empresa pode disponibilizar os símbolos de seus módulos da maneira que preferir. A Microsoft disponibiliza os símbolos através de um servidor através da URL http://msdl.microsoft.com/download/symbols. Apesar de parecer uma URL comum, essa URL não é utilizada para navegação e sim na configuração do WinDbg para que ele mesmo baixe os símbolos de forma preguiçosa (por default, apesar de eu preferir carga imediata para evitar delays durante a depuração.)

Configuração dos símbolos

Quando o WinDbg precisa de algum símbolo que não está carregado, ele primeiramente irá procurar no diretório padrão de símbolos e, caso não encontre neste diretório irá procurá-los no servidor de símbolos.

Para configurar o WinDbg de forma a carregar os símbolos através do servidor oferecido pela Microsoft, temos diversas opções:

  1. Configuração à nível de sistema e/ou usuário através da variável de ambiente _NT_SYMBOL_PATH.
  2. Configuração à nível de sessão no Command Prompt, também através da variável de ambiente _NT_SYMBOL_PATH.
  3. Na sessão de debugging dentro do WinDbg através do comando .sympath (ou ainda automaticamente através de .symfix.)
  4. Ou ainda através do parâmetro -y na linha de comando do WinDbg.

Particularmente, eu prefiro deixar o ambiente configurado por facilidade na hora da depuração e por haver o compartilhamento da configuração com outras ferramentas que façam uso dos bancos de símbolos, como Xperf por exemplo.

Setting environment variable using the System Properties Window

Variável de ambiente - System Properties

No WinDbg:

Setting symbols path using the .sympath WinDbg command

Configuração de símbolos no WinDbg

Como já mencionado, apesar dos símbolos públicos não oferecerem informações bastante relevantes para o processo de debugging como os símbolos privados, com assinaturas completas de funções e métodos, e exigir um pouco mais de esforço, ainda é possível identificar variáveis e parâmetros na memória do processo. A brincadeira fica muito mais fácil quando estamos falando de APIs documentadas, como a Windows API, com as assinaturas facilmente encontradas no MSDN, bastando apenas um pouquinho de conhecimento da convenção de chamadas da arquitetura em uso, que hoje em dia é na maioria dos casos o x64:

Breakpoint at VirtualAlloc

Breakpoint em VirtualAlloc

Windows API e x64 call convention

A VirtualAlloc é uma API utilizada para reservar ou confirmar (commit) endereço de memória virtual (VAS) do processo. Como é possível ver acima, não temos nenhuma informação à respeito dos parâmetros que estão sendo utilizados na chamada dessa API, mas através da sua documentação podemos observar quais parâmetros são esperados por ela:

LPVOID WINAPI VirtualAlloc(
   _In_opt_  LPVOID lpAddress,
   _In_      SIZE_T dwSize,
   _In_      DWORD flAllocationType,
   _In_      DWORD flProtect
 );

A convenção de chamadas x64 da Microsoft determina que os 4 primeiros parâmetros serão colocados nos registradores 64-bit rcx, rdx, r8 e r9, nesta ordem. À partir dos 4 primeiros parâmetros a brincadeira fica um pouco menos direta, mas como nesse caso temos exatamente 4 parâmetros, não vamos nos preocupar com isso agora.

Parameters for VirtualAlloc in Windbg

Registradores com os parâmetros de VirtualAlloc

Vamos primeiro verificar os valores dos parâmetros e depois tentar entendê-los:

  • (LPVOID) lpAddres: Podemos ver que o primeiro parâmetro, lpAddress, recebeu o valor 0 ou NULL em C/C++.
  • (SIZE_T) dwSize: O segundo parâmetro recebeu o valor 80000.
  • (DWORD) flAllocationType: O terceiro parâmetro recebeu o valor 101000.
  • (DWORD) flProtect: O quarto e último parâmetro recebeu o valor 4.

Segundo a documentação no MSDN, se a API VirtualAlloc recebe no primeiro parâmetro lpAddress o valor NULL, significa que o sistema deve determinar o endereço de destino onde realizar a alocação da memória:

“If this parameter is NULL, the system determines where to allocate the region.”

O parâmetro dwSize, por sua vez, determina a quantidade de memória a ser alocada. No nosso caso o valor é 80000h = 524288 / 1024 = 512 KB:

“The size of the region, in bytes.”

flAllocationType determina o tipo de alocação, mas a tabela na documentação não informa o valor 101000 que recebemos. É comum em C e C++ passarmos múltiplas flags em um único parâmetro realizando o que chamamos de opereação de OR lógico (| em C/C++), portanto 101000 equivale  a:

  • MEM_COMMIT – 0x00001000
  • MEM_TOP_DOWN – 0x00100000

Por fim o parâmetro flProtect recebe o valor 4, que indica a o tipo de proteção da memória:

  • PAGE_READWRITE – 0x04

Portanto a chamada que depuramos na screenshot corresponde a uma alocação de 512 KB de memória virtual com proteção de leitura e escrita realizada pelo processo do SQL Server!

Existem algumas considerações a serem feitas à respeito dessa chamada, mas não vou me adentrar nesse assunto neste post. A documentação do MSDN explica muito bem a chamada e seus parâmetros se você quiser se aprofundar um pouco mais nessa ou no restante das APIs do Windows.

Estou com alguns outros posts de WinDbg à caminho, mas não poderia ter começado a série sem dar uma introdução bem básica à ferramenta. Espero que eu tenha conseguido explicar e demonstrar um pouquinho da utilização do WinDbg e aberto caminho para mais investigações e sessões de debugging no futuro!

Pin It

Ferramentas de um DBA SQL Server

Sempre acreditei que boas ferramentas ajudam na realização de um bom trabalho, e com o tempo e a experiência juntei algumas das ferramentas mais recorrentes no meu trabalho como DBA.

Algumas dessas ferramentas não estão diretamentes ligadas ao SQL Server, mas ajudam na hora de realizar algumas tarefas comuns aos administradores.

Essa lista não é de forma alguma exaustiva, mas quem sabe pode ser o primeiro post de uma série, não é? smile face

Vamos por ordem de mais genérica à mais pontual:

Command Prompt

Sem dúvida alguma a minha ferramenta favorita, independente de plataforma. Trabalhei alguns anos com Unices (BSDs, Solaris e Linux) e provavelmente a melhor lição que tirei dessa experiência foi o uso da linha de comando para tarefas repetitivas. Muita gente descarta o Command Prompt do Windows por não ser tão flexível como o shell (bash, zsh e cia.) dos Unices, mas acredito que quando utilizado juntamente com outras ferramentas (logo abaixo), ainda é bastante útil.

Sysinternals Tools

As melhores ferramentas para qualquer tipo de administração em plataformas Windows, em linha de comando ou GUI.
Estão disponíveis gratuitamente pela Microsoft aqui, ou melhor ainda, você pode mapear a unidade remota (chamado de Sysinternals Live) diretamente:

Command Prompt

Mapeando Sysinternals Live pelo Command Prompt

Dessa forma você terá acesso fácil sempre às versões mais recentes das ferramentas, pelo Command Prompt ou Windows Explorer:

Windows Explorer with Network Mapped Drive

Mapeamento do Sysinternals Live no Windows Explorer

SQLCMD

O SQLCMD é uma mão na roda para realizar tarefas repetitivas de setup de bancos de dados, por exemplo. Geralmente eu crio scripts T-SQL e os executo através de um arquivo de batch (.bat) pela linha de comando, através de um job, pelo Makefile, ou algo do gênero. O mais interessante do SQLCMD é que os scripts suportam parametrização, algo que também pode ser ativado de dentro do próprio SSMS:

SQL Server Management Studio - SQLCMD Mode

Ativando SQLCMD Mode no Management Studio

PowerShell

Logo PowerShell

Windows PowerShell

Seguindo a linha de prompt de comando, o PowerShell é tudo que o bash queria ser quando crescer (que venham os trolls! :)). Na minha opinião a troca de objetos entre comandos ao invés de texto-puro é uma grande sacada.

Eu utilizo com uma frequência menor do que gostaria, mas com a ajuda do maluco do Posh – também conhecido como Laerte Junior – eu estou aprendendo a ferramenta um pouco mais à fundo e pretendo acabar fazendo o upgrade total do Command Prompt para o PowerShell em breve. Com a chegada do v3, a popularização do PowerShell na comunidade – não só SQL Server, mas em geral – só tende a aumentar.

PerfMon

Indispensável para qualquer tipo de trabalho de planejamento de capacidade, troubleshooting de desempenho e tuning, entre diversas outras utilidades, o PerfMon é uma ferramenta essencial para qualquer DBA na plataforma Windows. Há quem diga que PerfMon é ferramenta de SysAdmin, mas eu discordo veementemente. Uma introdução legal feita pelo Brent Ozar pode ser encontrada aqui.

PAL

PAL ou Performance Analysis of Logs. Essa é a queridinha do meu amigo e colega de trabalho Fabiano Amorim. Dizem por aí que ele não vive sem o PAL por perto. Ele já demonstrou o uso da ferramenta em palestras, e eu deixo o link de um webcast sobre DBA Checklist que também pode te interessar que ele fez com o Luti aqui na Sr. Nimbus onde ele demonstra um pouco do uso da ferramenta. :)

 

Pin It

SQL Server + Nuvem

O blog ficou meio parado por algumas semanas… Após o último post tivemos dois cursos fantásticos (Internals e Indexing) na Sr. Nimbus, alguns projetos novos e bastante trabalho! E para quebrar o silêncio e a inércia, nada melhor do que falarmos sobre dois assuntos muito interessantes e que levamos bastante a sério aqui na Nimbus: SQL Server e cloud computing! Smile

Muito tem sido falado a respeito de bancos de dados “web scale” e NoSQL, e acho que esse vídeo resume bem a minha opinião sobre o assunto:

There ain’t no such thing as a free lunch

Após alguns anos de certa histeria entre a comunidade de desenvolvedores web pelo mundo afora, chegamos a um ponto onde percebemos que NoSQL não é exatamente a solução definitiva para todos os problemas, ou o que chamamos de silver bullet.

NuoDB Logo

NewSQL: NuoDB

A arquitetura dos bancos de dados NoSQL pode diferir significativamente uma da outra, porém em geral eles abrem mão das propriedades ACID (com exceções) em favor da “infinita” escalabilidade que tanto ouvimos falar, mas a verdade é que não existe nada inerente no SQL ou nas propriedades em si que não permitam o mesmo tipo de escalabilidade. Exemplo disso são os novos bancos de dados relacionais (chamados de NewSQL) que estão surgindo, como o NuoDB, que vem ganhando destaque pela sua escalabilidade e benchmarks.

No lado do SQL Server nós temos algumas opções quanto a nuvem.

A primeira delas, que vem sido bastante falada, é o Azure SQL Database (antigo SQL Azure).

O SQL Database não é exatamente SQL Server, mas é próximo o suficiente para podermos considerá-lo aqui. Apesar de ser limitado a bancos de dados de até 5 GB para a edição Web e 150 GB para a edição Business, o SQL Database possui um mecanismo muito interessante de escalabilidade “infinita” através de Federations (que hoje tem um soft-limit de 150 bancos de dados por servidor).

Outra opção é o serviço de bancos de dados relacionais da Amazon, o Amazon RDS.

O Amazon RDS nada mais é do que um servidor SQL Server fornecido e administrado pela Amazon, onde você pega em um modelo baseado em uso de infraestrutura (opcionalmente incluindo licenciamento), no modelo IaaS, ao contrário do Azure SQL onde pagamos pelo consumo propriamente dito. É mais ou menos como contratar um servidor EC2 na Amazon e instalar o SQL Server, porém sem ter que administrá-lo (até certo ponto). Apesar de ser SQL Server propriamente dito, nem todas as funcionalidades estão disponíveis e o custo é relativamente alto. (Vale dizer que o SQL Server está incluído no Free Usage Tier promocional de 1 ano para novos clientes. Mais informações aqui.)

Outra opção é, digamos, à moda antiga. Contratar um servidor EC2 com Windows Server e gerenciar seu próprio servidor de bancos de dados. Algo interessante nesse cenário é que a Amazon oferece imagens EC2 com SQL Server pré-instalado e com o licenciamento incluído no valor por hora da imagem, dessa forma eliminando a necessidade (e alto custo) de compra de uma licença para seu banco de dados, no formato pay-as-you-go. (A opção de utilizar uma licença já adiquirida também está disponível, com algumas restrições.)

Dessa forma você tem um servidor SQL Server com todas as suas funcionalidades, sem restrições (exceto, obviamente, as da sua licença).

Cenários

Azure SQL Database

Windows Azure Logo

Microsoft's Cloud

O mecanismo de Federations permite uma grande elasticidade no banco de dados, porém não funciona de forma transparente para as aplicações. É necessário tomar alguns cuidados na conexão do cliente ao banco e/ou realizar alterações em aplicações pré-existentes para que funcionem nesse tipo de cenário. Outro ponto importante é que mesmo sem utilizar Federations, o SQL Database não é 100% compatível com o SQL Server on-premise. Por esses motivos, o Azure SQL Database pode ser mais viável e vantajoso para novas aplicações. Outra importante vantagem do SQL Database em relação às outras opções é a alta-disponibilidade out-of-the-box oferecida pelo Windows Azure.

Amazon RDS

Apesar de ser efetivamente SQL Server, o RDS tem algumas limitações de funcionalidades que devem ser levadas em conta. O Jeremiah, da Brent Ozar PLF tem um post bem interessante à respeito do assunto.

SQL Server

SQL Server Logo Amazon Logo

SQL Server on Amazon

Provavelmente a minha opção favorita hoje é rodar o SQL Server em um servidor EC2 (ou em uma Windows Azure Virtual Machine) e ter o suporte completo de todas as funcionalidades que o seu licenciamento permite. Essa é a forma mais flexível e compatível de rodar o SQL Server na nuvem hoje e possibilita a migração das aplicações existentes hoje para a nuvem (por qualquer razão que seja), porém com o custo adicional de manutenção da instância (que feito corretamente pode ser bastante reduzido).

 

Com isso temos diversas opções de SQL Server na nuvem! A decisão de qual solução utilizar, porém, vai além da preferência pessoal e dos custos. Cada uma das opções tem um cenário bem perceptível e pré-definido, e que devem ser levados em consideração para evitar surpresas desagradáveis após colocar um sistema em produção. Winking smile

Pin It

SQL Server na nuvem! Azure vs Amazon. Round I: desempenho de I/O

Um dos privilégios de trabalhar em uma empresa como a Sr. Nimbus é a oportunidade de trabalhar com tecnologias de ponta, nesse caso estamos falando da computação em nuvem!

Dentre os principais players hoje nesse mercado, estão o Azure da Microsoft e o AWS da Amazon. Vamos cada vez mais falar sobre ambos por aqui, e como vocês já podem ver, na semana passada o Luti escreveu um pouco sobre isso.

Esse mês tivemos a oportunidade de “fritar” algumas máquinas virtuais nos dois serviços e fazer um levantamento de capacidade, e hoje nós vamos dar uma olhada na primeira bateria de testes que realizamos: subsistema de I/O. Mas antes vamos dar uma olhada a respeito das diferenças entre os serviços que podem afetar o benchmark.

Latência e Throughput de Rede

A Amazon utiliza placas de rede de 1 Gigabit em seus servidores, o que nos limita a um throughput de 120 MB por segundo, na melhor das hipóteses, e esse servidor com uma única placa gigabit pode estar sendo utilizado por dezenas de máquinas virtuais.

Mesmo que nós tenhamos toda a banda da placa gigabit do servidor disponível para nós, ainda temos que levar em consideração o fato de que nós não somos os únicos usuários da rede, e não temos nenhum controle sobre o seu tráfego. Se outros usuários do serviço estiverem fazendo uso dessa mesma infraestrutura e o workload fizer uso significativo desse recurso nós estaremos concorrendo diretamente pela banda da rede, o que pode vir a afetar significativamente o nosso desempenho.

Outro problema que temos que ter em mente é a latência de rede. Por não haver nenhum controle sobre o hardware nós não podemos escolher onde os nossos servidores serão alocados, e isso significa que o nosso servidor SQL Server pode ficar (fisicamente) muito afastado do storage, aumentando a nossa latência e impactando o throughput.

Metodologia dos testes

Os testes foram elaborados de forma a simular um workload “genérico” do SQL Server.

Cada instância em cada empresa possui um workload próprio e não é possível simular um perfil de I/O que consiga encapsular todas as combinações possíveis de acesso ao subsistema de disco em um servidor SQL Server. Dessa forma escolhemos alguns perfis que acreditamos fornecer dados de valor mais abrangente e não necessariamente pontuais, e assim coletar informações úteis para mais de um tipo de workload. O objetivo principal é coletar dados suficientes que nos deem confiança para executar um servidor SQL Server na nuvem com desempenho razoável.

Os nossos testes são separados por perfis de escrita e leitura (50/50) de blocos de 64KB (SQL 64KB R50 W50), operações predominantemente de leitura (90%) com escrita não-sequencial, isso é, de acesso aleatório em blocos de 64 KB (SQL 64KB R90 W), operações de acesso sequencial de escrita (100%) em blocos de 64 KB (SQL 64KB Write Sequential) e por fim operações predominantemente de leitura (90%) em blocos de 256KB (SQL 256KB R90 W).

Realizamos testes com três ferramentas, e no final optamos por utilizar o excelente Iometer, originalmente desenvolvido pela Intel e posteriormente liberado para a comunidade Open Source, para realizar os testes do subsistema de I/O por oferecer muito mais flexibilidade de configurações finas em relação ao SQLIO, da Microsoft, e o CrystalDiskMark, da CrystalMark. Se você quiser saber um pouco mais sobre as configurações das ferramentas, o Brent Ozar já falou sobre isso no seu blog, aqui.

Todos os testes foram realizados com 8 threads (um em cada vCPU), por um período de 120 segundos por execução, um intervalo entre eles de ramp-up de 30 segundos e uma fila de 8 outstanding I/Os por teste.

Utilizamos apenas um disco alocado diretamente do serviço de storage de cada cloud: EBS na Amazon e Blob Storage no Azure, sem configurações de RAID, montados diretamente em uma partição e formatados com clusters de 64 KB.

Como dito acima, foram executados diversos testes com diferentes configurações, mas por questão de simplicidade vamos colocar aquela que acreditamos ser mais relevante, com maior número de outstanding I/Os, já que é natural vermos o SQL Server disparando bursts no subsistema de entrada e saída.

Diferença de hardware

Por não haver disponível servidores com as mesmas configurações em ambos os serviços nós optamos por utilizar as melhores configurações de máquinas virtuais de cada serviço. Dessa forma foi possível testar a capacidade máxima de desempenho que ambos os serviços disponibilizam hoje no mercado.

Serviço Nome da instância CPU (Núcleos) Memória
Amazon High-Memory Quadruple Extra Large 8 68.4 GB
Azure Extra Large 8 14 GB

Infelizmente a VM com maior quantidade de memória disponível hoje no Azure é de 14 GB, talvez em razão do serviço de VMs do Azure ainda estar em fase de preview, mas a Microsoft ainda não disse nada a respeito então não podemos dizer com certeza. Na questão de CPUs, entretanto, ambos os serviços disponibilizam máquinas virtuais com 8 núcleos.

Para os testes de hoje, por ser um workload I/O bound, não existe diferença significativa entre as configurações das VMs do Azure e da Amazon para justificarem qualquer eventual diferença de desempenho e portanto as configurações são satisfatórias.

O nosso interesse nesses benchmarks primariamente é definir a possibilida de execução de projetos envolvendo o SQL Server na nuvem. Adicionalmente queremos definir como ambos os serviços se comportam em comparação um ao outro e onde cada um se sai melhor em termos de desempenho.

Até aqui tudo certo, então chega de descrições e vamos aos testes!

Gráficos

image004

No caso do Azure nós já podemos perceber um tempo médio de resposta de operação de I/O significativamente maior em relação à Amazon, o que à primeira vista sugere uma latência ou sobrecarga maior na rede, mas como veremos a seguir pode não ser verdade.

image006

Neste gráfico, porém, podemos identificar que o principal responsável pelo altíssimo índice de Response Timeno Azure são as operações de Leitura, sendo o tempo de resposta das operações de Escrita no Azure inferiores ao do AWS. Temos algumas suspeitas sobre o motivo que leva a essa enorme diferença de desempenho entre as operações, mas vamos investigar um pouco mais a fundo antes de tirarmos conclusões a respeito.

image008

image010

image012

image014

Resultados

Através dos gráficos acima podemos observar que a Amazon foi capaz de obter resultados muito superiores em workloads que envolviam operações aleatórias, em particular no benchmark de leitura de blocos de 256 KB e 64 KB.

O Azure, por sua vez, conseguiu um nível melhor de desempenho apenas no benchmark de escrita 100% sequencial de blocos de 64 KB, mas com uma margem de superioridade percentualmente insignificante próximo ao desempenho apresentado pelo AWS no mesmo teste.

O Azure apresentou um desempenho significativamente inferior ao do AWS em todos os outros testes realizados, algumas vezes ficando com um desempenho inferior ao de 10% em comparação ao apresentado pela Amazon, o que foi uma surpresa para nós.

Estamos trabalhando com ambas as plataformas e pretendemos continuar detalhando as suas diferenças arquiteturais, que podem ser responsáveis por tal diferença de desempenho.

Segue abaixo o gráfico de desempenho final, de throughput total (MB/s) em ambos os serviços, onde é possível visualizar o forte desempenho da nuvem da Amazon em relação ao Azure nos nossos testes. A cor verde escura representa operações de Leitura (R) e o verde claro representa operações de Escrita (W):

image016

Conclusão

Vale ressaltar que o IaaS no Windows Azure é um serviço novo, ainda em preview e que deve receber diversas melhorias ao longo dos próximos meses, antes do seu lançamento final, inclusive um possível lançamento de configurações superiores de VMs, com maior quantidade de memória RAM. Ainda é muito cedo para tirar conclusões a respeito do serviço oferecido pela Microsoft, mas já é possível observar que eles terão bastante trabalho pela frente para equiparar a performance de I/O do seu IaaS com o da atual líder do mercado, a Amazon.

O Amazon Web Services, por outro lado, é um serviço maduro oferecido pela Amazon desde 2006, ou seja, há pelo menos 6 anos. O AWS se mostrou muito superior ao Azure nesse momento em termos de desempenho de I/O, especialmente em operações de Leitura.

Da equipe da Nimbus, os testes com cloud computing vão continuar e cada vez mais aprofundaremos nas características e configurações de cada player, e temos certeza que os resultados vão poder ajuda-lo a tomar decisões mais acertadas para o seu negócio, como por exemplo, considerar utilização de IaaS para o seu SQL Server, e todos os benefícios que a economia de escala pode trazer.

Pin It

Gerenciamento de Memória no Windows

Quero falar um pouco sobre o Buffer Manager do SQL Server, mas antes de começarmos acredito que é interessante repassar alguns conceitos de gerenciamento de memória do Windows:

Memória Virtual

O VAS, ou Virtual Address Space corresponde ao espaço de memória virtual de um processo. Através do VAS, cada processo no Windows tem a impressão de estar rodando em um enorme espaço de memória contígua não-compartilhada. Indeferente da real quantidade de memória física do sistema (16 GB, por exemplo), em sistemas x86, a memória virtual de cada processo tem um tamanho padrão de 2 GB, enquanto em sistemas X64 o processo recebe um espaço de endereçamento virtual de “exagerados” (para os padrões atuais) 8 TB.

Mesmo que a memória utilizada por um processo esteja (fisicamente) espalhada entre diversas áreas da memória física ou ainda paginadas no disco rígido, para o processo a memória acessível sempre terá um aspecto uniforme e contíguo.

Durante o tempo de execução do processo o componente do processador chamado de MMU (memory management unit) fará o mapeamento da memória virtual do processo à memória física do sistema através de page tables, ou tabelas de página, criadas pelo gerenciador de memória do Windows, e são os responsáveis por armazenar os mapeamentos entre os endereços virtuais da memória do processo e seus endereços reais correspondentes (físicos). A tabela de página do processo contém diversas Page Table Entries (PTEs), uma para cada página de memória virtual do processo.

Através deste mecanismo o sistema pode garantir que um processo não poderá afetar diretamente (propositada ou despropositadamente) a memória de outro processo rodando no mesmo sistema.

Outra característica de sistemas que utilizam memória virtual (como o Windows) é que ele permite que cada processo em execução em um sistema tenha acesso a uma quantidade possivelmente muito superior à memória física instalada. Nas versões 64-bit do Windows, por exemplo, a memória virtual de um processo corresponde a um total de 8 TB, e isso, como dito anteriormente, independente da memória física instalada.

Nas versões 32-bit, o processo fica restrito ao um VAS muito menor, de apenas 4 GB, sendo por padrão 2 GB para uso do sistema operacional e apenas 2 GB do usuário (aplicação). Essas configurações podem ser alteradas durante o processo de boot do Windows (através dos switchs /3GB no Windows 2003 e /set IncreateUserVa 3072 nas versões mais recentes), mas o processo continua restringido aos 4 GB, ou seja, a nova memória alocada para uso do processo foi tirada diretamente da memória disponível para a execução do SO, e agora é dividida como 3 GB + 1 GB.

Existem outras técnicas para superar esse limite mas não entraremos nos méritos aqui por não agregarem valor à nossa discussão. Você pode encontrar mais informações à respeito no fim deste artigo, nos links para leitura adicional.

É interessante notar que atualmente a edição mais robusta (Datacenter) do Windows Server mais atual (2008 R2) suporta um máximo de 2 TB de memória física em sistemas X64. É fácil notar, portanto, que o VAS não corresponde à memória física do sistema.

Memória Reservada e Memória Confirmada

As páginas em memória virtual podem estar em 3 estados:

  1. Reservada (MEM_RESERVE)
  2. Confirmada (MEM_COMMIT)
  3. Livre (MEM_FREE)

Uma thread de execução em um processo pode reservar um espaço de memória virtual sem que haja uso desnecessário de armazenamento (ex.: memória física) para aquele espaço, ou seja, reservar 10 MB de memória virtual não irá causar o consumo de 10 MB de armazenamento (ex.: memória física). Páginas de memória virtual confirmadas, por outro lado, são mapeadas à um armazenamento e consomem os recursos dos quais representam. Alocar e confirmar 10 MB de memória virtual irá causar o consumo de 10 MB de armazenamento (ex.: memória física).

Processos que necessitam de grande quantidades de memória (como o SQL Server) podem utilizar o processo de reservar e confirmar memória separadamente para evitar o desperdício de recursos preciosos do sistema (ex.: memória física), evitando confirmar o uso de memória até que esta seja realmente necessária, mas ainda assim manter o benefício de alocar grandes espaços de memória virtual contígua. Por exemplo, um thread poderia reservar 1 GB de memória virtual (do endereço 0x00f60000 ao endereço 0x40f6000000:

DWORD dwMemSize = 1024 * 1024 * 1024; // 0x40000000 = 1 GB
LPVOID lpMem = VirtualAlloc(0, dwMemSize, MEM_RESERVE, PAGE_READWRITE);
image 

Uma página reservada ou confirmada pode ainda ter 3 diferentes tipos:

  1. Privada (MEM_PRIVATE)
  2. Mapeada (MEM_MAPPED)
  3. Imagem (MEM_IMAGE)

Páginas privadas pertencem ao processo, não podem ser compartilhadas e podem ser escritas no arquivo de paginação do Windows se necessário (ex.: pressão de memória). Páginas confirmadas e mapeadas são páginas alocadas através de APIs de mapeamento de arquivos e estão associadas à um arquivo em disco:

image

Páginas de memória virtual do tipo MEM_IMAGE são páginas utilizadas para mapear um arquivo de imagem PE (.exe, .dll) no espaço de endereçamento virtual do processo, inclusive a sua própria imagem (ex.: sqlservr.exe):

0:059> !vadump
...
BaseAddress:       0000000000d70000
RegionSize:        0000000000001000
State:             00001000  MEM_COMMIT
Protect:           00000002  PAGE_READONLY
Type:              01000000  MEM_IMAGE
...
BaseAddress:       000000006ffe0000
RegionSize:        0000000000001000
State:             00001000  MEM_COMMIT
Protect:           00000002  PAGE_READONLY
Type:              01000000  MEM_IMAGE
...

E recuperamos informações sobre a imagem mapeada no endereço:

0:059> !dh 0000000000d70000

File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
    8664 machine (X64)
       8 number of sections
4DB2C9AD time date stamp Sat Apr 23 09:44:29 2011
...
0000000000d70000 image base
0:059> !lmi 0000000000d70000
Loaded Module Info: [0000000000d70000]
         Module: sqlservr
   Base Address: 0000000000d70000
     Image Name: C:SQL ServerMSSQL10_50.MSSQLSERVERMSSQLBinnsqlservr.exe
   Machine Type: 34404 (X64)
     Time Stamp: 4db2c9ad Sat Apr 23 09:44:29 2011
           Size: 3bb0000
       CheckSum: 3b10238
Characteristics: 22  perf
Debug Data Dirs: Type  Size     VA  Pointer
             CODEVIEW    25, 2bbb324, 2bba724 RSDS - GUID: {E0E45C4E-B0C6-4908-A902-...}
               Age: 2, Pdb: sqlservr.pdb
                CLSID     4, 2bbb320, 2bba720 [Data not mapped]
     Image Type: FILE     - Image read successfully from debugger.
                 C:SQL ServerMSSQL10_50.MSSQLSERVERMSSQLBinnsqlservr.exe
    Symbol Type: PDB      - Symbols loaded successfully from symbol server.
                 c:symbolssqlservr.pdbE0E45C4EB0C64908A90279B30F42FACA2sqlservr.pdb
    Load Report: public symbols , not source indexed
                 c:symbolssqlservr.pdbE0E45C4EB0C64908A90279B30F42FACA2sqlservr.pdb
0:059> !lmi 000000006ffe0000
Loaded Module Info: [000000006ffe0000]
         Module: xpstar
   Base Address: 000000006ffe0000
     Image Name: c:SQL ServerMSSQL10_50.MSSQLSERVERMSSQLBinnxpstar.dll
   Machine Type: 34404 (X64)
     Time Stamp: 4bb67993 Fri Apr 02 20:11:15 2010
           Size: 88000
       CheckSum: 93cb2
Characteristics: 2022
Debug Data Dirs: Type  Size     VA  Pointer
             CODEVIEW    23,  a5b8,    99b8 RSDS - GUID: {6DEA79A6-908B-4178-9F73-...}
               Age: 1, Pdb: XPSTAR.pdb
     Image Type: FILE     - Image read successfully from debugger.
                 c:SQL ServerMSSQL10_50.MSSQLSERVERMSSQLBinnxpstar.dll
    Symbol Type: PDB      - Symbols loaded successfully from symbol server.
                 c:symbolsXPSTAR.pdb6DEA79A6908B41789F734A3EB6CA9EC41XPSTAR.pdb
    Load Report: public symbols , not source indexed
                 c:symbolsXPSTAR.pdb6DEA79A6908B41789F734A3EB6CA9EC41XPSTAR.pdb

Working Set

E no caso do processo utilizar mais memória virtual do que a memória física disponível no servidor?

Bom, nesse caso temos o que é chamado de paging, ou paginação.

Dentro do espaço de memória virtual (VAS) do processo, existe o Working Set, que nada mais é do que o conjunto de páginas de memória confirmadas que foram recentemente utilizados pelo processo e se encontram em memória física. Quando a memória de um processo é removida do seu Working Set, ela pode ser colocada em dois destinos:

  1. Se esta página não foi modificada enquanto estava no Working Set ela será colocada diretamente na lista de páginas em standby.
  2. Caso contrário essa página irá para a lista de páginas modificadas (modified pages), onde fica até ser escrita em disco (paged out), no arquivo de paginação ou em um arquivo mapeado em memória, e só então será colocada na lista de páginas em standby.

As páginas em standby, apesar de serem consideradas “memória livre”, ainda estão ligadas a um processo e caso esse processo necessite novamente de uma dessas páginas, haverá um soft memory fault, e essa página será rapidamente recuperada e recolocada no Working Set do processo.

É interessante notar, portanto, que memória livre no sistema não significa necessariamente memória desperdiçada. Essa memória está ligada a algum processo para permitir sua recuperação de forma rápida caso este processo venha a utilizá-la novamente.

Quando uma página permanece na lista de standby por mais que um determinado período, esta página é então zerada e colocada na lista de páginas zeradas. Se houver a necessidade de liberar essa página para uso por outro processo, ela estará pronta para ser colocada em seu Working Set.

Se o processo requisitar uma página da memória que não se encontra mais em seu Working Set e já foi removida da lista de standby, é gerado então um hard memory fault (ao contrário do soft memory fault), e esta página será buscada à partir do armazenamento de suporte à qual pertencia essa memória (arquivo de paginação ou um arquivo mapeado na memória pelo processo), colocada em memória física e alocada no Working Set do processo.

SQL Server

O assunto é bem extenso e ainda faltou muita coisa pra cobrir, mas acredito que foi possível dar uma revisada nos principais conceitos que vamos precisar para o próximo post sobre o gerenciamento de memória no SQL Server, em especial o gerenciamento do Buffer Pool, o maior e principal consumidor de memória de um servidor SQL.

Referências e leitura adicional

Physical Memory Limits: Windows Server 2008 R2
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366778(v=vs.85).aspx#physical_memory_limits_windows_server_2008_r2
Working Set
http://msdn.microsoft.com/en-us/library/windows/desktop/cc441804(v=vs.85).aspx
How to use the /userva switch with the /3GB switch to tune the User-mode space to a value between 2 GB and 3 GB
http://support.microsoft.com/kb/316739
Windows Internals 5th Edition
http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx
Windows via C/C++
http://www.microsoft.com/learning/en/us/book.aspx?id=11241&locale=en-us
Inside Windows Debugging
http://blogs.msdn.com/b/microsoft_press/archive/2012/05/31/new-book-inside-windows-debugging.aspx

Pin It