Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

05.06.2024

Профілювання у Swift та оптимізація запитів


Етапи профілювання в утиліті XCode Instruments

Сьогодні вперше профілював застосунок на Swift, щоб його пришвидшити. Проблема наступна: список тегів при перемиканні на режим “сортувати за частотою” помітно гальмував. Вдалося знайти причину та оптимізувати.

В XCode найбільш дружній профайлер з всіх, що я бачив; він не тільки показує профіль, а ще й виділяє підвисання UI та відразу знаходить найважчий виклик. (Хоча планка дружності у профайлерів наднизька: навіть просто графічний інтерфейс є тільки для JavaScript в браузері.)

В чому виявилася біда. У SwiftData, щоб підрахувати кількість обʼєктів у асоціації, їх потрібно повністю завантажити та ініціалізувати. А значить, для мого списку за частотою фактично завантажувалась вся база, та ще й антипатерном N+1, та ще й, здається, не один раз, бо це відбувалося всередині алгоритму сортування.

Проблема загальна, зате рішення, до якого я звик в SQL, немає. А саме, жодних COUNT ... GROUP BY. Або взагалі способу обходити граф обʼєктів, окрім як прямий пошук, або асоціації. Вихід, який я знайшов, простий — зберігати кількість в окремому атрибуті (так званий кеш кількості.) Тепер можна взагалі з бази діставати теги, впорядковані за частотою.

Після цього “суворе зависання” перейшло у “мікрозависання”. Профіль вказав, що хоч я виправив сортування за кількістю, то все одно завантажував всі обʼєкти, щоб показати першу та останню дату використання тегу. Для того також додав атрибут-кеш. На цьому зависання закінчились.

Висновок: виходить, у SwiftData/CoreData більше логіки перекладається на шар застосунку. Це відрізняється від звичного для вебу підходу, де база є потужнішою та відповідальнішою. Втім, і контекст застосунку на одного користувача з локальною базою суттєво відрізняється від рівночасного багатокористувацького вебу.