O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

.NET Memoria y Rendimiento

45 visualizações

Publicada em

Charla en la NetCoreConf Barcelona 2020, donde hablé de memoria y rendimiento en .NET.
Empecé por el GC, luego novedades de C# 7.2 respecto a type values y finalmente Span<T>

Publicada em: Tecnologia
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

.NET Memoria y Rendimiento

  1. 1. 2020 Netcoreconf Memoria, .NET y rendimiento Eduard Tomàs Random Key Presser & Beer Crafter @eiximenis
  2. 2. #netcoreconf Sponsors
  3. 3. #netcoreconf ¿Quien soy yo? • Principal Tech Lead @ PlainConcepts BCN • Padre orgulloso • Bebedor de cerveza • Picateclas a mucha honra • Microsoft MVP desde 2012
  4. 4. #netcoreconf Memoria, .NET y Rendimiento • La (gran) mayoría de cosas que voy a contar no las vas a necesitar nunca… • … Hasta que un día quizá las necesites.
  5. 5. #netcoreconf • Hazlo o no lo hagas…. • … Pero si lo haces… • ¡MÍDELO!
  6. 6. #netcoreconf
  7. 7. #netcoreconf Código sin reservas de memoria (no alloc code)
  8. 8. #netcoreconf ¿Por qué? ¿Es costoso reservar memoria manejada? NO!!!!
  9. 9. #netcoreconf ¿Por qué? Lo costoso es liberarla (El GC)
  10. 10. #netcoreconf ¿Por qué? • Reservar más memoria implica más GC • GC implica pausas • Código con menos GC… • Será más fluído (no necesariamente más rápido) • Funcionará major en entornos restringidos (batería, cpu,…)
  11. 11. #netcoreconf ¿Como funciona el GC? • Objetos se guardan en el managed heap (memoria manejada) • Reservar un objeto es rapidísimo • Garbage Collector libera objetos no usados del managed heap
  12. 12. #netcoreconf GC – Generaciones • GC no libera todo el heap de golpe. Lo divide en Generaciones (3): Gen 0 Gen 1 Gen 2 Objetos de corta vida (Variables locales) Objetos de vida media Objetos de larga duración (P. ej. Singletons) • Los objetos de Gen 0 que están vivos cuando se ejecuta el GC se mueven a Gen 1 • Los objetos de Gen 1 que están vivos cuando se ejecuta el GC se mueven a Gen 2 • Los objetos de Gen 2 que están vivos cuando se ejecuta el GC se quedan en Gen 2
  13. 13. #netcoreconf GC - LOH • Heap especial para objetos “grandes” > 85Kb • No compactado (puede provocar OutOfMemoryException) • Solo se liberan en una “liberación completa” del GC
  14. 14. #netcoreconf GC - ¿Cuando se ejecucta? • Bueeeenoooo….. • Cuando no se puede reservar memoria • Cuando se ha reservado X memoria desde la última ejecución • Forzado (métodos de System.GC o por Profiler API) • Aplicación se mueve al background • No está garantizado cuando se ejecuta el GC
  15. 15. #netcoreconf GC – Tips / Tricks • GC pausa la aplicación mientras se está ejecutando… • … excepto en nuevas versiones de .NET (Background GC) • IDisposable ayuda al GC (limpia referencias) • Finalizers => Objeto va a la “finalizer queue” y suma una generación • Usar WeakReference • Una referencia que no es tenida en cuenta por el GC
  16. 16. #netcoreconf Back to Basics: Value Type vs Reference Type Reference Type class Almacenados en el heap La variable es una referencia al objeto en el heap Semántica de referencia (asignación y paso implica copiar la referencia, no el valor) Value Type struct Almacenados en la pila La variable es el propio valor Semántica de valor (asignación y paso implica copiar el valor)
  17. 17. #netcoreconf Reservas de memoria “ocultas” • params reserva un array con los parámetros • closures • LINQ reserva Enumerable • Iteradores • async/await • …
  18. 18. #netcoreconf Demo: Hidden Allocs
  19. 19. #netcoreconf Value Types o Reference Types Value Types: Barato reservarlos, caro pasarlos Reference Types: Caro reservarlos, barato pasarlos ¿Podemos tener objetos que sea barato reservarlos Y barato pasarlos?
  20. 20. #netcoreconf Value Types o Reference Types Con C# 7.2 SÍ Podemos tener Value Types con semántica de referencias
  21. 21. #netcoreconf Value Types con semántica de referencia • Permite usar value objects como si fuesen reference objects • Paso por referencia siempre  • Tiene limitaciones (para evitar refs valores inexistentes) • ref return • Devuelve un value object por referencia. Modificar la referencia es modificar el value object original • ref local • Una variable que es una referencia a un tipo por valor • ref local para guardar el resultado de ref return • Ojo con var! Usar ref var!
  22. 22. #netcoreconf Value Types con semántica de referencia • ref readonly return • Permite devolver un value type por referencia • No permite al receptor, modificar el objeto • El compilador hace copias automáticamente para asegurar readonly • Parámetros in • Permite pasar un value type por referencia (al igual que ref y out) • El método no puede modificar el parámetro • readonly struct • ValueType que el compilador sabe (y obliga a) que es inmutable • Elimina las copias defensivas del compilador para params in / ref readonly
  23. 23. #netcoreconf Parámetros in • Se aplican a la firma del método • Con structs no readonly puede implicar copias defensivas • Se puede aplicar a la llamada. Si NO se aplica se le da permiso al compilador para efectuar copias en algunos casos • Sobrecarga con paso por valor (preferida) • Existe una conversión implícita del tipo del argumento al tipo del parámetro • …
  24. 24. #netcoreconf Value Types con semántica de referencia Todos esos añadidos son puros del lenguaje C# El CLR no se ha modificado
  25. 25. #netcoreconf Consejos • Evita usar in para structs mutables • Copias defensivas pueden perjudicar el rendimiento • Usa ref readonly return siempre que puedas • Usa in para “readonly structs” de tamaño superior a IntPtr.Size
  26. 26. #netcoreconf Demo: ref return & ref local
  27. 27. #netcoreconf Demo: in & readonly struct
  28. 28. #netcoreconf ref struct • Una ref struct es una estructura que solo puede ser almacenada en la pila, nunca en el heap • NO puede ser miembro de un objeto que esté en el heap. • NO puede ser miembro de una clase porque estas siempre están en el heap • NO puede ser miembro de una estructura porque estas están en el heap si a su vez son miembros de un objeto que esté en el heap (p. ej. una clase) • Solo se pueden usar como parámetros, valores retorno o variables locales
  29. 29. #netcoreconf Gestión “unificada” de memoria Span<T>
  30. 30. #netcoreconf Span<T> • Unifica el trabajo con “bloques contíguos de memoria” • Arrays, strings, stackallock, memoria no manejada,… • Ofrece una API similar a la de un Array • Segura a nivel de tipos (elementos de tipo T) • Soporta slicing • Crear un nuevo Span<T>, subsección de uno existente… • … sin reservar nueva memoria!
  31. 31. #netcoreconf Span<T> - Dos implementaciones • Implementación portable • No require soporte adicional • Paquete NuGet (netstandard 1.1) • Netfx 4.5 • Sin ser lento… no es tan rápido como un array
  32. 32. #netcoreconf Span<T> - Dos implementaciones • Implementación “rápida” • Requiere soporte del framework • .NET Core 2.1 o superior • Optimizaciones JIT propias • Rendimiento equiparable al de un array
  33. 33. #netcoreconf Demo: Span<T>
  34. 34. #netcoreconf stackalloc • Fuerza el almacenamiento en la pila para aquellos elementos que, habitualmente, se almacenarían en el heap • Disminuye la presión sobre el GC • Liberación determinista (al final del método)
  35. 35. #netcoreconf Demo: Stackalloc
  36. 36. #netcoreconf Gestión “unificada” de memoria Memory<T>
  37. 37. #netcoreconf Memory<T> • Span<T> es “ref struct” => Solo se almacena en la pila • Variables en métodos async son realmente campos estáticos de una clase generada por el compilador (incompatible con ref struct) async Task DoSomethingAsync(Span<byte> buffer) { buffer[0] = 0; await Something(); buffer[0] = 1; } async Task DoSomethingAsync(Memory<byte> buffer) { buffer.Span[0] = 0; await Something(); buffer.Span[0] = 1; }
  38. 38. #netcoreconf Conclusiones • Todo eso son micro-optimizaciones • Úsalas solo si las necesitas. Probablemente puedas optimizar muchas cosas antes. • Mide siempre los resultados • ¡Recuerda que las mediciones dependen de TU máquina y de TU framework exacto! • No des nada por supuesto.
  39. 39. #netcoreconf Sponsors
  40. 40. Más información: info@netcoreconf.com @Netcoreconf Visítanos en: netcoreconf.com

×