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
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:
- Program.cs
- TesteRegex.cs
Nossa classe Program.cs será dessa forma:
class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<TesteRegex>();
}
}
Nossa classe TesteRegex.cs deverá ter o annotation [MemoryDiagnoser]
[MemoryDiagnoser]
public class TesteRegex
{
}
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; }
}
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);
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();
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));
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);
}
}
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);
}
}
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);
}
}
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);
}
}
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.
Após executarmos, teremos o resultado no console:
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
Top comments (0)