Pythonの高速化

高洛峰
リリース: 2016-10-19 13:25:12
オリジナル
1160 人が閲覧しました

もともと、私は Web ページのパフォーマンスをより良く最適化する方法を知りませんでした。そして最近、Python と PHP で同様の Web ページのレンダリング速度を比較していたときに、これまで発見したことのない非常に単純で馬鹿げた方法を偶然発見しました。私は自分自身を観察する必要があります): Discuz フォーラムなどの一部の PHP アプリケーションと同様に、生成された Web ページに「このページが何秒生成されたか」を出力し、テストのために Web ページにアクセスし続けると、直感的にどのような操作でボトルネックが発生するのか、ボトルネックを解決する方法を調べます。

そこで、SimpleCD がホームページを生成すると、予想外に約 0.2 秒かかったことがわかりました。これは本当に耐え難いものでした。Discuz フォーラムのホームページの平均的な生成に比べて、かかる時間はわずか 0.02 秒で、Discuz フォーラムのホームページは間違いなくはるかに長いものです。 SimpleCD のホームページよりも複雑です。このギャップは Python 言語によって引き起こされたものではなく、Discuz プログラムが適切に最適化されているとしか言えません。


実際、ホームページを生成するときに、SimpleCD は 3 つの SQLite データベースで 42 を超えるクエリを実行する必要があることは、分析しなくてもわかります。これは、歴史的な理由により非常に非効率な設計です。 ; しかし、これ 40 を超えるクエリのうち、ほとんどは実際には非常に高速なクエリであり、パフォーマンスが優れているクエリが 2 つあり、その他は遅くありません。

最初の大きな操作は次のとおりです: データの数を取得します

SELECT count(*) FROM Verycd

この操作には毎回時間がかかります。毎回データベースをロックする必要があり、主キーの統計が更新されるためです。データの数が多いため、かかる時間は O(N) であり、N はデータベースのサイズになります。この問題を解決するには、現在のデータ数を任意の場所に保存するだけです。データの追加または削除時に変更を加えるだけなので、時間は O(1) です

2 番目の大きな問題は、最新の更新された 20 個のデータ リストを取得する

SELECT です。 title,brief,updtime FROM Verycd

ORDER BY updtime DESC LIMIT 20;

インデックスは updtime に実行されるため、実際のクエリ時間は実際にはインデックスの検索時間になります。しかし、なぜこの操作は遅いのでしょうか?データは公開時間に従って挿入されているため、更新時間に従って表示すると、少なくとも 20 か所で I/O を実行する必要があり、遅くなります。解決策は、I/O を 1 か所で実行できるようにすることです。つまり、新しいデータがデータベースに追加されない限り、または元のデータが変更されない限り、このステートメントの戻り結果はキャッシュされます。これは 20 倍高速です:)

次は 20 の小さなケースです: パブリッシャーとクリック数の情報を取得します

SELECT owner FROM LOCK WHERE id=XXXX;

SELECT ヒット FROM stat WHERE id=XXXX;ここで使用されている SQL 結合ステートメントは、トラブルを避けるために使用されているのではありませんか?アーキテクチャ上の理由により、これらのデータは別のデータベースに配置されます。Stat は頻繁に挿入する必要があるため、mysql に保存されます。 mysql の悲劇的なインデックスの使用法。ページング効率の関係で sqlite3 データベースに保存されているため、結合できません -.-

つまり、先ほどの解決策と同様に、すべてがキャッシュされます

ということです。私の例を見ると、Web ページのパフォーマンスの最適化は一言で言えば、データベース クエリをキャッシュするだけです。ほとんどの Web アプリケーションは次のようなものだと思います:)

いよいよ memcached の番です。キャッシュする予定なので、キャッシュにファイルを使用する場合は、引き続きディスク I/O が発生します。メモリ I/O が大幅に高速になります。つまり、memcached はその名前が示すとおり、まさにそれです。

memcached は、分散共有メモリ キャッシュをサポートできるため、非常に強力なツールです。小規模なサイトでは、メモリに余裕がある限り、ホームページに必要なメモリ バッファも使用できます。サイズは 10K を超えないと推定されています。言うまでもなく、私は現在メモリ王でもありますが、それでもこれを気にする必要がありますか?

設定と操作: スタンドアロンマシンなので設定するものは何もありません。

vi /etc/memcached.conf

/etc/init.d/memcached restart



Python Web アプリケーションでは

import memcache

mc = memcache.Client(['127.0.0.1:11211'], debug=0) を使用します



memcache は実際にはマップ構造であり、最も一般的に使用されるのは次の 2 つです。関数:

1 つ目は set(key, value, timeout) で、キーを値にマッピングするのが非常に簡単です。タイムアウトはマッピングが無効になったときを指します。2 つ目は get(key) 関数で、値を返します。キーで指定されています

通常の SQL クエリに対してこれを行うことができます

sql = 'select count(*) from Verycd'

c = sqlite3.connect('verycd.db').cursor()



# 独自の処理メソッド

c.execute(sql)

count = c.fetchone()[0]



# 現在の処理メソッド

from hashlib import md5

key=md5(sql)

count = mc.get(key)

if not count:

c. execute(sql)

count = c.fetchone()[0]

mc.set(key,count,60*5) #5 分間保存します

ここで、md5 はキーの配布をより均一にするためのもので、その他はコードは非常に直感的なので説明は省略します。


ステートメント 1 とステートメント 2 を最適化した後、ホームページの平均生成時間は 0.02 秒に短縮され、これはステートメント 3 を最適化した後の discuz と同じ桁数であり、最終的な結果はホームです。 memcached コードを数行最適化しただけで、ページの生成時間が約 0.006 秒に短縮され、パフォーマンスが 3300% 向上しました。やっと背筋を伸ばしてDiscuzを見ることができます


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート