DEV Community

Cover image for .Net 5 Regex Performance
Wellington Martins
Wellington Martins

Posted on • Edited on

3 2

.Net 5 Regex Performance

Olá pessoal!

Hoje vamos fazer um teste de performance utilizando regex com .net 5.

Para esse teste criaremos um console application com a instalção de 2 pacotes nuget:

dotnet new console name TestePerformanceRegex
dotnet add package BenchmarkDotNet
dotnet add package Bogus
Enter fullscreen mode Exit fullscreen mode

BenchmarkDotNet é o pacote responsável por realizar nosso benchmark.

Bogus é o pacote responsável por gerar os dados para nossos testes.

Nosso console app será composto por duas classes:

  1. Program.cs
  2. TesteRegex.cs

image

Nossa classe Program.cs será dessa forma:

class Program
{
    static void Main(string[] args)
    {
        BenchmarkRunner.Run<TesteRegex>();
    }
}
Enter fullscreen mode Exit fullscreen mode

Nossa classe TesteRegex.cs deverá ter o annotation [MemoryDiagnoser]

[MemoryDiagnoser]
public class TesteRegex
{
}
Enter fullscreen mode Exit fullscreen mode

Agora vamos criar uma classe Usuário, onde teremos E-mail e Login:

public class Usuario
{
    public string Email { get; set; }
    public string Login{ get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Agora dentro da classe TesteRegex, vamos fazer o seguinte:

private static readonly List<Usuario> FakeUsuarios = new Faker<Usuario>()
    .UseSeed(420)
    .RuleFor(r => r.Email, faker => faker.Person.Email)
    .RuleFor(r => r.Login, faker => faker.Person.UserName)
    .Generate(10);
Enter fullscreen mode Exit fullscreen mode

Estamos criando 10 usuários, utilizando o Bogus.

Agora vamos criar uma lista com e-mails validos e e-mails inválidos:

private static readonly List<string> emails = 
    FakeUsuarios.Select(x => x.Email)
        .Concat(FakeUsuarios.Select(x => x.Login)).ToList();
Enter fullscreen mode Exit fullscreen mode

Com isso teremos um total de 20 itens na lista e-mails.

Agora faremos os regex abaixo:

private static readonly Regex RegexStatico =
    new(@"^[^@\s]+@[^@\s]+\.[^@\s]+$", RegexOptions.IgnoreCase);

private static readonly Regex RegexStaticoCompilado =
    new(@"^[^@\s]+@[^@\s]+\.[^@\s]+$", RegexOptions.IgnoreCase | RegexOptions.Compiled,
        TimeSpan.FromMilliseconds(250));
Enter fullscreen mode Exit fullscreen mode

Com isso temos o primeiro Regex sendo estático e o segundo estático e compilado, também foi informado um timeout de 250 milissegundos. Esse timeout deve ser configurado conforme a necessidade da sua aplicação.

Agora iremos criar os métodos responsáveis pelos testes.

Importante ressaltar que todos os métodos tem a anotação de [Benchmark].

[Benchmark]
public void IsMatchInternal()
{
    var regex = new Regex(@"^[^@\s]+@[^@\s]+\.[^@\s]+$", RegexOptions.IgnoreCase);

    for (var i = 0; i < emails.Count; i++)
    {
        var email = emails[i];
        var isMatch = regex.IsMatch(email);
    }
}
Enter fullscreen mode Exit fullscreen mode

No método acima, estamos declarando o regex internamente e fazendo a validação de todos os e-mails da nossa lista.

[Benchmark]
public void IsMatchInternalCompiled()
{
    var regex = new Regex(@"^[^@\s]+@[^@\s]+\.[^@\s]+$", RegexOptions.IgnoreCase | 
                    RegexOptions.Compiled);

    for (var i = 0; i < emails.Count; i++)
    {
        var email = emails[i];
        var isMatch = regex.IsMatch(email);
    }
}
Enter fullscreen mode Exit fullscreen mode

Já no método acima, estamos declarando o regex internamente e a flag de compilado.

[Benchmark]
public void IsMatchStatic()
{
    for (var i = 0; i < emails.Count; i++)
    {
        var email = emails[i];
        var isMatch = RegexStatico.IsMatch(email);
    }
}
Enter fullscreen mode Exit fullscreen mode

Nesse método estamos utilizando a declaração estática RegexStatico ao invés de declararmos internamente no método.

[Benchmark]
public void IsMatchStaticCompiled()
{
    for (var i = 0; i < emails.Count; i++)
    {
        var email = emails[i];
        var isMatch = RegexStaticoCompilado.IsMatch(email);
    }
}
Enter fullscreen mode Exit fullscreen mode

Finalmente o último método, temos a utilização da declaração estática RegexStaticoCompilado com a flag de compilado.

Agora vamos executar nossa aplicação, é importante ressaltar que devemos executá-la em modo Release.
image
Após executarmos, teremos o resultado no console:
image
Podemos ver que o método mais performático de todos foi quando utilizamos a declaração estática com a flag de compilado, onde levou 4 microssegundos.

Já o nosso pior cenário foi quando utilizamos a declaração interna e copilada, onde levou 1.9 milissegundos e foi alocado 18KB de memória.

Com alguns ajustes simples podemos ter um ganho expressivo de performance quando estamos trabalhando com regex.

Abaixo link do código no github:
https://github.com/ouell/regex-performance

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (1)

Collapse
 
insight_it_891bf8cd689700 profile image
Insight IT

Nice blog and informative content,
We are providing Best Dot NET Training in Hyderabad,
Thanks for sharing with us,
DOT NET Training in Hyderabad
DOT NET Online Training in Hyderabad

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay