2012-05-05 18 views
5

Introducción
Tengo (en su mayoría) una sola página application construida con BackboneJS y un servidor Rails.¿Cómo mejorar el rendimiento de la aplicación de una sola página?

Como la mayor parte de la interacción ocurre en una página de la aplicación web, cuando el usuario visita la página por primera vez, básicamente tengo que extraer gran cantidad de información de la base de datos en una consulta grande profundamente unida.

Esto me está provocando tiempos de carga bastante extremos en esta página.

load times

NewRelic me parece estar diciendo que la mayoría de mis problemas se deben a que de 457 llamadas a métodos rápidos individuales.

fast methid calls

Ahora he hecho toda la carga ansiosa que puedo hacer (he comprobado con el Bullet gem) y todavía tengo un problema.

Estas llamadas a métodos son más comunes en mi serializador Rabl que utilizo para serializar un grupo de JSON para incrustar en la página para inicializar Backbone. No necesita comprender todo esto, pero basta con decir que podría agregar hasta 457 llamadas a métodos.

object @search 
attributes :id, :name, :subscription_limit 

# NOTE: Include a list of the members of this search. 
child :searchers => :searchers do 
    attributes :id, :name, :gravatar_icon 
end 

# Each search has many concepts (there could be over 100 of them). 
child :concepts do |search| 
    attributes :id, :title, :search_id, :created_at 

    # The person who suggested each concept. 
    child :suggester => :suggester do 
    attributes :id, :name, :gravatar_icon 
    end 

    # Each concept has many suggestions (approx. 4 each). 
    node :suggestions do |concept| 
    # Here I'm scoping suggestions to only ones which meet certain conditions. 
    partial "suggestions/show", object: concept.active_suggestions 
    end 

    # Add a boolean flag to tell if the concept is a favourite or not. 
    node :favourite_id do |concept| 
    # Another method call which occurs for each concept. 
    concept.favourite_id_for(current_user) 
    end 
end 

# Each search has subscriptions to certain services (approx. 4). 
child :service_subscriptions do 
    # This contains a few attributes and 2 fairly innocuous method calls. 
    extends "service_subscriptions/show" 
end 

Parece que tengo que hacer algo al respecto, pero no estoy seguro de qué enfoque tomar. Aquí está una lista de posibles ideas que tengo:

ideas de mejora del rendimiento

Dumb-Abajo de la interfaz
Tal vez pueda llegar a la forma de presentar la información al usuario que no requieren el actual datos para estar presente. Aunque no veo por qué debería hacerlo, otras aplicaciones de una sola página, como Trello, tienen interfaces increíblemente complicadas.

Concepto Paginación
Si pagino conceptos, se reducirá la cantidad de datos que se extraen de la base de datos cada vez. Sin embargo, el producto tendría una interfaz de usuario inferior.

Almacenamiento en caché
Por el momento, actualizar la página simplemente extrae toda la búsqueda de la base de datos de nuevo. Tal vez pueda almacenar en caché partes de la aplicación para reducir los hits de DB. Sin embargo, esto parece desordenado porque no muchos de los datos con los que trato son estáticos.

múltiples peticiones
Técnicamente es mala para servir a la página sin incorporar el JSON en la página, pero tal vez el usuario se sentirá como si las cosas están sucediendo más rápido si me carga la página despoblado y luego recuperar los datos.

Índices
Debo asegurarme de tener índices en todas mis claves foráneas. También debería tratar de pensar en lugares en los que ayudaría tener índices (como los favoritos?) Y agregarlos.

Mover llamadas a métodos en DB
Quizás pueda almacenar en la base de datos algunos de los resultados de la iteración que hago en mi capa de vista y simplemente extraerlos en lugar de calcularlos.O podría sincronizar cosas en escritura en lugar de en lectura.

Pregunta
¿Alguien tiene alguna sugerencia en cuanto a lo que debería gastar mi tiempo en?

Respuesta

1

Esta es una pregunta difícil de responder sin poder ver la interfaz de usuario real, pero me centraría en cargar exactamente la cantidad de datos necesaria para mostrar la interfaz inicial. Por ejemplo, si el usuario tiene que profundizar para ver algunos de los datos que está presentando, puede cargar esos datos a pedido, en lugar de cargarlos como parte de la carga útil inicial. Menciona que una búsqueda puede tener hasta 100 "conceptos", ¿quizás no es necesario buscar todos esos conceptos inicialmente?

En pocas palabras, no parece que su problema esté realmente en el lado del cliente - parece que el código del lado del servidor está ralentizando las cosas, por lo que exploraría lo que puede hacer para obtener menos datos, o diferir las consultas complejas hasta que sean definitivamente necesarias.

1

Recomiendo separar su código base JS en módulos que se cargan dinámicamente utilizando un cargador de activos como RequireJS. De esta forma, no tendrás tantos XHR disparando en el momento de la carga.

Cuando se necesita un módulo específico, puede cargarse e inicializarse en un momento apropiado en lugar de cada carga de página.

Si complica un poco su código, cada módulo debería poder iniciarse y detenerse. Por lo tanto, si tiene algún código polling o código complejo ejecutándose, puede detener el módulo para aumentar el rendimiento y disminuir la carga de la red.

+0

Aunque estoy de acuerdo en que la optimización de la entrega de activos es un paso importante para aumentar el rendimiento, no creo que sea el problema principal que tengo aquí. Si bien hay una luz de JS en la aplicación, está comprimida, minimizada y llega a ~ 100kb. También se debe almacenar en el caché en el lado del cliente, por lo que el costo de la carga se reduce al mínimo para los visitantes que repiten. –

Cuestiones relacionadas