Design a site like this with WordPress.com
Get started

Radarc, el “Tanque” de Visual Studio

Seguro que todos tenéis en algún rincón de vuestra mente la gran escena de Triniti en Matrix: “Tanque, necesito un programa de pilotaje para un helicóptero B-212, ¡Date Prisa!”

¿Os imagináis que algo así fuese posible? Pues para sorpresa de todos, es posible gracias a Radarc y los chicos de Icinetic que lo hacen posible, por ahora en nuestro mundo del bit&byte.

Seguro que todos tenéis en algún rincón de vuestra mente la gran escena de Triniti en Matrix: “Tanque, necesito un programa de pilotaje para un helicóptero B-212, ¡Date Prisa!”

¿Os imagináis que algo así fuese posible? Pues para sorpresa de todos, es posible gracias a Radarc y los chicos de Icinetic que lo hacen posible, por ahora en nuestro mundo del bit&byte.

Radarc

RadarC es un generador de código para .NET muy sencillo y realmente útil. Plantándonos unas reglas de diseño arquitecturales sólidas con las que cimentar nuestros proyectos. Y para muestra un botón, vamos a crear una pequeña aplicación en para MVC con RadarC, pero para ello tenemos que prepararnos el sistema.

Sólo tenemos que ir a la web de Radarc y seguir sus instrucciones de instalación, son muy sencillas. Acto seguido nos descargamos la Formula MVC, hay que hacer el proceso de compra pero es totalmente gratuito ;).

¿Qué es una Formula?

Una fórmula es una arquitectura empaquetada y configurada por defecto con todo lo necesario para centrarnos en nuestro negocio y preocuparnos de hacer lo que realmente aporta valor a nuestro proyecto. En el ejemplo que vamos a ha realizar se trata de una aplicación para ASP .NET MVC y la Formula MVC nos va a permitir crearla de forma muy sencilla y ordenada como veremos.

Manos al teclado.

Una vez preparado nuestro entorno, sólo tenemos que abrir Visual Studio 2010 e irnos al menú “Nuevo Proyecto”. Veremos que ha aparecido una nueva plantilla llamada Radarc:

Radarc Template

Cuando hagamos clic en “OK” nos preguntará qué fórmula queremos usar, en nuestro caso seleccionamos “MVC Formula”:

MVC Formula

En este momento nos pedirá cierta información que necesita para poder acceder a la base de datos, namespace por defecto, y el estilo básico (hemos seleccionado el Green) necesario para crear la estructura básica de toda la solución:

Deploy MVC Formula

Una vez hagamos clic en “Finish” Radarc comenzará a crear la arquitectura básica y necesaria para un proyecto MVC:

Estructura de la solución

Ahora podemos empezar a modelar nuestro negocio de forma muy sencilla. Fijaos que directamente nos deja abierto el diseñador de modelos de nuestro Entity Data Model para comenzar a modelar nuestro negocio. De esta manera vamos a añadir cuatro Entidades a este modelo directamente:

RadarC Modeling 1

Las cuatro entidades y las propiedades que necesitamos son :

  • Product:
    • Description (string)
    • UnitPrice (decimal)
  • Order Detail:
    • Ammount (Int16)
    • Discount (Single)
  • Order:
    • OrderDate (DateTime)
    • DeliveryDate (DateTime)
    • ShippingAddress (String)
  • Customer:
    • CustomerCode (Int16)
    • CompanyName (String)
    • ContactName(String)

Así quedaría nuestro modelo:

RadarC Modeling 2

Ahora toca establecer las relaciones entre nuestras entidades, tenemos que establecer las relaciones de

  •  Un Product está en varias OrderDetails
  • Una Order tiene varias OrderDetails
  • Un Customer tiene 0 o varias Order.

RadarC Modeling 3

Guardamos los cambios y ejecutamos la aplicación, aseguraros de que el proyecto por defecto es el  proyecto MVC, ya que si no lo hacéis, se puede establecer como proyecto de inicio otro y os dirá que no existe un punto de entrada.

Cuando ejecutamos la aplicación, RadarC comenzará a generar todo el código fuente, creando las entidades, test, vistas,  servicios que exponen la lógica de negocio para ser consumida desde otros clientes, View Models y lanzará la aplicación lista para ejecutar:

Demo App

Y ya, a partir de aquí tenemos una aplicación MVC lista para poder meterle datos y todo. Es una app totalmente funcional, id probando a añadir clientes, productos y todo lo demás.

Fijaos que incluso la aplicación ya está preparada para múltiples idiomas, si abrimos el Global.asax veremos este código y en el directorio App_GlobalResources tendremos los diferentes archivos de recursos:

