{"id":461,"date":"2021-02-28T14:43:06","date_gmt":"2021-02-28T17:43:06","guid":{"rendered":"https:\/\/millerdantas.wordpress.com\/?p=461"},"modified":"2021-03-11T21:57:20","modified_gmt":"2021-03-12T00:57:20","slug":"sobre-otimizacao-em-aplicacoes-net-parte-1","status":"publish","type":"post","link":"https:\/\/millerdantas.com\/blog\/2021\/02\/28\/sobre-otimizacao-em-aplicacoes-net-parte-1\/","title":{"rendered":"Sobre otimiza\u00e7\u00e3o em aplica\u00e7\u00f5es .Net &#8211; Parte 1"},"content":{"rendered":"\r\n<p>Bom, acredito que nunca tenha postado algo espec\u00edfico do meu trabalho.<\/p>\r\n\r\n\r\n\r\n<p>Um dos motivos para isso seria que parte das coisas que fa\u00e7o s\u00e3o muito sens\u00edveis para compartilhar.<\/p>\r\n\r\n\r\n\r\n<p>Mas esse final de semana comecei um projeto do zero para identificar e otimizar o <a href=\"https:\/\/github.com\/millerscout\/Kenshi-Mod-Manager\">Kenshi Mod Manager<\/a> (KMM) do jogo <a href=\"https:\/\/store.steampowered.com\/app\/233860\/Kenshi\/\">Kenshi<\/a>, porque isso vai me deixar exercitar as tarefas que preciso em meu trabalho e o risco \u00e9 mais controlado.<\/p>\r\n\r\n\r\n\r\n<p>Resumidamente o gerenciador tem v\u00e1rios recursos, mas quando desenvolvi h\u00e1 cerca de um ano, haviam problemas s\u00e9rios de performance, bom&#8230; n\u00e3o pro meu pc, mas pra quem utiliza.<\/p>\r\n\r\n\r\n\r\n<p>Tenho cerca de 300+ mods, e indexar os conflitos nele causam ~1GBs e um tempo consider\u00e1vel pra apresentar as falhas<\/p>\r\n\r\n\r\n\r\n<p><\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Como que comecei a an\u00e1lise<\/h2>\r\n\r\n\r\n\r\n<p>O KMM \u00e9 um WPF em .Net Core 3.1 e eu acho realmente muito trabalhoso analisar cada parte do c\u00f3digo sem ter uma ferramenta externa, j\u00e1 que o projeto j\u00e1 passou de 5K de linhas..<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/millerdantas.files.wordpress.com\/2021\/02\/image.png?w=966\" alt=\"\" class=\"wp-image-466\"\/><\/figure>\r\n\r\n\r\n\r\n<p>Ent\u00e3o j\u00e1 que eu precisava estudar <a href=\"https:\/\/grpc.io\/\">gRPC<\/a> iniciei primeiro criando dois projetos, um server e um client.<\/p>\r\n\r\n\r\n\r\n<p>sendo que o server est\u00e1 no KMM e o client em um console no <a href=\"https:\/\/github.com\/millerscout\/MMDHelpers.CSharp\">MMDHelpers<\/a>.<\/p>\r\n\r\n\r\n\r\n<p>A altera\u00e7\u00e3o no KMM foi muito simples, bom &#8230; j\u00e1 que ele n\u00e3o era uma aplica\u00e7\u00e3o web, eu apenas subi o kestrel.<\/p>\r\n\r\n\r\n\r\n<p>Uma observa\u00e7\u00e3o, neste webserver que eu estou subindo, estou ignorando a parte de seguran\u00e7a completamente, j\u00e1 que irei identificar os problemas, remover o pacote e disponibilizar a nova vers\u00e3o.<\/p>\r\n\r\n\r\n\r\n<p><\/p>\r\n\r\n\r\n\r\n<p>Com o <a href=\"https:\/\/github.com\/millerscout\/MMDHelpers.CSharp\/tree\/master\/MMDHelpers.CSharp.Performance.GrpcClient\">Client<\/a> eu pude enviar comando para iniciar ou terminar as m\u00e9tricas no KMM<\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-embed is-type-rich is-provider-embed wp-block-embed-embed\"><div class=\"wp-block-embed__wrapper\">\r\nhttps:\/\/gist.github.com\/millerscout\/e9228ffe5f61edf9f151cab3aa61dbf7\r\n<\/div><figcaption>Simples n\u00e3o?<\/figcaption><\/figure>\r\n\r\n\r\n\r\n<p>o resultado foi este: <\/p>\r\n\r\n\r\n\r\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/millerdantas.files.wordpress.com\/2021\/02\/image-4.png?w=502\" alt=\"\" class=\"wp-image-483\"\/><\/figure><\/div>\r\n\r\n\r\n\r\n<p>Eu consigo observar quantas coletas em Gen0-2, a quantidade de mem\u00f3ria e o tempo que levou.<\/p>\r\n\r\n\r\n\r\n<p>o tempo aqui n\u00e3o \u00e9 meu foco ainda, mais para abaixo explico uma otimiza\u00e7\u00e3o para tempo (mas \u00e9 tiro de canh\u00e3o pra matar mosca)<\/p>\r\n\r\n\r\n\r\n<p><\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Primeiro Passo<\/h2>\r\n\r\n\r\n\r\n<p>Particularmente eu tento quebrar os problemas mais complexos para o mais simples poss\u00edvel, e existe um item que n\u00e3o tinha nenhuma coleta no GC mas era o primeiro item que eu queria otimizar<\/p>\r\n\r\n\r\n\r\n<p>Temos aqui o cen\u00e1rio: <\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-embed is-type-rich is-provider-embed wp-block-embed-embed\"><div class=\"wp-block-embed__wrapper\">\r\nhttps:\/\/gist.github.com\/millerscout\/a628f32fb4edd9d710c0fbb6c2b775ff\r\n<\/div><\/figure>\r\n\r\n\r\n\r\n<p>O c\u00f3digo nem causa problema, afinal s\u00f3 estou usando o IO.Path.GetExtension e comparando se o arquivo est\u00e1 naquela extens\u00e3o.<\/p>\r\n\r\n\r\n\r\n<p>ent\u00e3o tinha duas op\u00e7\u00f5es:<\/p>\r\n\r\n\r\n\r\n<ul class=\"wp-block-list\"><li>Usar <em>String.EndsWith<\/em><\/li><li>Criar o meu <em>EndsWith<\/em><\/li><\/ul>\r\n\r\n\r\n\r\n<p>Ainda estou encontrando formas de pegar o c\u00f3digo base do c# pra remover alguns recursos que n\u00e3o preciso validar, ganhando tempo de processamento.<\/p>\r\n\r\n\r\n\r\n<p>Em minha solu\u00e7\u00e3o eu achei mais f\u00e1cil iterar uma string do final pro come\u00e7o, levando em conta que se qualquer char for diferente ele retorna <em>false<\/em>,<\/p>\r\n\r\n\r\n\r\n<p>o c\u00f3digo ficou desse jeito: <\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-embed is-type-rich is-provider-embed wp-block-embed-embed\"><div class=\"wp-block-embed__wrapper\">\r\nhttps:\/\/gist.github.com\/millerscout\/879956f6a0038330992827d09fedd429\r\n<\/div><\/figure>\r\n\r\n\r\n\r\n<p>A \u00fanica coisa que faltou foi um benchmark certo?<\/p>\r\n\r\n\r\n\r\n<p>ent\u00e3o t\u00e1 ai: <\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-embed is-type-rich is-provider-embed wp-block-embed-embed\"><div class=\"wp-block-embed__wrapper\">\r\nhttps:\/\/gist.github.com\/millerscout\/52f6e56a64faa3658e7e6958c1261b29\r\n<\/div><\/figure>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/millerdantas.files.wordpress.com\/2021\/02\/image-3.png?w=920\" alt=\"\" class=\"wp-image-481\"\/><\/figure>\r\n\r\n\r\n\r\n<p>n\u00e3o apenas descartei o EndsWith de string, como percebi que minha vers\u00e3o \u00e9 mais eficiente pro problema um ganho de 69% de performance, se este problema estivesse em um cen\u00e1rio de 4M de itera\u00e7\u00f5es o ganho seria de 195.16ms para 60.44ms, Bom depende muito do cen\u00e1rio n\u00e9? mas&#8230; \u00e9 algo \u00e1 se pensar quando for otimizar, aqui nem usei o Princ\u00edpio de Pareto, s\u00f3 foi pra brincar mesmo.<\/p>\r\n\r\n\r\n\r\n<p><br>Pontos de aten\u00e7\u00e3o:<br>no meu cen\u00e1rio n\u00e3o preciso verificar se a string \u00e9 case-sensitive ou possui acentos.<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Segundo Passo<\/h2>\r\n\r\n\r\n<br>\r\n<p>Fiz uma d\u00fazia de altera\u00e7\u00f5es simples: <\/p>\r\n<!-- \/wp:post-content -->\r\n\r\n<!-- wp:list -->\r\n<ul><li>Parei de usar List para um array pequeno onde eu n\u00e3o precisava fazer nada apenas conter a lista.<\/li><li>Alterei algumas classes para structs pois as classes eram imut\u00e1veis e tamb\u00e9m n\u00e3o h\u00e1 risco de c\u00f3pia em mem\u00f3ria delas.<\/li><li>adicionei o capacity em algumas at\u00e9 o momento onde revisei<br><\/li><\/ul>\r\n<!-- \/wp:list -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>O que seria dar essa lista sem o commit n\u00e3o \u00e9 mesmo? segue ai:<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>https:\/\/github.com\/millerscout\/Kenshi-Mod-Manager\/commit\/7f9ef386bdcb902ed3a168afac8eaaa23babf4c1<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>o resultado foi bem promissor:<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:image {\"align\":\"center\",\"id\":470,\"sizeSlug\":\"large\",\"linkDestination\":\"none\"} -->\r\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/millerdantas.files.wordpress.com\/2021\/02\/image-1.png?w=556\" alt=\"\" class=\"wp-image-470\"\/><\/figure><\/div>\r\n<!-- \/wp:image -->\r\n\r\n\r\n<!-- wp:paragraph -->\r\n<p>Gen 0: 990 redu\u00e7\u00e3o de 18% comparando com 1217 anteriormente<br>Gen 1: 284 redu\u00e7\u00e3o de 31% comparando com 351 anteriormente<br>Gen 3: 28   aumento de 16% comparando com 24 anteriormente<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Primeira parte encerrada aqui.<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Voc\u00ea pode continuar lendo a <a href=\"https:\/\/millerdantas.wordpress.com\/2021\/03\/01\/sobre-otimizacao-em-aplicacoes-net-parte-2\/\">Parte 2 <\/a><\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:heading -->\r\n<h2>Conclus\u00e3o<\/h2>\r\n<!-- \/wp:heading -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Ainda h\u00e1 um longo caminho de aprendizado e t\u00e9cnicas para aprimorar minha capacidade de fine-tuning em .Net, mas acredito que o resultado mostra que n\u00e3o \u00e9 rocket science,  apenas precisamos nos policiar em coisas simples para trazer um ganho maior.<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph -->\r\n<p><\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:heading -->\r\n<h2>Cr\u00e9ditos<\/h2>\r\n<!-- \/wp:heading -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Acredito que essa minha vontade de otimiza\u00e7\u00e3o n\u00e3o seriam poss\u00edveis caso as conversas com o @<a href=\"https:\/\/www.linkedin.com\/in\/adrianocroco\/\">crocco<\/a> @<a href=\"https:\/\/www.linkedin.com\/in\/massato-takaki\/\">Massato<\/a> n\u00e3o tivessem acontecido.<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Eu tive tamb\u00e9m alguns materiais para me inspirar e aprender, bem como algumas refer\u00eancias, sendo elas:<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>o <a href=\"https:\/\/www.hanselman.com\/\">tio Scott<\/a>, <a href=\"https:\/\/twitter.com\/elemarjr\">Elemar Jr.<\/a> e <a href=\"https:\/\/twitter.com\/konradkokosa\">Konrad Kokosa<\/a><\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Estive consumindo v\u00e1rios artigos da Eximia.Co, documenta\u00e7\u00f5es da pr\u00f3pria microsoft em momentos espec\u00edficos os seguintes itens:<\/p>\r\n<!-- \/wp:paragraph -->\r\n\r\n<!-- wp:list -->\r\n<ul><li><a href=\"https:\/\/www.youtube.com\/watch?v=3r6gbZFRDHs\">High-performance code design patterns in C#. Konrad Kokosa .NET Fest 2019<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=INMH8JcU1uM\">Micro-otimiza\u00e7\u00f5es em c\u00f3digo .NET &#8211; Quando e como fazer? Como avaliar?<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=SdXIGCU8xuE\">Processando arquivos grandes (CSV) em .NET<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=rkiOdtC2KzI\">Melhorando a performance de aplica\u00e7\u00f5es .NET com &#8220;Value Types&#8221; bem implementados<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=TbvD3BwC01U\">Como funciona o &#8220;yield return&#8221;, do C#, &#8220;por baixo do cap\u00f4&#8221;?<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=6qQ7dBv63M8\">Paralelismo em .NET com Thread, ThreadPool, TPL e CUDA<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=CgWTXh66cXc\">Como o Garbage Collector (GC) afeta a performance em .NET: Valida\u00e7\u00e3o de CPF<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=s5-uC-taIi4\">Entendendo a Heap e o Garbage Collector em .NET<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=M_AFTZFSwo8\">Pequenas mudan\u00e7as no c\u00f3digo, grandes ganhos (10x) na performance em aplica\u00e7\u00f5es .NET<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=il9gl8MH17s\">C# Async\/Await\/Task Explained (Deep Dive)<\/a><\/li><\/ul>\r\n<!-- \/wp:list -->\r\n\r\n<!-- wp:heading -->\r\n<h2>Sneak Peek<\/h2>\r\n<!-- \/wp:heading -->\r\n\r\n<!-- wp:paragraph -->\r\n<p>Pr\u00f3ximo post gostaria de experimentar mais sobre sobre warmup em .Net, comecei ler algumas coisas, assim que tiver algo conclusivo trago para compartilhar \ud83d\ude42<\/p>\r\n<!-- \/wp:paragraph -->","protected":false},"excerpt":{"rendered":"<p>Bom, acredito que nunca tenha postado algo espec\u00edfico do meu trabalho. Um dos motivos para isso seria que parte das coisas que fa\u00e7o s\u00e3o muito sens\u00edveis para compartilhar. Mas esse final de semana comecei um projeto do zero para identificar e otimizar o Kenshi Mod Manager (KMM) do jogo Kenshi, porque isso vai me deixar &hellip; <a href=\"https:\/\/millerdantas.com\/blog\/2021\/02\/28\/sobre-otimizacao-em-aplicacoes-net-parte-1\/\" class=\"more-link\">Continue lendo <span class=\"screen-reader-text\">Sobre otimiza\u00e7\u00e3o em aplica\u00e7\u00f5es .Net &#8211; Parte 1<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-461","post","type-post","status-publish","format-standard","hentry","category-programacao"],"_links":{"self":[{"href":"https:\/\/millerdantas.com\/blog\/wp-json\/wp\/v2\/posts\/461","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/millerdantas.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/millerdantas.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/millerdantas.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/millerdantas.com\/blog\/wp-json\/wp\/v2\/comments?post=461"}],"version-history":[{"count":3,"href":"https:\/\/millerdantas.com\/blog\/wp-json\/wp\/v2\/posts\/461\/revisions"}],"predecessor-version":[{"id":573,"href":"https:\/\/millerdantas.com\/blog\/wp-json\/wp\/v2\/posts\/461\/revisions\/573"}],"wp:attachment":[{"href":"https:\/\/millerdantas.com\/blog\/wp-json\/wp\/v2\/media?parent=461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/millerdantas.com\/blog\/wp-json\/wp\/v2\/categories?post=461"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/millerdantas.com\/blog\/wp-json\/wp\/v2\/tags?post=461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}