6. Мобильные сети
TCP-Подключения часто полуживые
Очень нестабильный Ping (от 100мс до 2с)
Иногда в подключение удается отправить лишь один
пакет и не получить ответа
Необходима минимизация трафика, тк часто просто нет
другой возможности работать
Часто пытаются слушать трафик так, что системы
слежения сами падают и теряют пакеты
7. Высоконагруженные
сервисы
Сервера часто умирают
Необходим эффективный протокол, который
рассчитан на нагрузки
Быстрое восстановление работы при разных сбоях
между клиентом и серверами
Производительность протокола напрямую связана
с ценой обслуживания
8. Эффективный HTTP
На каждый запрос 5 попыток с таймаутом в 5 секунд
Не использовать отмену запросов (вешает Apache HTTP)
LongPoll для получения событий
В сумме выходит медленно, но, в целом, стабильно и
комфортно.
Официальное приложение ВК продолжает НЕ делает
так, потому у него часто все плохо.
10. MTProto v2 (by Actor)
Стандартная TLS
криптография
Редиректы
Более гибкая
сериализация
На уровне транспорта
реализованы инструменты
проверки связи
11. MTProto v3?
Peer-To-Peer
Детектирование типа подключения и адаптация
приложения под эти условия
Создание отдельного протокола для обмена
файлами
Версия протокола для Long Fat Networks
12. Детали реализации
Мессенджер VK писался во времена Apache HTTP,
он был стабильным, сейчас считается устаревшим.
Для Телеграмма использовались синхронные
сокеты, а не NIO, тк NIO в разных версиях по
разному глючит. Однако, официальный клиент
всегда разрабатывал на асинхронных.
15. 5 ms
Или 1/3 кадра при 60 FPS
Время загрузки диалогов
16. CursorAdapter
- Чтение из курсора в UI-потоке
- Иногда и повторное чтение
+ Подгружается сразу весь список
+ Нет сложной логики по подгрузке
+ Более гибкое управление данными
17. Cached Cursor Adapter
Кеширование загруженных результатов
Немного исправляет производительность для тех,
кто уже был отображен, но до первого обновления
списка
Все равно читает с диска в UI-потоке
18. MemoryAdapter +
Background Cursor
+ UI работает только с обычным ArrayList, который
обновляется и синхронизируется в фоне с БД
+ Основано на тех же запросах, что и предыдущие
варианты
- Нужно реализовывать сложную логику (не слишком, но в
ней легко допустить баги) и более сложные состояния
списков
- При обновлении списка надо все равно с нуля пере
запрашивать Cursor
20. Оптимизация запросов
Денормализация: убрать все Join
Например, в списке диалогов хранятся имена и аватарки
пользователей и групп и обновляются вручную
Минимизировать сами таблицы и набор колонок для списка,
минимизировать любые большие колонки
В итоге запись немного медленнее, но чтение становится
гораздо быстрее (увы, цифр не помню)
Можно упростить таблицу и оставить только ID и BLOB,
почему-то это работает быстрее.
21. ORM
Без ORM
+ Отсутствие overhead
- Более сложная работа с БД
ORMLite
+ Управление схемой из кода
- Reflection
GreenDAO
+ Малый overhead
- Необходимо писать в коде схему и генерировать необходимые классы
22. Actor List Engine
На базе SQLite, но адаптируемый под любой Storage
Запись - id, sortKey и BLOB
Id генерируется снаружи движка
Асинхронная запись и чтение в фоновом потоке
Кеширование записей
Лишь подмножество операций: addOrUpdate, delete, clear, getItem
Используется ProtoBuf-подобная сериализация
24. Display List
Display List - список элементов, который
синхронизируется с ListView
Можно изменять список из любого потока
Внутри - два списка, которые попеременно
переключаются
Много одновременных изменений списка
группируется
25. BindedDisplayList
BindedDisplayList - DisplayList, который связан с
ListEngine
Автоматическая асинхронная подгрузка данных из
БД
Возможность фильтрации списка (перезапросы в
ListEngine)
Загрузка списка из центра коллекции
26. Результат
Максимальная возможная скорость загрузки
списков из SQLite
Отзывчивый интерфейс
Удобная асинхронная работа с БД
Гибкие синхронизируемые списки, которые не надо
программировать
29. Пара фактов
16 мс на все
Layout сложных объектов долгий. Иногда измерения
проходят не один раз.
В ListView много View - все они делают layout
При обновлении списка - зачастую проходит повторный
Layout (конкретно зависит от версии Android)
Лишние View - лишний рендеринг
31. Список диалогов
Каждый элемент - одно View
Проверяется повторный
binding данных
Пересчитываются размеры
только те, что изменились
Иногда для текста layout
просчитывается в фоне
Это - единственный способ
сделать быстро везде
32. Список сообщений
Расчет размеров текста при загрузке из БД (отключаемо)
Каждое сообщение - лишь одно View с ручной
отрисовкой.
Нажатие на ссылки обрабатываются вручную
Изображения грузятся в фоне и масштабируются строго
под размер сообщения
Blur превью через оптимизированный native-код
35. Переиспользование
памяти
При файловых операциях часто выделяются и
высвобождаются небольшие массивы байт (8-16кб),
что провоцировало GC
Для устранения проблемы был создан собственный
аналог malloc, который кешировал выделенные
массивы и переиспользовал их
В наиболее активных циклах переиспользуются
объекты, а не выделяются новые (например Envelope
в Actor System)
37. Google Cloud Messaging
Большие задержки (до 10 минут) в оповещениях
Иногда просто не работают
Есть устройства без GCM вообще
Итог - Написать свое.
38. Разработка собственных
оповещений
Держать всегда активное подключение
Однако, нужно быть аккуратным что бы не тратить
энергию
Запуск радио происходит за 5 секунд и работает на
полную мощность примерно 10-20 секунд. Затем
еще минуту радио работает в среднем режиме и
только после этого возвращается в спящий режим.
WiFi при этом почти не потребляет энергии.
39. Энергоэффективности
Время перехода от состояний зависят от типа сети
Потребление 3G может быть ниже чем у EDGE, тк
можно за более короткое время скачать нужные
данные
На WiFi можно всегда сколько угодно данных
передавать и батарея не будет садиться вообще
Хорошая лекция от Google: http://www.youtube.com/
watch?v=dASOm88Wh8g
40. Общая логика работы
пушей
У Apple очень умные пуши. Анализируют порядка 23
параметров использования устройства и приложений.
(последнее использование, движение устройства,
последнее открытие приложения, активность его
использования)
У гугла тупее.
Логика очень простая - поднимается коннект и раз в 10
минут на мобильных сетях отправляется пинг для
проверки, на вайфае раз в 2-3 минуты (некоторые роутеры
вешают коннект через 5 минут)