Localization

Resumen

Los chicos de Icinetic han hecho un excelente trabajo con Radarc, un trabajo realmente envidiable.

Me ha sido posible acceder a una beta privada que tienen lista ya para VS 2012 y Windows 8 y el funcionamiento es exactamente igual.

Juan María Laó Ramos

Segundo camino para alcanzar el Nirvana del Garbage Colector y cuál elegir

En este segundo post sobre la serie de optimizaciones en juegos en el que vamos a ver la segunda forma de optimizar el proceso de recolección de basura, evitando caídas de rendimiento en nuestros juegos.

Latencia adecuada.

El tiempo que consume el proceso de recolección de basura es directamente proporcional a lo complejo que sea nuestro heap. Si el heap está vacío, el recolector no tendrá nada que hacer.

Fijaos que hemos dicho “lo complejo que sea nuestro heap”. La complejidad del heap es una combinación del número de objetos vivos y el número de referencias a objetos que tengamos. En realidad no importa nada el tamaño en bytes que los objetos del heap tengan: lo que realmente importa es el número total de objetos (ya que el recolector debe examinar cada uno de ellos) y el número de referencias a objetos (el recolector debe seguir cada referencia para ver a qué está apuntando cada una).

Cuando medimos la complejidad del heap, un array de 100.000 enteros es poco costosa. Aunque ocupe mucha memoria, el recolector de basura sólo tiene que examinar el objeto una vez, y no tiene que mirar dentro.

100.000 arrays, cada una con un entero dentro será más costoso, ya que el recolector tiene más objetos que examinar.

Un array de 100.000 referencias a objetos es también más costoso, ya que aunque el array es sólo un objeto, el recolector tiene que recorrer todas las referencias para ver si cada objeto que contenga el array tiene que seguir vivo. Aunque el array sólo contenga nulls, el recolector los tiene que recorrer todos para asegurarse.

Aquí tenéis unos consejos para reducir la complejidad del heap:

  • Es mejor algunos objetos grandes antes que muchos objetos pequeños.
  • Mejor tener en el heap  tipos por valor que  referencias.
  • Cuantas menos referencias a objetos mejor.
  • Los arrays de tipos por valor son tus amigos!
  • Considera reemplazar referencias a objetos por manejadores enteros, es decir, en lugar de guardar una referencia la nave que creó la bala, podrías guardar el “fui creado por la nave 23” como un entero directamente.
  • Es prefeible un T[] o List<T> antes que un LinkedList<T> o un Dictionary<K,V>

Los discípulos del camino de la latencia no se preocupan de reservar memoria durante el juego. Pueden llamar a news, causar boxings, y usar delegados anónimos y métodos generadores. No les importa que pase el recolector de basura, ya que su heap es tan simple que el proceso termina muy rápido.

¿Cuál de los dos caminos elijo?

Podemos obtener un mejor rendimiento evitando las reservas de memoria, de manera que el recolector nunca pasará. Esto funciona sin importar lo complejo que sea nuestro heap.

También obtendremos un mejor rendimiento manteniendo nuestro heap simple, el recolector tardará muy rápidamente. Esto funciona aunque reservemos memoria durante el juego.

¡¡Lo que no podemos hacer es mejorar el rendimiento mezclando ambas soluciones!! Se consigue muy poco reservando memoria sólo para la mitad de memoria necesaria y tener un heap de complejidad media. Eso producirá un juego con un tamaño medio cada pocos segundos.

Si tu objetivo es evitar la recolección de basura, debes elegir sólo uno de los caminos y seguirlos hasta el final.

Reinicia tu cabeza

Los programadores nuevos en el mundo de evitar la recolección de basura piensan que pueden mejorar el rendimiento llamando a GC.Collect en momentos específicos.

Casi siempre se equivocan. Forzar la recolección de basura es una receta para confundir al recolector y dañar su rendimiento.

Pero…

En Xbox, el .NET Compact Framework realiza una recolección de basura cada vez que se ha reservado un megabyte.

Supongamos que estamos optimizando nuestro juego para evitar reservar de memoria. Después de un estudio cuidadoso con el CLR Profiler hemos conseguido reducir a 50 bytes por frame las reservas de memoria que hacemos, pero no conseguimos reducirlo más, no hay manera.

Además, digamos que nuestro juego se ejecuta a 60 frames por segundo, y que un nivel típico tarda 2 minutos en completarse. Al final del nivel tendremos reservados sólo 352k, no es suficiente para que el recolector se ejecute. En realidad, nuestro juego puede estar hasta 5 minutos sin tener que recolectar nada, el único momento en el que el jugador notará que está pasando el recolector de basura es si él mismo se dedica a recorrer el universo “perdiendo el tiempo”.

Suena razonable no? Seguramente podríamos vivir con ello.

Pero…

Estaremos reservando mucha memoria mientras se carga el nivel, y esto causará muchas recolecciones. En realidad no es un problema: no está mal que el recolector pase en este momento, ya que a la pantalla de carga no le importa el framerate.

Pero ¿qué pasa si durante la carga se reserva algo menos de un número de megabytes, por ejemplo 24,452k? Después de la última recolección en el mega 23, esta operación de carga reserva muy poco como para lanzar otra recolección, pero lo suficiente como para dejarnos sin espacio. Ahora nuestro juego sólo puede reservar 124k antes de lanzar otra recolección, así que el jugador notará esto sólo cuando lleve 42 segundos en el nivel.

La solución es llamar a GC.Collect al final de cada método de carga. Esto limpiará cualquier recolección que hiciese falta, reseteando el reloj para que tarde más en pasar el recolector.

Juan María Laó Ramos.

Artículo original.

Primer camino para alcanzar el Nirvana del Garbage Colector

En este post vamos a ver una de las técnicas usadas para evitar que el recolector de basura se ejecute en mitad de la partida de un juego, teniendo como consecuencia una pérdida de rendimiento.

Para ponernos en contexto y verlo más claro debemos saber que lo que vamos a ver es realmente importante en el mundo de los videojuegos ya que en este mundo el consumo de memoria y de recursos es algo crucial y hay que optimizarlos al máximo. En este sentido el proceso de recolección de basura es algo importantísimo ya que consume recursos del sistema y si se ejecuta en mitad del juego se puede producir una bajada de rendimiento importante.

En este primer post de la serie vamos a ver una de las formas de evitarlo.

Este es el post original de Shawn Hargreaves:

En este post vimos cómo saber si el recolector de basura de nuestra Xbox está tardando mucho. Vimos que el tiempo que tarda el recolector de basura es el resultado del producto del número de veces que se recolecta por la latencia misma de la recolección.

Esto nos hace pensar en dos formas de mejorar el rendimiento del proceso de recolección de basura. Podemos reducir el número de recolecciones, o podemos reducir la latencia del proceso de recolección. Con que consigamos reducir uno de esos valores se notará una mejora bastante notable en el rendimiento total.

En este post vamos a ver el primer caso:

Elegir una frecuencia de recolección adecuada

La frecuencia con la que se produce la recolección de basura es directamente proporcional al número de veces que reservamos memoria. Si nunca reservamos memoria, el proceso nunca se lanzará.

Para reducir el número de recolecciones, debemos reservar memoria para aquello que vamos a necesitar mientras cargamos los niveles, y evitar reservas de memoria en el tiempo de juego, evitando así que el recolector de basura entre en acción en mitad del juego.

Hay varias formas para evitar la reserva de memoria:

No reserves memoria (jah!)

Es simple, no hagas news de tipos por referencia. Está bien cuando lo hacemos con tipos por valor como Matrix, Vector3, Color y demás.

Cada vez que queramos hacer un new de un tipo por referencia, debemos usar un pool de objetos para reusar sus referencias. Los ejemplos de Particle y Audio 3D de creators.xna.com usan esta técnica, y SwampThingTom escribió sobre un pool genérico y reusable.

No uses clases que reserven memoria por sí mismas.

Cuando añadimos datos a una colección como un List<T> o un Dictionary<K,V>, se reserva memoria cuando se quieren ampliar. Podemos evitarlo usando el constructor existente en el que se indica el tamaño específico de la colección. Usando este constructor hacemos que se reserve la memoria necesaria para toda la colección haciendo que esta no tenga que ampliar ni disminuir la memoria que necesita.

Ten cuidado cuando formatees cadenas. Es difícil manipular cadenas en .NET sin causar reservas de memoria.

Evita que el CLR reserve memoria.

El CLR reserva memoria cuando ocurre el boxing. ¡Evítalos como si de una plaga se tratase! El boxing puede ocurrir por muchas razones, algunas son obvias, otras no tanto, veamos cuándo ocurre el boxing.:

  • Si asignamos un tipo por valor a una variable Object.
  • Si guardamos tipos por valor en una colección no genérica.
  • Si accedemos a tipos por valor a través de una interfaz.
  • Si usamos un enumerado como clave de un diccionario, las operaciones internas del diccionario generan boxings. Podemos evitarlo usando claves enteras (de tipo int), y hacer casting a los valores de nuestro enumerado antes de añadirlas al diccionario.

No dejes que el compilador de C# reserve memoria.

