5

Введение
У меня есть (в основном) одностраничный application, построенный с BackboneJS и бэкэндом Rails.Как повысить производительность одностраничного приложения?

Поскольку большая часть взаимодействия происходит на одной странице webapp, когда пользователь впервые посещает страницу, я в основном должен вытащить тонну информации из базы данных в один большой сложный запрос.

Это вызывает у меня некоторые экстремальные времена нагрузки на этой странице.

load times

NewRelic, кажется, говорил мне, что большинство моих проблем из-за 457 индивидуальных быстрых вызовов метода.

fast methid calls

Теперь я сделал все жадную загрузку я могу сделать (я проверил с Bullet gem), и я до сих пор есть проблемы.

Эти вызовы методов, скорее всего, возникают в моем сериализаторе Rabl, который я использую для сериализации связки JSON для встраивания в страницу для инициализации Backbone. Вам не нужно все это понимать, но достаточно сказать, что может добавить до 457 вызовов методов.

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 

Таким образом, мне кажется, что мне нужно что-то сделать, но я не уверен, какой подход принять. Вот список потенциальных идей у ​​меня есть:

Улучшение производительности Идеи

Тупой вниз Интерфейс
Может быть, я могу придумать способы представления информации пользователю, которые не требуют фактического данные должны присутствовать. Я не понимаю, зачем мне это нужно, но другие одностраничные приложения, такие как Trello, имеют невероятно сложные интерфейсы.

Концепция разбиения на страницы
Если я разбиваю концепции, он будет каждый раз восстанавливать объем данных, извлекаемых из базы данных. Хотя бы у продукта был бы неполный пользовательский интерфейс.

Кэширование
На данный момент обновление страницы просто извлекает весь поиск из БД. Возможно, я могу кэшировать части приложения, чтобы уменьшить количество обращений к БД. Это кажется беспорядочным, хотя из-за того, что многие данные, с которыми я имею дело, являются статическими.

Множественные запросы
Это технически плохо обслуживать страницы без вложения JSON в страницу, но, возможно, пользователь будет чувствовать, что все происходит быстрее, если я загрузить страницу безлюдный, а затем извлечь данные.

Индексы
Я должен убедиться, что у меня есть индексы по всем моим внешним ключам. Я также должен попытаться подумать о местах, где это поможет иметь индексы (например, избранное?) И добавлять их.

Метод переадресации вызовов в DB
Возможно, я могу кэшировать некоторые из результатов итерации, которые я делаю в своем слое представления, в БД и просто вытаскивать их вместо их вычисления.Или я мог бы синхронизировать вещи, а не читать.

Вопрос
Кто-нибудь есть какие-либо предложения относительно того, что я должен тратить свое время на?

ответ

1

Ответ на этот вопрос является трудным, не имея возможности увидеть фактический пользовательский интерфейс, но я бы сосредоточил внимание на загрузке ровно столько же данных, сколько требуется для отображения начального интерфейса. Например, если пользователь должен развернуться, чтобы просмотреть некоторые данные, которые вы представляете, вы можете загрузить эти данные по требованию, а не загружать их как часть начальной полезной нагрузки. Вы отмечаете, что поиск может иметь до 100 «понятий», может быть, вам не нужно изначально извлекать все эти концепции?

В нижней строке это звучит не так, как будто ваша проблема действительно на стороне клиента - похоже, что ваш серверный код замедляет работу, поэтому я исследую, что вы можете сделать, чтобы получить меньше данных, или отложить сложные запросы, пока они определенно не потребуются.

1

Я бы рекомендовал разделить вашу JS-базу на модули, которые динамически загружаются с помощью загрузчика ресурсов, например RequireJS. Таким образом у вас не будет так много XHRs, стреляющих во время загрузки.

Когда требуется конкретный модуль, он может загружать и инициализировать в соответствующее время, а не каждую загрузку страницы.

Если вы немного усложнили свой код, каждый модуль должен иметь возможность запускать и останавливать. Итак, если у вас есть polling встречающийся или сложный код, вы можете остановить модуль для повышения производительности и снижения сетевой нагрузки.

+0

Хотя я согласен с тем, что оптимизация доставки активов является важным шагом в повышении производительности, я не думаю, что это главная проблема, которую я испытываю здесь. Несмотря на то, что в приложении есть JS-приложение, оно gzipped, minified и достигает ~ 100kb. Его также следует кэшировать на стороне клиента, поэтому стоимость загрузки минимизируется для повторных посетителей. –

Смежные вопросы