About |

Пробуем Jinja2 в Django с помощью coffin

Попробовали перевести  проект vpoisk.tv на  Jinja2

Легко гуглится обёртка для Django, поддерживающая основые фильтры Django templates - https://github.com/coffin/coffin/

Всё что вам нужно сделать для переезда это:

  1. Установить Jinja2 и Coffin - pip install jinja2, pip install coffin.

  2. В вашем views.py, меняем:

    from django.shortcuts import render
    

    на:

    from coffin.shortcuts import render 

    note: render почему-то не описан в доках coffin (только render_to_response). Можно использовать и его.

  3. Меняем шаблоны, чтобы соответствовали синтаксису jinja2 и coffin.

    Всё.

Еще один сервис по поиску видео роликов

Т.к. vscrpaper.com был продан, решили сделать новый сервис для поиска интересных видео роликов.

Основная фишка этого проекта — он не пропустит ни одного интересного видео ролика, который появляется в сети. На данный момент добавлены сервисы Youtube и Вконтакте. В разработке — vimeo.com. Кроме того в будущем на него можно будет загружать свои видео ролики.

Приколы для программистов

Мы запустили очередной проект -  приколы для программистов.

На сайте ежедневно размещаем гиф-картинки с тематической подписью. Сайт сделан “для себя/just for fun”. - 

Еще пара сайтов на движке pron888

Запустили английскую версию поисковика порно роликов — porn search engine. И еще одну русскую — поисковик порно видео. Выбирайте, какая вам больше нравится.

На prn88.com количество роликов уже перевалило за 2 миллиона. Предложения и критика приветствуются!

Прикольные картинки

Сделали для себя такой проект — прикольные картинки. Основная фишка в постоянном обновлении из различных источников. И когда нам скучно, мы всегда можем открыть сайт http://jpg-1.com/ с новыми приколами! Сейчас уже подключено 19 источников, но будет гораздо больше!

vscraper — смотрим ютуб

Запустили новый проект — vscraper.com — видео ролики. В проекте нет ничего особенного. Парсит топы ютуба, яндекс.видео и строит свой рейтинг видео роликов. Цель была — сделать для себя автоматический инструмент, позволяющий находить/смотреть новые, интересные ролики на ютубе.

Джаббер бот анекдотов

Обновился jabber-бот анекдотов и цитат с баш.орг.ру. Jid — anekdot@webii.ru. Чтобы нормально с ним общаться — его необходимо добавить в ростер и запросить авторизацию. Если у вас бот был добавлен уже давно но не авторизован — бот отвечать не будет. В данном случае нужно заново запросить авторизацию.

Новый проект — поиск порно роликов

Запустили новый проект — поисковая система по бесплатным порно роликам. Сейчас в базе уже более 1 миллиона роликов. Ежедневно база пополняется на 2-3 тысячи роликов:

Поиск пока только самый базовый: по релевантности и по рейтингу. Кроме того можно сортировать ролики по размеру и популярности.

Основная фишка — поисковик находит англоязычные ролики по русским запросам. Например: лесбиянки со страпоном. Как видите в топе находятся англоязычные ролики, релевантные поисковому запросу.

Быстрый random() select

Я долго думал как без костылей, а только на уровне базы (PostgreSQL) сделать быстрый select * from table order by random(); К сожалению ничего хорошего найти не получилось. Вот explain на базе из около 300 000 записей:

     Limit  (cost=29127.46..29127.71 rows=100 width=358) (actual time=2531.542..2531.900 rows=100 loops=1)

       ->  Sort  (cost=29127.46..29850.98 rows=289406 width=358) (actual time=2531.536..2531.658 rows=100 loops=1)

             Sort Key: (random())

             Sort Method:  top-N heapsort  Memory: 67kB

             ->  Seq Scan on wall_wallpapper  (cost=0.00..18066.58 rows=289406 width=358) (actual time=0.033..1139.509 rows=276459 loops=1)

     Total runtime: 2532.240 ms

Не очень быстро. Очевидным решением было генерировать массив случайных значений на уровне кода и выбирать жанные по ключу. Чтобы выбирать по сгенерированным в коде значениям нам нужен непрерывный интервал значений (чтобы не было “дырок”). Это решение мне не очень нравится, но работает оно очень быстро. Итак для этого я создал таблицу с непрерывным интервалом значений, и ключом на исходную таблицу (в моем случае таблицу с обоями) -

