Pycon2014 django performance
Upcoming SlideShare
Loading in...5
×
 

Pycon2014 django performance

on

  • 426 views

Djangoアプリケーションチューニング、Djangoアプリケーションのチューニング方法、負荷測定方法を紹介します。PyConJP2014での発表資料です。

Djangoアプリケーションチューニング、Djangoアプリケーションのチューニング方法、負荷測定方法を紹介します。PyConJP2014での発表資料です。

Statistics

Views

Total Views
426
Views on SlideShare
327
Embed Views
99

Actions

Likes
4
Downloads
3
Comments
0

1 Embed 99

https://twitter.com 99

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Pycon2014 django performance Pycon2014 django performance Presentation Transcript

  • Djangoアプリケーション パフォーマンスチューニング @hirokiky
  • 話すこと Djangoアプリケーション高速化 パフォーマンス測定ツール
  • 話さないこと ミドルウェアパラメータ調整 検証用データの作成方法 なんか魔法みたいに速くなる技
  • 自己紹介 @hirokiky Python Django 好き ギョームで100万ユーザーくらいのサイト Django本体への貢献
  • Github https://github.com/hirokiky/
  • Djangoアプリ高速化 SQLを吐きまくるコードは誰だ インデックス キャッシュキャッシュキャッシュ アプリケーション外
  • SQLを吐きまくるコードは誰だ ● django-debug-toolbar dbログ出力
  • django-debug-toolbar デモ https://pypi.python.org/pypi/django-debug-toolbar
  • django-debug-toolbar
  • dbログ出力
  • dbログ出力設定例 LOGGING['loggers']['django.db.backends'] = { 'level': 'DEBUG', 'handlers': ['console'] } 'console'ハンドラーは標準出力に表示する想定
  • SQLを吐きまくるコードを倒す ● .select_related/.prefetch_related .bulk_create / .update .count / .exists
  • .select_related (demo) ● FK先のデータも一緒に取ってくる 内部的にはJOINなどが走る
  • .prefetch_related (demo) ● FK元のデータも一緒に取ってくる 複数クエリを実行しPython側で結合
  • .bulk_create (demo) ● 複数のオブジェクトを一度に作成
  • .update
  • .exist - countダメ
  • その他 ● .only / .defer .values / .values_list アプリケーションが複雑化しやすい....
  • QuerySetはlazy >>> articles = Article.objects.all() >>> articles = articles.filter(title__startswith='title') >>> print(articles) >>> >>> q = articles.filter(author_id=1) >>> print(q) ここでクエリ実行 https://docs.djangoproject.com/en/1.7/topics/db/queries/#querysets-are-lazy
  • ここまでのまとめ ● ORMが実行するSQLを知ろう ORMの特性を意識しよう 他にも: https://docs.djangoproject.com/en/1.7/topics/db/optimization/
  • インデックス ● 適切なインデックスを使おう 結局相手にしてるのはRDB
  • インデックス 1) 吐かれてるSQLをみて適応してく 2) インデックスがかかるクエリに変更
  • 吐かれるクエリは? 検証環境などにデータたっぷりいれて 画面をポチポチします JetProfilerなどがツールも優秀です
  • JetProfiler for MySQL http://www.jetprofiler.com/tour/
  • インデックスの貼り方 ここでは話しません
  • インデックスがかかるクエリにする .extra: クエリの一部分を生SQLで書く .raw: クエリを生SQLで書く 複雑化しやすいのでキャッシュとの兼ね合いです
  • ここまでのまとめ ● クエリを眺めてインデックス適応 好みのクエリを走るようにする あとそもそもテーブルの設計ちゃんとしましょう
  • キャッシュキャッシュキャッシュ キャッシュの種類と使いどころ Redisでのキャッシュ
  • キャッシュの種類 レスポンスキャッシュ ビューキャッシュ テンプレートキャッシュ オブジェクトキャッシュ 効果的 https://docs.djangoproject.com/en/1.7/topics/cache/
  • テンプレートキャッシュ {% load cache %} {% cache 500 sidebar %} .. sidebar .. {% endcache %} https://docs.djangoproject.com/en/1.7/topics/cache/
  • キャッシュの使いどころ ユーザーに依存する表示は基本キャッシュ無理 画面設計段階でどこキャッシュできるか考える
  • Redisでキャッシュ Redisならではの型を有効利用: * Set型でユニークユーザーの管理 * SortedSet型でランキング http://redis.io/
  • まとめ ユーザーに近いほどキャッシュは有効 あまり複雑化しないように設計
  • アプリケーション外 セッションバックエンド変更 静的ファイル圧縮 DBのPrimary/Replica構成
  • セッションバックエンド変更 Cacheバックエンド Redisのバックエンド
  • Redisバックエンド $ pip install django-redis-sessions SESSION_ENGINE = 'redis_sessions.session' https://pypi.python.org/pypi/django-redis-sessions
  • 静的ファイル圧縮 django-compressor か django-asset
  • django-compressor {% load compress %} {% compress css %} <link rel="stylesheet" href="/static/css/one.css" type="text/css"> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/static/css/two.css" type="text/css"> {% endcompress %} http://django-compressor.readthedocs.org/en/latest/
  • DBのMaster/Slave django-replicatedが便利 レプリ遅延にも賢く対応
  • django-replicated $ pip install django-replicated DATABASES = {'default': {...}, 'slave1': {...}} DATABASE_SLAVES = ['slave1'] DATABASE_ROUTERS = ['django_replicated.ReplicationRouter'] 更新が master, 参照が slave になります https://github.com/yandex/django_replicated
  • レプリ遅延対策 MIDDLEWARE_CLASSES = [ ... 'django_replicated.middleware.ReplicationMiddleware', ] GET, HEADで slave, それ以外で master https://github.com/yandex/django_replicated
  • レプリ遅延対策 2 from django_replicated.decorators import use_master, use_slave @use_master def my_view(request, ...): # GETで更新&参照するViewなんだぜ。。。 Viewに強制指定 https://github.com/yandex/django_replicated
  • まとめ ORMの使い方は基本としてマスター インデックス+キャッシュのバランス まんべんなくやっとくのが吉です
  • Funkloadでパフォーマンス測定 負荷試験ツール (Pythonで書く) セッション付きのシナリオ 静的ファイルの自動取得などリッチ https://funkload.nuxeo.org/
  • Funkload (テストシナリオ) 1) 一覧画面 2) 詳細画面 3) 編集画面 4) 更新 5) 詳細画面
  • Funkload (demo) $ fl-run-test test_Wiki.py $ fl-run-bench test_Wiki TestWiki.test_update
  • Funkload 一覧画面
  • Funkload 詳細画面
  • Funkload 編集画面
  • Funkload 更新
  • Funkload 詳細画面
  • Funkload レポートビルド $ fl-run-test test_Wiki.py $ fl-run-bench test_Wiki TestWiki.test_update
  • レポートその他 2レポート間の差分レポート 複数レポートでのトレンドレポート
  • 耐えるべき負荷は? アクティブユーザー10万人、1日100万PV ピーク時でその3倍として秒間34PV 人間1人5秒/1ページとして同時接続数170 このあたり模索中で良い方法などあれば教えてください
  • ここまでのまとめ FunkloadはPythonで書ける シナリオでかけるので信頼できる
  • 全体まとめ ORMの扱いなどは当たり前にやっておく 面倒、複雑なものは測定しつつ必要な分やる
  • 感想 カッコいいこと言っても結局 設計とミドルウェアが重要 どううまく使うかを考えましょう
  • 出会い系 オフィスアワー(会議室4/5)に13:15〜 Sprint(3日目)
  • @hirokiky