{"id":471,"date":"2015-02-08T23:32:48","date_gmt":"2015-02-09T02:32:48","guid":{"rendered":"http:\/\/thesqltimes.com\/blog\/?p=471"},"modified":"2015-02-08T23:32:48","modified_gmt":"2015-02-09T02:32:48","slug":"after-virtual-pass-pt-sql-server-cpuing-part-i","status":"publish","type":"post","link":"https:\/\/thesqltimes.com\/blog\/2015\/02\/08\/after-virtual-pass-pt-sql-server-cpuing-part-i\/","title":{"rendered":"After Virtual Pass PT: SQL Server CPUing &#8211; Part I"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"Muito \u00fatil!\" data-post-id=\"471\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">    <\/span>\r\n<\/div><\/div><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Tempo de Leitura:<\/span> <span class=\"rt-time\"> 4<\/span> <span class=\"rt-label rt-postfix\">minutos<\/span><\/span><p>Salve, galera.<\/p>\n<p>Este \u00e9 o primeiro post pelo\u00a0THE SQL TIMES e vou aproveitar a novidade para compartilhar o conte\u00fado\u00a0do meu primeiro webcast, que foi pelo <a title=\"VIRTUAL PASS PT\" href=\"http:\/\/www.virtualpass.com.br\" target=\"_blank\">Virtual Pass PT<\/a>.<\/p>\n<p>Eu disponibilizei a apresenta\u00e7\u00e3o, tanto em PPSX quanto em PDF, e a ferramenta que usei para fazer a DEMO, juntamente com o c\u00f3digo fonte. Voc\u00ea pode baixar <a title=\"Download dos arquivos da apresenta\u00e7\u00e3o\" href=\"https:\/\/drive.google.com\/folderview?id=0B9MFBfb3HCHXQ2t6eDNTdzNxNFk&amp;usp=drive_web\" target=\"_blank\">aqui, no Google Drive<\/a>.<\/p>\n<p>A ideia era demonstrar como o Windows apresenta as informa\u00e7\u00f5es de uso de CPU (a porcentagem de uso). Para isso eu elaborei uma ferramenta que n\u00e3o s\u00f3 me permitiu controlar a demo, como tamb\u00e9m me permitiu validar tudo o que foi falado.\u00a0Eua batizei de\u00a0&#8220;CPU SPENDER&#8221; e escrevi em C. O c\u00f3digo foi escrito\u00a0apenas para fins\u00a0did\u00e1ticos, portanto, pode ser melhorado em bastantes aspectos.<\/p>\n<p>Aproveitando o assunto, um amigo que viu o webcast me disse que havia ficado muito curioso para entender como o c\u00f3digo funcionava. Bom, para refor\u00e7ar o que eu falei no webcast, vou tentar resumir neste post.<\/p>\n<p>Na apresenta\u00e7\u00e3o, eu mencionei que o gasto de CPU de uma thread \u00e9 contabilizado baseado em um intervalo de coleta. Ou seja, o percentual de uso de uma thread depende do intervalo que est\u00e1 sendo considerado. Nas ferramentas como o task manager, o process explorer e o perfmon, esse intervalo \u00e9 de 1 segundo, por padr\u00e3o. Por exemplo, se em 1 segundo, uma thread A gastou 900 milissegundos de tempo de CPU, os contadores para esta thread ir\u00e3o marcar um uso de 90%:<\/p>\n<figure id=\"attachment_473\" aria-describedby=\"caption-attachment-473\" style=\"width: 1024px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/thread900ms_1segundo.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-473 size-large\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/thread900ms_1segundo-1024x497.png\" alt=\"Thread em 90%, em um intervalo de 1 segundo\" width=\"1024\" height=\"497\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/thread900ms_1segundo-1024x497.png 1024w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/thread900ms_1segundo-300x146.png 300w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/thread900ms_1segundo.png 1650w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption id=\"caption-attachment-473\" class=\"wp-caption-text\">Thread em 90%, em um intervalo de 1 segundo<\/figcaption><\/figure>\n<p>Se o intervalo de coleta for de 500 milisegundos, ent\u00e3o os contadores de CPU ir\u00e3o mostrar 100% no primeiro intervalo, e no pr\u00f3ximo intervalo (os pr\u00f3ximos 500 milisegundos), a sua thread ir\u00e1 marcar 80%. A imagem abaixo facilita esse entendimento:<\/p>\n<figure id=\"attachment_474\" aria-describedby=\"caption-attachment-474\" style=\"width: 1024px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/thread900ms_500ms.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-474 size-large\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/thread900ms_500ms-1024x489.png\" alt=\"Thread em 100% no primeiro intervalo, e 80% no segundo\" width=\"1024\" height=\"489\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/thread900ms_500ms-1024x489.png 1024w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/thread900ms_500ms-300x143.png 300w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/thread900ms_500ms.png 1632w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption id=\"caption-attachment-474\" class=\"wp-caption-text\">Thread em 100% no primeiro intervalo, e 80% no segundo<\/figcaption><\/figure>\n<p>O\u00a0CPU-SPENDER utiliza esses conceitos para &#8220;gastar processamento&#8221;. \u00a0Ao criar um &#8220;SPENDER&#8221;, a ferramenta cria duas threads. Uma thread \u00e9 a &#8220;<strong>spender thread<\/strong>&#8221; (irei chamar de spender somente) e a outra \u00e9 a &#8220;<strong>control thread<\/strong>&#8221; (irei chamar de control). \u00a0Quando a <strong>spender<\/strong> inicia, ela entra em um loop infinito, onde o corpo do loop \u00e9 apenas o incremento de uma vari\u00e1vel i (i++):<\/p>\n<pre class=\"lang:c decode:true \">\twhile(spender-&gt;live){\r\n\t\ti++;\r\n\t}<\/pre>\n<p>Isso faz com que a thread utilize o processador para executar a instru\u00e7\u00e3o ADD. A condi\u00e7\u00e3o do loop, \u00e9 uma vari\u00e1vel acess\u00edvel por ambas as threads: <strong>spender-&gt;live<\/strong>. Enquanto essa\u00a0vari\u00e1vel for igual a 1, a <strong>spender<\/strong>\u00a0continua efetuando a soma. Percebam que a <strong>spender<\/strong>\u00a0 faz, al\u00e9m do incremento, a compara\u00e7\u00e3o da vari\u00e1vel com 1 para manter o loop, o que requer o uso de mais algumas instru\u00e7\u00f5es.\u00a0A <strong>control<\/strong>\u00a0\u00e9 a thread que entra em a\u00e7\u00e3o a cada 1000 milissegundos (1 segundo). Esta thread\u00a0deixa a <strong>spender<\/strong>\u00a0executar pelo n\u00famero de milissegundos que foi configurado. Ap\u00f3s passar este tempo, ela entra em a\u00e7\u00e3o e coloca a &#8220;spender thread&#8221; para a fila de espera do schedule do Windows. Ele s\u00f3 libera a spender quando passa os milissegundos restantes para completar 1 segundo. Ap\u00f3s isso ele libera a thread e repete o processo. Isso continua enquanto a vari\u00e1vel <strong>spender-&gt;thread<\/strong> for 1, tamb\u00e9m. Segue o trecho do c\u00f3digo executado pela control thread referente ao que foi descrito acima:<\/p>\n<pre class=\"lang:c decode:true\">\twhile(spender-&gt;live){\r\n\t\t\r\n\t\t\/*\r\n\t\tNeste ponto n\u00f3s vamos calcular por quanto tempo a control thread\r\n dever\u00e1 adormecer antes de liberar a spender thread. \r\nPor exemplo, se a spender estiver configurada para executar por 100 milissegundos, e o intervalo for de 1000 milissegundos, ent\u00e3o esta thread dever\u00e1 dormir por 900 milissegundos antes de liberar a control thread. \r\nspener-&gt;maxExecution cont\u00e9m o valor, em milissegundos, que a spender thread dever\u00e1 \"gastar\".*\/\r\n\t\tLeftTime = FULL_INTERVAL_TIME - spender-&gt;maxExecution;\r\n\r\n\t\t\/\/Aqui n\u00f3s adormecemos a control thread antes de pausar a spender thread. Ela ir\u00e1 adormecer pelo mesmo tempo que a spender dever\u00e1 \"gastar\"\r\n\t\tSleep(spender-&gt;maxExecution);\r\n\r\n\t\t\/\/Ap\u00f3s a control acordar, ela imediatamente suspende a spender\r\n\t\tSuspendThread(spender-&gt;spenderThread);\r\n\r\n\t\t\/*Neste ponto a spender estar\u00e1 sem gastar quaisquer ciclos da CPU.\r\nEnt\u00e3o vamos adormecer a control novamente at\u00e9 o fim do intervalo.*\/\r\n\t\tSleep(LeftTime);\r\n\r\n\t\t\/\/Ap\u00f3s acordar, colocamos a spender para executar novamente.\r\n\t\tResumeThread(spender-&gt;spenderThread);\r\n\t}<\/pre>\n<p>A macro FULL_INTERVAL_TIME cont\u00e9m o tempo de 1 intervalo de coleta, em milissegundos. Para o nossos testes, 1000 (1 segundo) \u00e9 o valor adequado. A imagem abaixo ilustra melhor:<\/p>\n<p><a href=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/cpu_spender.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-476\" src=\"http:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/cpu_spender-1024x460.png\" alt=\"cpu_spender\" width=\"1024\" height=\"460\" srcset=\"https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/cpu_spender-1024x460.png 1024w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/cpu_spender-300x135.png 300w, https:\/\/thesqltimes.com\/blog\/wp-content\/uploads\/2015\/02\/cpu_spender.png 1979w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<p>\u00c9 claro, que vamos ter algumas diferen\u00e7as, e n\u00e3o conseguirmos\u00a0o n\u00famero exato, pois ha v\u00e1rios fatores que influenciam, al\u00e9m de que podem haver outras threads\u00a0executando. Para tentar minimizar os efeitos, na inicializa\u00e7\u00e3o do programa ele \u00e9 configurado para rodar em prioridade alta, tanto do processo, quanto as threads. Isso permite que outras threads n\u00e3o interfiram tanto em nossos testes. A control thread passa a maior parte do tempo dormindo do que executando, e quando executa, n\u00e3o gasta um n\u00famero consider\u00e1vel de instru\u00e7\u00f5es, o que deixa o seu &#8220;overhead&#8221; insignificante.<\/p>\n<p>Espero que tenham gostado da apresenta\u00e7\u00e3o, e caso isso tenha ficado muito confuso, n\u00e3o hesitem em deixar um coment\u00e1rio para que eu possa melhorar e tentar ser mais claro. Mais adiante, irei falar mais desse assunto, desde o in\u00edcio.<\/p>\n<p>At\u00e9 a pr\u00f3xima, e bem vindo ao <strong>THE SQL TIMES!<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Salve, galera. Este \u00e9 o primeiro post pelo\u00a0THE SQL TIMES e vou aproveitar a novidade para compartilhar o conte\u00fado\u00a0do meu primeiro webcast, que foi pelo Virtual Pass PT. Eu disponibilizei a apresenta\u00e7\u00e3o, tanto em PPSX quanto em PDF, e a ferramenta que usei para fazer a DEMO, juntamente com o c\u00f3digo fonte. Voc\u00ea pode baixar&hellip;&nbsp;<a href=\"https:\/\/thesqltimes.com\/blog\/2015\/02\/08\/after-virtual-pass-pt-sql-server-cpuing-part-i\/\" rel=\"bookmark\"><span class=\"screen-reader-text\">After Virtual Pass PT: SQL Server CPUing &#8211; Part I<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":473,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"categories":[1],"tags":[],"series":[],"class_list":["post-471","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/471","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/comments?post=471"}],"version-history":[{"count":3,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/471\/revisions"}],"predecessor-version":[{"id":477,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/posts\/471\/revisions\/477"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/media\/473"}],"wp:attachment":[{"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/media?parent=471"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/categories?post=471"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/tags?post=471"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/thesqltimes.com\/blog\/wp-json\/wp\/v2\/series?post=471"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}