Column  |  Type   |                         Modifiers                          | Storage | Description 

–––+–––+––––––––––––––––––––+–––+––––-

 id      | integer | not null default nextval(‘wall_wallhash_id_seq’::regclass) | plain   | 

 h_id    | integer | not null                                                   | plain   | 

 w_id_id | integer | not null                                                   | plain   | 

Indexes:

    “wall_wallhash_pkey” PRIMARY KEY, btree (id)

    “wall_wallhash_h_id_key” UNIQUE, btree (h_id)

    “wall_wallhash_w_id_id” btree (w_id_id)

Foreign-key constraints:

    “wall_wallhash_w_id_id_fkey” FOREIGN KEY (w_id_id) REFERENCES wall_wallpapper(id) DEFERRABLE INITIALLY DEFERRED

Has OIDs: no

где h_id — значение на непрерывном интервале, w_id_id — ключ на таблицу с обоями (джанга сгенерировала такое название, т.к. я сначала хотел делать триггером и назвать ключ w_id)
Эту таблицу я заполнил непрерывным интервалом с ссылками на таблицу обоев -
    
    CREATE SEQUENCE tmp_hash;
      insert into wall_wallhash (h_id, w_id_id) (SELECT nextval(‘tmp_hash’), id from wall_wallpapper);

 В коде я генерирую случайные значения в интервале от 0 до max() значения таблицы ключей. И выбираю данные примерно следующим запросом - 

    select * from wall_wallpapper where active=TRUE and id in (select w_id_id from wall_wallhash where h_id in (23260,79052,115503,235463,22031,17547,91859,95542,17186,244111,136111, …. 101076,218414,227782,120009,25861))

     Nested Loop  (cost=722.88..1526.57 rows=100 width=358) (actual time=3.687..6.449 rows=100 loops=1)

       ->  HashAggregate  (cost=722.88..723.88 rows=100 width=4) (actual time=3.605..3.740 rows=100 loops=1)

             ->  Bitmap Heap Scan on wall_wallhash  (cost=397.92..722.63 rows=100 width=4) (actual time=2.180..3.390 rows=100 loops=1)

                   Recheck Cond: (h_id = ANY     (‘{23260,79052,115503,235463,22031,17547,……..101076,218414,227782,120009,25861}’::integer[]))

                   ->  Bitmap Index Scan on wall_wallhash_h_id_key  (cost=0.00..397.90 rows=100 width=0) (actual time=2.140..2.140 rows=100 loops=1)

                         Index Cond: (h_id = ANY     (‘{23260,79052,115503,235463,….. 227782,120009,25861}’::integer[]))

       ->  Index Scan using wall_wallpapper_pkey on wall_wallpapper  (cost=0.00..8.01 rows=1 width=358) (actual time=0.021..0.023 rows=1 loops=100)

             Index Cond: (wall_wallpapper.id = wall_wallhash.w_id_id)

             Filter: (wall_wallpapper.active)

     Total runtime: 6.737 ms

Как видно время уменьшилось почти в 400 раз! И чем больше база тем больше будет разница в этих значениях. 

 continue reading

Сравнение производительности Nginx и Lighttpd

Сделали ради интереса небольшой тест производительности двух легких и быстрых вебсерверов (nginx и lighttpd).

Результаты

Результаты по скорости примерно одинаковы. На конфиге по умолчанию лайти немного проигрывал nginx’у и на больших и на маленьких файлах. После отключения лишних модулей и добавления пары опций (см. конфиг вверху страницы) лайти на небольших файлах начал выигрывать.

Пример работы программы ab -c 10 -n 100000 http://127.0.0.1/test_ind.html -

nginx маленький html файл выдал 28488.55 запросов в секунду.

А лайти, — lighttpd маленький html файл выдал 29411.67 запросов в секунду.

После проведения серии тестов (каждый тест мы запускали 3 раза и брали среднее арифметическое значение), были получены следующие результаты:

Как видно из таблицы nginx немного выигрывает на больших файлах а лайти на маленьких. ИМХО, разница в скорости совершенно несущественна. Поэтому выбор веб-сервера для статики (или проксирования) следует делать из других соображений. Мы используем оба веб-сервера и особых нареканий нет ни к тому ни к другому. К плюсам nginx стоит отнести более активную разработку и немного меньшую нагрузку на процессор при проведении тестов.

 continue reading