Кто-нибудь захочет дать мне совет о том, как я могу улучшить производительность следующего метода контроллера?Улучшение производительности контроллера Rails, возвращающего сериализованный хеш
def index
@contacts = Hash[current_user.company.contacts.map {|contact| [contact.id, ContactSerializer.new(contact).as_json[:contact]] }]
respond_to do |format|
format.json { render json: { contacts: @contacts } }
end
end
Это возвращает следующую структуру данных:
{
contacts: {
79: {
id: 79,
first_name: "Foo",
last_name: "Bar",
email: "[email protected]",
engagement: "0%",
company_id: 94,
created_at: " 9:41AM Jan 30, 2016",
updated_at: "10:57AM Feb 23, 2016",
published_response_count: 0,
groups: {
test: true,
test23: false,
Test222: false,
Last: false
},
invites: [
{
id: 112,
email: "[email protected]",
status: "Requested",
created_at: "Jan 30, 2016, 8:48 PM",
date_submitted: null,
response: null
}
],
responses: [ ],
promotions: [
{
id: 26,
company_id: 94,
key: "e5cb3bc80b58c29df8a61231d0",
updated_at: "Feb 11, 2016, 2:45 PM",
read: null,
social_media_posts: [ ]
}
]
},
81: {
id: 81,
first_name: "Foo2",
last_name: "Bar2",
email: "[email protected]",
engagement: "0%",
company_id: 94,
created_at: "12:55PM Feb 04, 2016",
updated_at: " 4:25PM Feb 19, 2016",
published_response_count: 0,
groups: {
test: true,
test23: true,
Test222: false,
Last: false
},
invites: [
{
id: 116,
email: "[email protected]",
status: "Requested",
created_at: "Feb 22, 2016, 9:10 PM",
date_submitted: null,
response: null
}
],
responses: [ ],
promotions: [
{
id: 26,
company_id: 94,
key: "e5cb3bc80b58c29df8a61231d0",
updated_at: "Feb 11, 2016, 2:45 PM",
read: null,
social_media_posts: [ ]
}
]
}
}
}
Мне нужен метод index
возвращать хэш где ключи идентификаторов контактов, в отличие от массива, который является то, что обычно возвращаться. Кроме того, я передаю каждый контакт через сериализатор, чтобы получить все связанные данные, которые нужны моему клиенту.
Этот метод работает нормально, когда есть только несколько контактов, однако, когда у меня есть 100 или 1000, он действительно замедляется. Я сравнил его с 100 контактами, и для завершения потребовалось 4 секунды, что было ужасно. Мне интересно, как я могу улучшить свой код, чтобы получить точно такой же результат более результативным образом. Ключевым моментом здесь является то, что выход должен оставаться неизменным. Я не заинтересован в изменении кода на стороне клиента (это зависит от этой структуры данных для множества приложений), поэтому все изменения должны происходить на стороне сервера.
Вот мой ContactSerializer
для справки:
class ContactSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :email, :engagement, :company_id, :created_at, :updated_at, :published_response_count, :groups
has_many :invites
has_many :responses
has_many :promotions
def groups
Hash[object.company.groups.map {|group| [group.name, object.groups.include?(group)] }]
end
def published_response_count
object.responses.where(published: true).count
end
def created_at
object.created_at.in_time_zone("Eastern Time (US & Canada)").strftime("%l:%M%p %b %d, %Y")
end
def updated_at
object.updated_at.in_time_zone("Eastern Time (US & Canada)").strftime("%l:%M%p %b %d, %Y")
end
def engagement
object.engagement
end
end
Для чего это стоит, я полностью осознаю, что возвращает данные в формате JSON, как это с Rails не является большой практикой и с тех пор отошел от него полностью. К сожалению, этот фрагмент кода был написан довольно давно, и я не могу позволить себе время полностью переписать клиентскую сторону, чтобы потреблять стандартный вывод, такой как массив контактов.
«Рефакторинг» меняет структуру кода ради структуры. Улучшение производительности - это не рефакторинг. Я отредактировал соответственно. Что касается производительности, медленность, вероятно, связана с повторяющимися запросами при поиске групп, приглашений и/или рекламных акций и, вероятно, может быть исправлена путем добавления 'includes' в запрос контактов. Посмотрите в log/development.log и посмотрите, какие запросы повторяются и/или замедляются. –