Как я ускорил выгрузку чата Telegram в 11 раз и долго чинил не то
У меня есть проект, который считает статистику переписки прямо в браузере. Кто пишет первым, кто дольше отвечает, какие слова повторяются. Для Telegram обычно нужен файл экспорта из Telegram Desktop, а с телефона его не сделать никак. Поэтому я сделал второй путь. Человек входит в свой Telegram прямо на странице, выбирает чат, и браузер сам скачивает историю через официальный API, как обычный клиент.
Работало это три недели, и работало медленно. Я открыл свою аналитику. Чат на 100–250 тысяч сообщений выгружался в среднем 33 минуты, самый долгий сто. И всё это время человек держит вкладку открытой с горящим экраном, потому что в фоне телефон останавливает загрузку. Дожидались не все.
Потом я выгрузил с телефона свою переписку на 52 тысячи сообщений. Страница честно написала, что осталось около 29 минут. Вы бы стали ждать полчаса, глядя на полоску загрузки? Я бы, наверное, нет.
Сейчас тот же чат с того же телефона грузится за две с половиной.
Но путь к этому вышел кривой.
Куда уходило время
Telegram отдаёт историю страницами по сто сообщений. Если спрашивать слишком часто, он отвечает «подождите N секунд». В первой версии я сделал паузу между страницами и удваивал её после каждого такого ответа. А уменьшать забыл. Одна неудачная минута в начале, и дальше весь чат ползёт на минимальной скорости. Ошибка глупая, исправил сразу.
Дальше интереснее. Библиотека, через которую я хожу в Telegram, короткие просьбы подождать молча пережидает сама. Мой код их просто не видел, и в аналитике выходило, что Telegram почти не жалуется. Я выключил это поведение и посмотрел на реальную картину со своего телефона.
Telegram не попросил подождать ни разу. А страница всё равно шла три с половиной секунды. Почему?
У других людей, судя по той же аналитике, ответ занимает около 0,2 секунды на страницу, у меня в пятнадцать раз дольше. На телефоне у меня включён VPN. Видимо, дело в нём, хотя без VPN я так и не проверил. Но тогда я об этом не подумал и пошёл чинить ограничения, которых не было.
Режим экспорта, который ничего не дал
У Telegram есть официальный режим для экспорта, им пользуется сам Telegram Desktop. В нём, если верить документации, лимиты мягче. Сразу его не включить. На свежем входе Telegram присылает в служебный чат запрос на экспорт, и человек должен нажать «Разрешить». Я сделал плашку с этой просьбой и тихий повтор, пока кнопку не нажмут.
Ускорения не случилось. Я полез в исходники Telegram Desktop, нашёл, что он делает ещё (запрашивает историю по диапазонам и совсем без пауз), повторил. Те же три с половиной секунды на страницу.
Если подумать, всё логично.
Режим экспорта снимает ограничения на число запросов, а я в них не упирался, время съедала дорога туда и обратно. Это я понял, кажется, далеко не сразу, когда уже переписал половину кода выгрузки, добавил плашку, повтор запроса и диапазоны, и всё равно смотрел на те же три с половиной секунды в строке скорости.
Двенадцать страниц сразу
Раз один запрос идёт три секунды, а Telegram не жалуется, напрашивается простое. Просить несколько страниц одновременно, каждую по своему соединению.
Сколько именно, снаружи никто не знает, и я сделал так, чтобы ширина подбиралась сама. Начинаем с четырёх страниц, после трёх спокойных пачек добавляем ещё две, до двенадцати. На первое же «подождите» ширина падает вдвое. Без режима экспорта потолок три, там Telegram, по моим ощущениям, строже.
Вышло 52 тысячи сообщений за две с половиной минуты. Telegram за всю выгрузку один раз попросил подождать 19 секунд. Тут надо сказать честно. В последнем замере ответ сервера вдруг стал быстрее, похоже, VPN в тот вечер работал лучше. Часть прироста подарила сеть, и сколько именно, я не знаю. С компьютера по QR получилось так же быстро.
И кстати, режим экспорта в итоге пригодился. Без него больше трёх страниц сразу просить не стоит, а с ним двенадцать проходят почти без пауз. Так что плашка с «Разрешить» осталась главным советом на экране.
Не качать то, что уже есть
Вторая половина работы про повторную выгрузку. Человек посчитал чат в октябре, а в декабре хочет итоги года. Зачем снова тянуть сто пятьдесят тысяч сообщений, если новых там тысяч пять?
Теперь переписка сохраняется на самом устройстве, в браузере, сжатой. Чат на 52 тысячи занимает 1,9 МБ. При обновлении страница скачивает только новое и ещё два дня до последнего сохранённого сообщения. Эти два дня заменяются свежей версией целиком, так в итог попадает то, что за это время удалили или исправили, и не бывает дублей.
Обновление чата, где за пару часов ничего не написали, заняло меньше половины секунды.
Неделя переписки, наверное, займёт несколько секунд.
Самое обидное случилось в конце. На компьютере всё работало, а на iPhone копия молча не сохранялась. Полдня ушло, чтобы понять, что Safari не даёт второй раз прочитать файл, который я уже убрал из кэша. В Chrome можно, в Safari нет. Пришлось сохранять копию раньше, пока данные ещё в памяти.
Чего я до сих пор не знаю, так это сколько запросов сразу выдерживает Telegram на хорошей сети, без VPN. У меня один аккаунт и один вечер замеров. Если кто-то выгружал большие чаты через API и мерил, расскажите, мне правда интересно сравнить.