Puedes ser realmente tricky usar delegados (especialmente los que están definidos “inline”) sin hacer que el compilador reserve memoria. Esto es todo un mundo por sí solo, pero en caso de duda evita el uso de delegados o eventos

Los yield hacen que el compilador reserve siempre memoria.

Los foreach pueden reservar memoria sin cuidado. Pero ojo, esto no significa que tengamos que evitarlos. Suele ser la forma más rápida de recorrer una colección.  Aprended las reglas para usarlos de manera adecuada

Todo lo que no reserve memoria está bien.

A los discípulos del camino de la frecuencia se les permite tener estructuras de datos complejos. Pueden reservar cientos de miles de objetos mientras su juego carga, llenar el heap con una malla de objetos referenciados entre si. Siempre que no reserven nada después de que termine de cargar, el recolector de basura nunca se ejecutará, así que no hay problema ninguno en mantener en memoria objetos complejos.

Resumen

Hemos visto una forma de hacer que el recolector de basura no se ejecute mientras se está jugando al juego: evitando hacer reservas de memoria durante el juego, en vez de eso las hacemos en el proceso de carga y se mantiene todo en memoria.

En el próximo post veremos la segunda opción: Elegir la latencia adecuada.

Juan María Laó Ramos.

Post original.

La “locura” de las optimizaciones en los juegos.

¿A quien no le preocupa que su código no sea óptimo? Eso de “funcionar funciona … pero tarda mucho” no es escusa para no preocuparse por optimizar las partes optimizables. Una de las mejores formas de evitarse problemas desagradables cuando el sistema está “terminado” es interiorizar los conceptos y aplicarlos en la práctica de manera casi automática.

Para ponernos en contexto y verlo más claro debemos saber que lo que vamos a ver es realmente importante en el mundo de los videojuegos ya que en este mundo el consumo de memoria y de recursos es algo crucial y hay que optimizarlos al máximo. En este sentido el proceso de recolección de basura es algo importantísimo ya que consume recursos del sistema y si se ejecuta en mitad del juego se puede producir una bajada de rendimiento importante.

Estos conceptos no son sencillos, ya que involucran “gran cantidad” de detalles que se suelen pasar por alto.

En un afán de mejorar y compartir lo aprendido vamos a ver en detalle un par de posts de  Shawn Hargreaves que he encontrado y que publicaré en varios posts para no saturar y podamos interiorizarlos mejor.

Espero que os sirva.

Juan María Laó Ramos

CodeFluent Entities. Nunca el DDD fué tan fácil

Vamos a ver en este post es un producto que he encontrado y parece muy prometedor. CodeFluent Entities es una herramienta de modelado que nos permite generar y mantener actualizadas todas las layers y capas de nuestra aplicación. Asegurando el conjunto de buenas prácticas arquitecturales en nuestros sistemas desde su nacimiento. Esto es, han creado una herramienta para aplicar Domain Driven Development sin que apenas nos demos cuenta.

La he estado probando un tiempo y la verdad me ha dejado sorprendido, pensé en un momento que iba a ser un ORM más, pero luego descubrí el modelador de objetos de negocio, seguido de la generación de servicios RESTful, la sencillez de enlazar el modelo de negocio con las interfaces de usuario ASP.NET Web Forms, WPF y Windows Forms (están trabajando en los conectores para ASP.NET MVC, Silverlight). Continue reading “CodeFluent Entities. Nunca el DDD fué tan fácil”

¡¡¡Normalízate!!!

¿Porqué respiramos? Respirar es algo normal que hacemos sin pensar. Parpadeamos sin darnos cuenta. Pues lo mismo debería pasar cuando vas a crear una tabla en una base de datos. ¿Cual es el primer campo que se añade a toda tabla? … Si NO has pensado  una Clave Primaria auto numérica y auto incrementable, mejor será que esfuerces en no dejar de respirar. Continue reading “¡¡¡Normalízate!!!”

Si protegemos una escritura con una critical section, seguramente querreis proteger la lectura.

Es normal tener una critical section en proyectos que hacen escrituras concurrentes en variables o en una colección de variables, y si no lo haces ya tienes una pista de porqué se cae tu sistema ;).

Sin embargo, si protegemos una escritura con una critical section, seguramente también querremos proteger la lectura, ya que si no, la lectura también luchará contra la escritura a la hora de acceder a la variable de la discordia. Continue reading “Si protegemos una escritura con una critical section, seguramente querreis proteger la lectura.”

Mejora tu código, código, código (III)

Continuamos con la mini serie sobre análisis estático de código con el último post de la serie.

Aquí tenéis el enlace al primero y al segundo.

