Nov 7, 2022

Um pequeno puzzle sobre o C# 10 - Solução (Parte II)

Read this post in English

Lire cet post en Français.

Em meu último post apresentei um desafio para modificar a saída do programa abaixo de forma que o mesmo apresentasse apenas as linhas contendo números pares.

As únicas restrições  eram que você:

  1. Não poderia modificar a implementação do método Foo, a não ser, o tipo do parâmetro msg.
  2. Não poderia modificar a implementação do laço for.
  3. Não poderia utilizar IL post-processing
  4. Quaisquer outras modificações seriam aceitas.

Eu também mencionei que ao observar atentamente o programa serial possível encontrar pistas da solução que eu estava pensando na forma de código que não era essencial para que o programa apresentado compilasse/funcionasse; obviamente eu vou discutir estes pontos, mas antes, gostaria de apresentar a funcionalidade base (introduzida no C# 6) a qual será usada na minha solução: Interpolated strings.

Interpolated strings tem como objetivo simplificar o código de formatação de strings sendo formadas por strings literais prefixadas com o caractere $ e que contem expressões C# envolvidas em chaves ({ ... }) as quais são substituídas pelos seus respectivos valores pelo compilador C#. Por exemplo, no programa abaixo:

O compilador C# substituirá {i} pelo valor da variável i e {args[i]} pelo valor do elemento armazenado no índice i do array args.

Até a versão 9 do C#, o código acima seria convertido pelo compilador para algo como:

Ou, em outras palavras, o compilador substituiria a interpolated string com uma ou mais chamadas ao método String.Format()(como observado na linha #10 acima). Ainda que este  código não seja essencialmente incorreto (afinal de contas este seria mais ou menos o código usado na ausência desta funcionalidade), com a crescente busca na melhoria de performance no últimos anos, os desenvolvedores .NET notaram que existia margem para melhorias nesta área; e realmente, se observarmos atentamente notaremos claramente alguns padrões, não ideais, com relação à utilização de memória:

  1. Na linha #5, há uma alocação de um array.
  2. Existem 3 operações de boxing (lines #6, 7 & 8)(ou seja, alocações no heap)
  3. O método String.Format() muito provavelmente executará o método Int32.ToString() o qual acabará introduzindo alocações de strings no heap.

Note que, em programas pequenos (ou talvez mesmo em médios ?) estas alocações  seriam praticamente desprezíveis; contudo em aplicações maiores ou aplicações que fazem uso constante de tais operações estas alocações podem introduzir problemas de performance devido ao mecanismo de Garbage Collection (ou GC) necessitar executar constantemente.

Com o objetivo de melhorar a performance de tais aplicativos, C# 10 introduziu o conceito que abordaremos no próximo post e que será usado na solução do problema proposto: string interpolation handlers.

Have fun!

Adriano

No comments: