Pull to refresh

Ну да, сайты на C++

Reading time4 min
Views34K
Проскочила пара топиков про веб на C++ и уж много товарищей недопонимают смысл использования C++ в вебе. Поэтому расскажу как я в своем опыте использовал это. Я использовал, правда, Python, но только потому что библиотеки типа WebToolKit не было под рукой.

Если честно, я в C++ разбираюсь как хакер в женских помадах — как и многие, я большей частью использую PHP (и все больше Python, но его редко для веба — больше для OpenGL), но тем не менее это не мешает мне его(C++) использовать. Это к тому, что не пугайтесь сложности языка — там не все так плохо, как кажется.

Но, что важно: «Premature optimization is the root of all evil». И это важно. Писать какую-нибудь сложную систему сразу на C++ бессмысленно (я про сайты, конечно). Оптимизировать, как правило, нужно только 3% кода. Вот про эти 3 процента я и расскажу.

Был у меня сайт и на нем на всех страницах пользователи могли кое-чего кое-куда писать (долго объяснять) и в уголке шел «поток» в реальном времени (через AJAX update каждые 5 секунд) кто куда и чего написал. Делалось, как и положено на PHP/MySQL — таблица, в ней выбираем последние (условно говоря: WHERE id>MAX(id)-10 ORDER BY id DESC) записи. Периодически удаляем все, кроме последних десяти. Работало замечательно. Пока TechCrunch про сайт не написал. Сдох сервер из-за этой части. Как только я ее отключил (помните про 3%?) — все десятки тысяч человек, что они мне послали — прекрасно стали видеть сайт. Я решил это коряво — сделал memcache. PHP выбирал последние 10 записей и писал в memcache, а при запросах — отдавал строчку из memcache. Однако и это решение в результате начало помирать.

Я написал простенький http-сервер на Python (из стандартной библиотеки), который имел массив в 10 строчек и отдавал его AJAX запросу или добавлял новую и удалял первую (FIFO).

То есть PHP (на сервере) обрабатывало формы и отправляло через file_get_contents('http://mysite.com:9000/?put='.urlencode($_GET[msg])); а AJAX (в смысле — клиент на JavaScript) напрявлялся на mysite.com:9000/?get — в обход всех Апачей, PHP интерпретатора, MySQLя и даже memcached (к которому все равно надо коннектится — а это время — оверхэд).

Написать такое приложение на Python или на C++ при наличии хорошей библиотеки HTTP-server'а — разницы никакой. C++ уже имеет достаточно много средств для достаточно высокоуровневого программирования. Даже средний программер на PHP в состоянии на современном C++ писать безопасные и серьезные приложения.

Но, и вот тут уже интересно: запущенный Python HTTPd скриптик кушает до 10-20Mb оперативки, а запущенный C++ сервер с недавно опубликованным WebToolKit — всего 0.6-1.4Mb (речь идет про RES память). Так что такий маленьких оптимизаций на сервере может быть запущено море (в отличии от Python, который кусками по 20Mb на небольшом VPS быстро скушает всю память).

Аналогично сделать, например, реал-тайм показ пользователей на сайте — кто-на какой странице-откуда.

Как результат — сайт все еще на PHP, он ускорен в десятки раз (за счет оптимизации самого тяжелого к выполнению куска), база данных разгружена, никаких dog pile эффектов кэширования и т.п., а по времени ну часа 2-3 ушло на эту оптимизацию.

Другой пример — голосования. Допустим что Вам надо добавить за кого-то голос через AJAX и сохранить IP пользователя чтобы он больше не голосовал. На C++ это займет в памяти ну может байт 20, таким образом можно спокойно хранить все данные обо всех пользователях и голосах за последнюю неделю с мгновенным доступом к ним. В то же время, если это делать обычным способом (PHP/Python + MySQL/SQLite/Postgres...) база данных будет разрастаться и доступ к ней замедляться и если обращения идут постоянно — это может значительно замедлить сервер. Я не говорю тут что SQL проиграет раз в 10 памяти, но у меня бывали такие случаи (в частности SQLite :memory: проигрывает файловому SQLite в десятки или даже сотни раз).

Еще пример — ГЕО-локация пользователя. Можно загрузить информацию о всех IP в память (разумеется в форме range'й) и C++ один цикл пройдет за наносекунды, в то же время PHP+MySQL будут долго копаться подбирая нужный range.

Еще: счетчик чего-нибудь, допустим количества голосов за пост (или кармы) — карму всех пользователей реально держать в памяти и пусть AJAX напрямую к сишному серверу обращается, в то же время PHP/MySQL, да и Django что будут делать: проверим изменился ли файл(PHP), сделаем regex проверку куда мы идем (django routes), если нет оптимизатора в PHP — прочитаем заново файл, пропарсим его, инициализируем коннект к базе данных, запросим одну цифру, поставим лок, чтобы никто ее пока не изменял, увеличим ее, вернем назад, снимем лок.

И это если нет ORM, а ведь Джанго еще насоздает объектов, чтобы обработать запрос и вернуть его. Это все, конечно, проблема, а не катастрофа, но опять же — если у Вас 99% времени тратится на бесполезные вещи — то не лучше ли от них за часик избавиться.

В то же время для C++ это практически пара процессорных тактов (+1 к Integer в памяти и перевести в строку). Проще говоря, пока PHP+MySQL один такой запрос обработают, C++ сделает может и тысячу, может и миллион (если не учитывать время на обработку самого HTTP протокола). Да и такая программа на C++ будет по факту может и короче (но уж вряд ли сильно длиннее), чем PHP+MySQL.

В общем, если есть задачи уровня «к чему-то надо прибавить единицу», «найти что-то среди небольшого набора чего-то» — то куски сайтов на C++ могут Вас очень выручить. А общее представление пока все равно лучше делать на чем-то более высокоуровневом (типа PHP/Python) или присматриваться к таким языкам как Arc.

Недостатки такого подхода?

Ну больше заморочки.

1. Мониторинг, например. Как вариант — самый простой, допустим есть compiled_file.cpp, который компилится в compiled_file (без расширения). Заходим в crontab (crontab -e) и дописываем:

* * * * * /bin/pgrep compiled_file || /path/to/compiled_file

Максимум минуту пролежит скрипт если что не так, потом перезапустится. Реально — меньше пол-минуты.

2. Update работающего процесса. Да просто заменой файла, как в PHP не обойдется, придется убивать процесс (killall compiled_file) и перезапускать.

Так что не стоит отбрасывать так сразу идею сайтов на С++, но и фанатизмом страдать тоже не надо. Вы можете и на C++ написать целый сайт, но если у Вас полчеловека в день — то зачем?

Просто использование этого языка должно быть обоснованно. Если у Вас сервер загружен на 100% и Вы знаете что 90% запросов идет к одному месту, которое можно было бы очень просто выразить в виде маленького сервера с отпечатком памяти в 1МБ и который бы не требовал баз данных, интерпретаторов и т.п. — то зачем покупать более дорогое оборудование, вместо того чтобы заменить этот кусок на компилированный?

А если С++ уж очень страшный — то посмотрите на то, что такое Cython для Python'а.


Йои Хаджи,
вид с Хабра
Tags:
Hubs:
Total votes 156: ↑142.5 and ↓13.5+129
Comments105

Articles