Как ускорить рендеринг вложенных полей simple_fields_for?
Есть две модели (товар и характеристики товара), связянные ассоциацией has_one
Есть форма - делится на две логические части
1 Для редактирования общих для всех товаров полей
2 Специфичных для данной категории полей
С первой частью вопросов нет. Пользуемся simple_form_for для вытащенной из базы записи и рендерим f.inputы. Все достаточно шустро.
Но как доходим до паршиала дополнительных полей появляются большие тормоза
Объявляю блок simple_fields_for в котором для вытащенной из базы связанной записи характеристик рендерим все те же инпуты. Так вот серверу требуется около ~100мс на рендер одного чекбокса. Я уже выбросил все лишнее из кода паршиала дополнительных полей. Оставив только рендер 20 чекбоксов. Но не тут то было WebRick утверждает, что на рендер этого паршиала уходит 2 секунды. А боевая форма висит все 6 секунд только на этом месте. Что здесь может крыться не то? (По поводу приведения кода даже не знаю - там особо смотреть не на что).
Такое ощущение, что для того, чтобы выяснить состояние чекбокса для отображения simple_form делает новый запрос к базе для каждого инпута. Лог сервера говорит, что при загрузке страницы происходит три запроса к базе: выбираем пользователя, товар, характеристики, потом идут рендеринги паршиалов...
Rails 4.2.1, simple_form_for 3.1.0
В общем я нашел решение!! Оно было на гитхабе в разделе bug reports репозитория simple_form. What is the expected slowdown of using SimpleForm?
Там мистер nashby в марте этого года написал примерно следующее:
SimpleForm spends a lot of time for trying to translate hints and placeholders for inputs
Соответственно подставив везде placeholder: false, hint: false где только можно. Получил ускорение с 6 секунд до 780ms.
Имейте ввиду у себя в приложениях ;)
Не видя кода, можно только ванговать.
6 секунд — очень много для одной формы. Причины могут быть такие:
1. Плохо составлены запросы к БД, из-за чего загрузка данных занимает слишком много времени (проблема N+1)
2. Плохо составлена структура страницы/паршиалов. Паршалы сильно замедляют рендеринг страницы, поэтому стоит оптимизировать структуру страницы и сократить количество паршиалов
Рендерится 10 паршиалов. Итого страница отрендерилась за 5400мс из которых лейаут 2700 и урезаная до нельзя проблемная форма тоже 2700, остальные паршиалы по 1-20мс. Проблемы N+1 нет (или я ее не вижу в логах) так как связь has_one. Вижу 3 запроса по 1мс.
Антон Мисягин: То есть один только этот паршиал рендерится 2700 мс? А вся остальная часть вьюхи — другие 2700?
Если удалить часть чекбоксов, то сколько времени будет рендериться? А если вообще убрать чекбоксы, оставить только голую форму? А если саму форму убрать, оставить паршиал без формы?
@category, @details — ещё вот это меня смущает. Тут нужно первым параметром передавать название ассоциации, а вторым — объект модели apidock.com/rails/ActionView/Helpers/FormHelper/fi...
"То есть один только этот паршиал рендерится 2700 мс?""
да
" "А вся остальная часть вьюхи — другие 2700?""
все остальное еще примерно 3сек
"Если удалить часть чекбоксов, то сколько времени будет рендериться?""
пропорционально количеству чекбоксов
"А если вообще убрать чекбоксы, оставить только голую форму?"
совсем на голую ругается, оставляю один инпут:
= f.simple_fields_for @category, @details do |f|
= f.input :used, label: ":", as: :integer
120мс
"А если саму форму убрать, оставить паршиал без формы?""
29мс
"@category, @details — ещё вот это меня смущает. Тут нужно первым параметром передавать название ассоциации, а вторым — объект модели""
я пробовал:
= f.simple_fields_for @category, @details do |f|
= f.simple_fields_for @category do |f|
= f.simple_fields_for @details do |f|
Антон Мисягин:
= f.simple_fields_for @category, @details do |f|
= f.simple_fields_for @category do |f|
= f.simple_fields_for @details do |f|
И это всё неправильно. Должно быть = f.simple_fields_for :detail, @category.detail do |f| если Category has_one :detail
Это единственная причина, как мне видится, которая здесь может быть, так как 20 инпутов это слишком мало, чтобы рендер начал тормозить.
Продолжил заниматься проблемой. Разбил все на две формы. Т.е. есть отдельный маршрут для редактирования деталей товара. Соответственно ушел от использования siple_fields_for. Теперь эта форма не содержит вложенных полей, а только непосредственные. Стоит отметить, что ничего не поменялось)). Потом решил попробовать без simple_form_for и без f.input. Т.е. Переписал в виде form_for и f.check_box. И тут все зашуршало 70ms. Стою, чешу репу...
Попробовал модифицировать другие формы приложения просто добавив в них порядка 50 повторений одного и того же инпута, присущего той форме, которую изменял, т.е.:
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
= f.input :empty
...
и так 50 раз в любой форме (естественно :empty уже есть на форме в моем случае). И вуаля. Вот они тормоза! Даже не знаю что и делать. Хоть прям ищи замену simple_form который теперь очень тесно переплетается с моим приложением и выдергивать его будет очень больно(((