Y es que en los anteriores post no hemos visto el trato con el código heredado o legacy code (ese gran hijo de …). Y es que es un handicap muy común en nuestro día a día.

Si este código heredado no tiene contratos, vamos a obtener algunos warnings molestos del Static Checker. Sin embargo, la API de Code Contracts nos ofrece un pequeño workarround sobre esto.

Básicamente, este tipo de warnings son debidos a la falta de información – el Checker no es capaz de encontrar la información necesaria. Sin embargo, podemos dar algunos detalles.

Vamos a mirar el siguiente código:

Código con un Warning
Código con un Warning

El checker nos avisa de una posible referencia nula. Aparentemente la variable context está siendo usada sin haber sido inicializada. ¿Quién es el responsable del warning, el Checker u otra cosa?

En este caso, el aviso lo está dando ReSharper, cuyo motor de análisis identifica una posible referencia nula. ¿Pero porqué no nos lo da el Checker?, la respuesta es por la línea:

Contract.Assume(context!=null);

Y es que con esa línea le estamos diciendo al Checker que la variable context nunca va a ser nula. El Checker confía en nosotros y añade esa información a sus procesos. Resharper no ofrece soporte completo a los contratos de .NET, de ahí el aviso. Sin embargo, ReSharper soporta su propio sistema de anotaciones que podéis usar de la misma manera. Si queréis ver más detalles pasáos por aquí.

Uso óptimo del análisis estático de código.

El análisis estático es complejo, y no suele ser una ciencia exacta. Suele ocurrir que rellenamos nuestro código con información de contratos con la mejor intención, sólo para hacer que el tiempo de compilación se dispare. Para esto hay un par de soluciones que podríamos tomar para optimizar el uso de contratos y los análisis siguientes.

La primera es crear una configuración de compilación especial y habilitar las comprobaciones sólo en esa configuración. Compilamos en esa configuración de vez en cuando para obtener información, la corregimos los posibles problemas y continuamos trabajando sin el análisis estático.

La segunda es probar a usar contratos poco a poco. Aplicamos contratos de manera extensiva en el código, pero deshabilitamos los contratos a nivel de assembly. Esto lo asemos añadiendo el siguiente atributo en las propiedades del assembly:

[assembly:ContractVerification(false)]

Lo siguiente, es re-habilitar el checkeo de contratos sólo cuando estemos centrados en clases, métodos o assemblies.

Aviso

El análisis estático de código es una técnica que intenta evaluar el correcto funcionamiento de vuestro código sin ejecutarlo. Hay algunas herramientas que hacen esto. La primera es el compilador, otra es el Static Checker – un ejecutable que se integra en el proceso de compilación. En .NET, una herramienta especial aprende desde los contratos que tengáis, evalúa la información y nos muestra posibles errores y violaciones de contratos.

En el momento en el que la complejidad aumenta continuamente y el equipo de desarrollo se va quedando sin tiempo, integrar este tipo de herramientas salva algún tiempo de compilación, pero más importante, nos protege de errores feos en nuestro software.

 

Juan María Laó Ramos.

Mejora tu código, código, código (II)

Hace dos días vimos una pequeña introducción sobre las herramientas de análisis estático de código.

Hoy vamos a ver un poco lo que ofrece Visual Studio 2010 y .NET 4 junto a la herramienta Static Checker  creada por el equipo de Contratos de código. Continue reading “Mejora tu código, código, código (II)”

Mejora tu código, código, código

Pasa muchas veces, que cuando le enseñas a alguien tu código te quedas con cara de tonto. A mi me pasa mucho, y aún sabiendo que tengo herramientas disponibles para evitarlo en gran medida. Estoy hablando de las herramientas de análisis estático de código.

Cada vez son más las herramientas disponibles. Incluso la última versión del compilador de C# busca violaciones del principio de Liskov, sin embargo no lo califica como un error sino como sólo un warning.

Visual Studio 2010 viene con una nueva característica de análisis de código que podemos usar para realizar un análisis más profundo y evitar sonrojarnos cuando enseñamos nuestro código:

Opciones de Visual Studio 2010
Opciones de Visual Studio 2010

Incluso se pueden establecer y personalizar las reglas que queremos cumplir:

Warnings de VS 2010
Warnings de VS 2010

Estas herramientas nos ofrecen avisos sólo cuando se incumplen estas reglas. Incumplir una regla no significa que haya un bug, sólo indica que hay un posible bug y es mejor hecharle un vistazo sin esperar a que aparezca Murphy por ahí diciéndonos: “te lo dije, si algo puede fallar, fallará”.

Espero que os sirva, y a mi también.

Juan María Laó Ramos.