Flask-Cache и что я еще кэширую в бложике

November 20, 2014

Current Status

Блог все еще запущен на отладочном wsgi сервере встроенном во flask, но я наперед закладываю оптимизацию, почему? А почему бы и нет.

Оптимизация фронтенда

Таски из Gruntfile.js для фронтенда

 
            less: {
            dist: {
                'files': {
                  'pro/static/css/style.min.css': ['pro/static/less/style.less']
                },
                'options': {
                  compress: true,
                  cleancss: false,
                  sourceMap: false
                }
              } // distfiles: {
        }, //less
         concat: {
              js: {
                src: [
                                'pro/static/js/jquery.js',
                                'pro/static/js/bootstrap.min.js',        
'pro/static/js/highlight.js', 'pro/static/js/modernizr.js', 'pro/static/js/svg.js'], dest: 'pro/static/js/app.js', }, css: { src: [ 'pro/static/css/bootstrap.min.css', 'pro/static/css/style.min.css', 'pro/static/css/highlight.css'], dest: 'pro/static/css/app.min.css', } }, uglify: { dist: { files: { 'pro/static/js/app.min.js': ['pro/static/js/app.js'] } } }, svg2string: { elements: { files: { 'pro/static/js/svg.js': [ 'pro/static/img/set.svg' ] } } }, autoprefixer: { options: { browsers: ['last 6 version', 'ie 8', 'ie 9'] }, // prefix the specified file single_file: { src: 'pro/static/css/style.min.css', dest: 'pro/static/css/style.min.css', } /// ... /// grunt.registerTask('build', ['less','autoprefixer','svg2string','concat','uglify']);

$ grunt build

На выходе получаем два файла app.min.css и app.min.js


Вся статика лежит в /static/ поэтому ее можно кэшировать на уровне nginx


  location /static/ {
    expires 24h;
    root /home/loki/www/gunlinux.org/pro/;
    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
}

Кэширование Flask

Кэшированием во flask занимается модуль Flask-Cache, для тестирования создал достаточно большой пост, так как все посты у меня в markdown разметке и у постов бывают тэги, то это целых два sql запроса, которые потом надо рендерить

Простейший пример использования Flask-Cache


from flask import Flask
from flask.ext.cache import Cache

app = Flask(__name__)
# Check Configuring Flask-Cache section for more details
cache = Cache(app,config={'CACHE_TYPE': 'simple'})


#### И вешаем декоратор на вьюшку
@app.route('<alias>')
@cache.cached(timeout=50)
def post(alias=None):



Для тестов я создал большой и достаточно сложный в плане разметки пост и замерил скорость генерации шаблона через flask-debugtoolbar

 
  
# Тестовый роут с кэшированием
@app.route('<alias>')
@cache.cached(timeout=50)
def post(alias=None):
    post = Post.query.filter(Post.alias == alias).filter(
        Post.published > 0).first()
    if not post:
        abort(404)
    return render_template('post.html', post=post)

# Эталлоный роут
@app.route('<alias>')
def post_c(alias=None):
    post = Post.query.filter(Post.alias == alias).filter(
        Post.published > 0).first()
    if not post:
        abort(404)
    return render_template('post.html', post=post)
  

При таком самом деревянном способе, без кэширования orm запросов и функции затрачиваемое процессорное время снизилось с 1200-1800 до 0.67 в дебаг режиме под присмотром debugpanel. После первого кэширования разумеется, создание которого занимает примерно столько же времени, как и генерация шаблона на лету.

Результаты http://www.webpagetest.org/ в режиме 3g.

Ссылки

One line of code cut our Flask page load times by 60% Flask-debugtoolbar Flask-Cache Grunt