c# - route - Rendimiento de generación de URL ASP.NET MVC
route() in mvc (4)
Un pequeño punto de referencia con ASP.NET MVC. Código de vista:
public string Bechmark(Func<string> url)
{
var s = new Stopwatch();
var n = 1000;
s.Reset();
s.Start();
for (int i = 0; i < n; i++)
{
var u = url();
}
s.Stop();
return s.ElapsedMilliseconds + " ms, " + ((s.ElapsedMilliseconds) / (float)n) + " ms per link<br/>";
}
Ver código:
<%= Bechmark(() => Url.Action("Login", "Account")) %>
<%= Bechmark(() => Url.Action("Login", "Account", new {username="bla", password="bla2", returnurl="blabla32", rememberme=false} )) %>
<%= Bechmark(() => Html.BuildUrlFromExpression<AccountController>(a=>a.ChangePassword("bla", "bla", "ya")) ) %>
Al ejecutar esto en un portátil Core2 típico en la nueva plantilla de proyecto predeterminada con ASP.NET MVC Beta, se obtienen los siguientes resultados:
38 ms, 0,038 ms por enlace
120 ms, 0,12 ms por enlace
54 ms, 0,054 ms por enlace
Al ejecutar el mismo benchmark en un proyecto de producción con aproximadamente 10 controladores que tienen todos los 100 métodos y 30 entradas de la tabla de enrutamiento, el rendimiento se degrada mucho para el método basado en expresiones:
31 ms, 0,031 ms por enlace
112 ms, 0,112 ms por enlace
450 ms, 0,45 ms por enlace
Usamos bastante este método (mantenibilidad) y hacemos algunos benchmarking de rendimiento, esto degrada el rendimiento del sitio en gran medida: las páginas contienen rápidamente alrededor de 30 o más de esos enlaces, lo que significa 10ms de sobrecarga adicional en una sola página. Incluso 0.112ms por una URL son alrededor de 4 ms de CPU pura.
Cabe señalar que el rendimiento de las tres llamadas de generación de URL entre MVC Preview 3 y Beta (lanzado ayer) se mejoró en un factor de 5.
Stack Overflow supuestamente funciona con el mismo framework, ¿cómo han abordado ustedes este problema de escalado? Caché liberal de la página principal (muchos enlaces) y controles pretratados?
¿Algún otro sitio web de producción en ASP.NET MVC con problemas de rendimiento o algunos buenos consejos?
Los enlaces de almacenamiento en caché probablemente sean una buena sugerencia para el equipo, ya que no cambiarán durante la vida del proceso (para la mayoría de las aplicaciones de todos modos).
¿Cómo se pueden guardar en caché los enlaces ?, no se puede hacer eso, que yo sepa, porque se necesita almacenar en caché el método que se ejecuta, lo que sucede una vez que se resuelve la ruta, que es la parte lenta.
Hice esta pregunta en los foros de MS, que obtuvo una respuesta de un desarrollador de MS MVC.
La respuesta
Desde MVC Preview 2 hasta el MVC Beta lanzado recientemente desde ayer, ha habido muchos cambios en Routing. Algunos de esos cambios incluyen mejoras de rendimiento. Aquí hay algunos trucos para hacer que la generación de URL sea más eficiente en su aplicación:
Use rutas con nombre. Las rutas con nombre son una característica opcional del enrutamiento. Los nombres solo se aplican a la generación de URL: nunca se utilizan para hacer coincidir las URL entrantes. Cuando especifica un nombre al generar una URL, solo intentaremos hacer coincidir esa ruta. Esto significa que incluso si la ruta especificada que especificó es la ruta número 100 en la tabla de rutas, saltaremos directamente a ella e intentaremos unirla.
Coloque sus rutas más comunes al comienzo de la tabla de rutas. Esto mejorará el rendimiento tanto de la generación de URL como del procesamiento de las URL entrantes. El enrutamiento funciona según la regla de que gana el primer partido. Si la primera coincidencia es la ruta número 100 en su tabla de rutas, eso significa que debe probar otras 99 rutas y ninguna de ellas coincide.
No use la generación de URL. A algunas personas les gusta, otras personas no. Es un poco difícil de dominar. Es bueno usarlo si sus URL son muy dinámicas, pero puede ser un poco complicado cuando tiene muy pocas URL para empezar y quizás no le importe exactamente cómo son.
Mi opción favorita es # 1, ya que es muy fácil de usar y también hace que la generación de URL sea más determinista desde la perspectiva del desarrollador de la aplicación (¡ese eres tú!).
Los enlaces de almacenamiento en caché probablemente sean una buena sugerencia para el equipo, ya que no cambiarán durante la vida del proceso (para la mayoría de las aplicaciones de todos modos).
Hasta que comiences a definir tus rutas en una forma configurable (como web.config o en una base de datos), entonces tendrás que reducir un poco la escala.
Sospecho que una gran parte de la demora en el ejemplo del medio es el tipo anónimo que se convierte automáticamente a un diccionario. El almacenamiento en caché de la URL no ayudaría aquí b / c aún tendría que reflejar ese tipo.
Mientras tanto, puede crear sus propios métodos de ayuda para algunos de esos enlaces basados en diccionarios que toman la entrada exacta que necesita. Entonces puede manejar el almacenamiento en caché usted mismo.
Ok, dos métricas adicionales en el proyecto de plantilla en blanco:
<%= Bechmark(() => Url.Action("Login", "Account", new Dictionary<string, object> {{"username", "bla"}, {"password", "bla2"}, {"returnurl", "blabla32"}, {"rememberme", "false"}})) %>
<%= Bechmark(() => Url.Action("Login", "Account", new RouteValueDictionary(new Dictionary<string, object> {{"username", "bla"}, {"password", "bla2"}, {"returnurl", "blabla32"}, {"rememberme", "false"}}))) %>
Resultados:
71 ms, 0,071 ms por enlace
35 ms, 0,035 ms por enlace
Mucho mejor rendimiento con código más desagradable. Demasiado.