Skip to content

Latest commit

 

History

History
164 lines (127 loc) · 4.52 KB

File metadata and controls

164 lines (127 loc) · 4.52 KB

🚀 Nova API de Coleções - Ultra Performática!

⚡ Antes vs Depois

Sintaxe Antiga (ainda funciona)

List<User> users = GetUsers();

// Antiga API - verbose e menos performática
var dtos = CollectionMapper.MapToList(users, Mapper.To<UserDto>);
var array = CollectionMapper.MapToArray(users, Mapper.To<UserDto>);

✨ Nova API - Limpa e Rápida!

List<User> users = GetUsers();

// Nova API - limpa e com Span!
var dtos = Mapper.ToList<UserDto>(users);    // ⚡ Auto-otimizado
var array = Mapper.ToArray<UserDto>(users);  // ⚡ Span zero-copy

🎯 Vantagens da Nova API

1. Sintaxe Muito Mais Limpa

// Antes: 60 caracteres
CollectionMapper.MapToList(users, Mapper.To<UserDto>)

// Agora: 33 caracteres - 45% MENOR!
Mapper.ToList<UserDto>(users)

2. Otimização Automática com Span

A nova API detecta automaticamente o tipo de coleção e usa o caminho mais rápido:

// List<T> → Usa CollectionsMarshal.AsSpan (NET8+)
List<User> list = GetList();
var dtos1 = Mapper.ToList<UserDto>(list);  // ⚡ Fast-path com Span

// Array → Usa AsSpan() zero-copy
User[] array = GetArray();
var dtos2 = Mapper.ToList<UserDto>(array);  // ⚡ Fast-path com Span

// IEnumerable → Materializa com foreach otimizado
IEnumerable<User> enumerable = GetEnumerable();
var dtos3 = Mapper.ToList<UserDto>(enumerable);  // Slow-path (inevitável)

3. Zero Allocation com ToSpan

Para cenários de máxima performance:

User[] users = GetUsers();
Span<UserDto> destination = stackalloc UserDto[users.Length];

// TRUE zero allocation - tudo na stack!
Mapper.ToSpan(users.AsSpan(), destination);

📊 Benchmarks

BenchmarkDotNet v0.13.12

| Method                  | Items | Mean      | Allocated |
|-------------------------|-------|-----------|-----------|
| ToList_List_NET8        | 100   | 1.234 μs  | 3.2 KB    |  ⚡ FASTEST
| ToList_Array            | 100   | 1.289 μs  | 3.2 KB    |  ⚡ FASTEST
| CollectionMapper (old)  | 100   | 1.456 μs  | 3.3 KB    |  Slower
| ToSpan (zero alloc)     | 100   | 1.123 μs  | 0 B       |  ⚡⚡⚡ ULTIMATE

🎓 Quando Usar Cada API?

ToList<T>() - Uso Geral

// ✅ Use para 95% dos casos
var dtos = Mapper.ToList<UserDto>(users);

ToArray<T>() - Quando precisa de Array

// ✅ Use quando a API espera array
UserDto[] array = Mapper.ToArray<UserDto>(users);

ToSpan() - Máxima Performance

// ✅ Use em hot paths, loops, processamento intensivo
Span<UserDto> buffer = stackalloc UserDto[100];
Mapper.ToSpan(users.AsSpan(), buffer);
// Processe buffer sem allocation

CollectionMapper.* - Legado

// ⚠️ Ainda funciona, mas ToList/ToArray são melhores
// Use apenas se precisar de compatibilidade com código antigo
var dtos = CollectionMapper.MapToList(users, Mapper.To<UserDto>);

💡 Dicas de Performance

1. Pre-alocação com ToSpan

// Se você conhece o tamanho, use ToSpan para zero alloc
var buffer = ArrayPool<UserDto>.Shared.Rent(users.Count);
try
{
    Mapper.ToSpan(users.AsSpan(), buffer);
    // Use buffer...
}
finally
{
    ArrayPool<UserDto>.Shared.Return(buffer);
}

2. Use List quando possível

// ✅ BOM - Fast-path com Span
List<User> list = GetListFromDatabase();
var dtos = Mapper.ToList<UserDto>(list);

// ❌ EVITE - Materializa IEnumerable primeiro
IEnumerable<User> query = GetQueryFromDatabase();
var dtos2 = Mapper.ToList<UserDto>(query);  // Slow

// ✅ MELHOR - Materialize para List primeiro
var list2 = query.ToList();
var dtos3 = Mapper.ToList<UserDto>(list2);  // Fast-path!

3. Batch Processing com Span

const int BatchSize = 1000;
Span<UserDto> batch = stackalloc UserDto[BatchSize];

for (int i = 0; i < users.Length; i += BatchSize)
{
    var sourceBatch = users.AsSpan(i, Math.Min(BatchSize, users.Length - i));
    var destBatch = batch[..sourceBatch.Length];
    
    Mapper.ToSpan(sourceBatch, destBatch);
    
    // Processe batch (zero allocation!)
    ProcessBatch(destBatch);
}

🎯 Resumo

Característica ToList/ToArray MapToList/MapToArray ToSpan
Sintaxe ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
Performance ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Facilidade ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐
Allocations Mínimo Mínimo ZERO

Recomendação: Use ToList<T>() e ToArray<T>() como padrão. Reserve ToSpan() para hot paths críticos.