Dropbox - это самый простой способ...
- Хранить файлы в безопасном месте
- Делиться файлами с другими людьми
- Постоянно иметь к ним доступ вне зависимости от своего месторасположения
Взрывной рост
- 1 миллион файлов сохраняются в Dropbox каждые 15 минут (по презентации это больше, чем твитов в Twitter за тот же период времени, но это несколько преувеличено)
- Одно из самых скачиваемых приложений, уступает лишь Skype
- Важная часть жизни многих пользователей: "не могу жить без этого"
- Рост обеспечен "сарафанным радио", практически без рекламы
Команда в начале проекта
- Все хорошие друзья
- Самые умные, голодные и страстные, которых они знали :)
- Для каждого это была первая реальная работа, очень ограниченный опыт в данной индустрии
- Эти качества хорошо сочетаются с итеративной методологией разработки на Python
Ранние достижения
- Reverse engineering приложения Finder для Mac OSX 10.4/5 для отображения иконок статуса синхронизации ("в процессе", "все готово")
- Сложная инфраструктура HTTP нотификаций для избежания регулярного опроса серверов на каждом клиенте, основанная на Twisted
- Общая кодовая база, работающая на всех основных операционных системах: Windows, Mac OS, Linux (на основе PyObjC, wxPython, ctypes, py2exe, py2app, PyWin32)
- Горизонтально масштабируемое хранилище для информации о файлах на основе MySQL
- Собственная инфраструктура для аналитики в реальном времени
- Собственный механизм выделения памяти для Python, позволивший сократить её потребление на 90%
Сферы применения Python
По сути он используется во всех частях проекта:
- логика backend синхронизации;
- клиенты для основных ОС (Windows, Mac, Linux);
- контроллер основного сайта;
- обработка API запросов;
- аналитика.
Исключения из-за ограничений по доступной оперативной памяти:
- Android (мог бы быть Jython)
- iPhone (мог бы быть Cpython)
Почему именно Python?
- Легок в изучении и понимании:
- новые люди легко втягиваются в процесс;
- позволяет людям переключаться с проекта на проект.
- Легок в написании: важно для быстрой реализации функционала и выпуска новых версий.
- Легок в изменении:
- нет необходимости в перекомпиляции;
- высокая скорость итерации;
- динамическая типизация:
- рефакторинг очень прост;
- уменьшение прямых зависимостей модулей;
- динамические инструменты.
- Позволяет обеспечивать качество путем создания более-менее работающей версии продукта и доведения её до качественного уровня путем быстрых итераций.
Не без трудностей
Аргх!!! Python потребляет слишком много оперативной памяти и о-о-очень медленный!
На серверной стороне можно вообще не заморачиваться и купить больше оборудования - всегда помогает. Но для клиентской части такой подход не прокатит, если только Вы не собираетесь купить новые компьютеры и телефоны всем своим клиентам.
Как с этим бороться?
- Убедитесь, что все длинные внутренние циклы выполняются в C (может сэкономить до 44% процессорного времени)
- С оптимизацией потребления вычислительных ресурсов все просто:
- есть много готовых решений для профайлинга;
- проблемный код чаще всего не раскидан по всей кодовой базе.
- С оптимизацией потребляемой памяти все сложнее:
- нет готовых решений для профайлинга память (одновременно в Python и C);
- много потенциальных причин для повышенного потребления памяти:
- утечки в Python и C;
- фрагментация памяти;
- неэффективное её использование.
- Как исправить? Однозначного решения нет - чаще всего приходится перерывать всю кодовую базу в поисках неоптимальных мест и источников утечек.
- Почему память фрагментируется?
- Большинство объектов расположены в heap памяти (большой последовательный кусок, выделенный приложению);
- Много маленьких объектов вперемешку с большими;
- Много временных объектов вперемешку с постоянными;
- В CPython нет сборщика мусора, позволяющего собрать объекты компактно в одной части heap'а.
- Решением проблемы с фрагментацией стал собственный аллокатор памяти (механизм её выделения под определенные типы объектов):
- В Dropbox обнаружили, что большая часть heap-памяти захламляется контейнерами с метаданными файлов, которые синхронизируется;
- Было решено вынести их куда-нибудь еще;
- CPython позволяет управлять процессом выделения памяти для типов данных расширений;
- Делается это с помощью простых структур на C;
- "Not Rocket Science, just C code";
- Выделяются области памяти по 4Мб, состоящие из заголовка и буферов фиксированной длины.
- Что насчет внутренней фрагментации?
- по идее же даже в одном буфере останутся данные, весь блок нельзя будет освободить...
- потенциально этот факт может привести к еще большему расходу оперативной памяти;
- но это оказывается не так, если учесть, что все объекты являются временными, то есть живут не долго!
- в результате Dropbox редко использует более 100Мб памяти для больших синхронизаций (раньше эта цифра могла достигать 1.5Гб)
- Но писать C расширение для каждой структуры данных, которую может понадобиться вынести в отдельный аллокатор - дело неблагодарное: в результате эта история закончилась изменением
type_new()
вObjects/typeobject.c
для того, чтобы можно было указывать__use_region_allocator__
= True** для тех классов, которым требуется такой механизм выделения памяти.
Подводим итоги
- Python стал ключом к технической реализации обоих сторон Dropbox: серверной и клиентской.
- Залогом успеха является максимальная простота с пользовательской точки зрения: "положил файл в папку и он становится доступен отовсюду"
- Dropbox не брали на себя реализацию стороннего функционала, вроде собственно создания хранилища файлов - используется Amazon S3, что позволило им запуститься очень быстро и стремительно.
- Лучше решать одну задачу, но качественно, чем много, но так себе!
Источники информации
18 марта 2011 | | Высокие нагрузки