Я участвовал в недельном испытании, который стартовал 4 мая, опишу свой подход. В таблицу лидеров вошло 445 человек:

Обзор задачи

Участникам был предоставлен веб-интерфейс с 33 короткими задачами кодирования и ограничением по времени в 180 секунд. Ограничений на количество испытаний не было. Также нас поощряли к творчеству, позволяли боты.

Всего за проблемы с кодированием было получено 1740 баллов. За подачу досрочно начислялось 10 дополнительных баллов за каждую секунду. Таким образом, если бы кто-то каким-то образом отправил их все мгновенно, это было бы дополнительными 1800 баллами, в результате чего общее количество достигло бы 3540. Лучшие 6 набрали ›3500 баллов, так что 33 решения отправлены менее чем за 4 секунды.

Как все прошло

Вначале люди начинали решать задачи и копировать их вручную, доходя до лимита только из задач кодирования. До тайм-аута можно вставить вручную 33 задачи, чуть меньше 180 секунд. Ускорение - это когда начинается самое интересное.

Ранее уже проводился аналогичный конкурс JavaScript, вот и ретроспектива. Можно автоматизировать вставку или пропустить браузер и просто поговорить с API. Второй бежит быстрее, поэтому многие на него пошли. Чтобы быстро воспроизвести обмен данными, можно проверить запросы HTTPS, сохранить их как cURL и затем преобразовать в код библиотеки Python requests. Я также удалил ненужные данные: оставил только cookie из заголовков, а исходный код задачи мог состоять только из одного символа. D оказался самым быстрым из-за своей битовой структуры.

Нет, шучу, это могло быть что угодно (пусто не вышло). Но да, ваш код не запускался на стороне сервера, сервер проверял только ответы на случайные тестовые случаи (которые вам нужно было отправить). В ответе сервера прибыли случайные тестовые примеры для следующей задачи.

Если бы тестовые примеры не были случайными, можно было бы отправить 33 запроса еще быстрее, ждать ответа сервера не нужно. Идентификатор попытки был, но при быстрой отправке он просто увеличивался.

Python отправил все ответы на моем ноутбуке за ~ 11 секунд. Посмотрим, куда его отправили:

$ host speedcoding.toptal.com
speedcoding.toptal.com has address 104.22.43.181
speedcoding.toptal.com has address 104.22.42.181
speedcoding.toptal.com has IPv6 address 2606:4700:10::6816:2ab5
speedcoding.toptal.com has IPv6 address 2606:4700:10::6816:2bb5

Проверка первого адреса, например, Https://ipinfo.io/104.22.43.181 сообщает, что это Cloudflare US. Таким образом, пакеты сначала летают туда, а затем на фактический сервер оценивания, время прохождения туда и обратно имеет большое значение. Но я мог бы запустить его из бесплатного экземпляра на AWS / GCP в каком-нибудь регионе США. После проверки пары комбинаций AWS us-east-1c показался самым быстрым, в результате чего время сократилось до 4 секунд.

Чтобы увеличить количество испытаний (из которых самые быстрые учитывались в таблице лидеров), я отправлял каждые 7 секунд:

$ while true; do date; time python3 run.py; sleep 7; done

Можно выйти из системы и оставить на ночь с:

$ nohup ./loop.sh &

Это также дало хороший nohop.out журнал для grep, sort по времени и т. Д.

Более быстрая отправка может произойти через несколько часов. Сокращение 100 мс давало 1 балл (и верх был плотным, каждая точка имела значение). Другие оптимизации:

  1. Использование keep-alive, чтобы избежать постоянного рукопожатия.
  2. Отключение проверки SSL (API работал только с HTTPS).

Подробности вы можете найти в исходном коде. Публикую как было, только вырезанные решения задач, потому что организаторы попросили, чтобы они могли повторно использовать задачи.

Резюме

Я должен был попробовать другие библиотеки Python, такие как urllib3 и pycurl, другие говорили, что они быстрее. Имеет смысл, потому что requests вызывает urllib3, а pycurl - это интерфейс Python для libcurl.

Я пробовал разные вещи, но безрезультатно:

  1. Более мощная машина (m5n.24xlarge) с «улучшенными сетевыми возможностями» на AWS. В GCP я не видел эквивалента для «расширенных сетей».
  2. HTTP / 2, для которого использовалась слишком старая версия curl, нашла hyper библиотеку Python, но она не была заменой для requests, поэтому не стал тратить на нее больше времени.

В целом задача была легкой по времени, а формат был довольно оригинальным. Спасибо организаторам и поздравляю всех участников, было весело.

Если вам нравятся такие итоги соревнований, я недавно написал еще одно: Наш NIPS 2017: подход к обучению бегу.