web-dev-qa-db-ja.com

Python=呼び出しが高価な場合の単一責任原則(SRP)の使用

いくつかの基点:

  • Pythonメソッド呼び出しは、その解釈された性質により「高価」です 。理論的には、コードが十分に単純な場合、Pythonコードを分解すると、読みやすさと再利用に加えて悪影響があります()これは、開発者にとって大きな利益であり、ユーザー)。
  • 単一責任原則(SRP)はコードを読み取り可能に保ち、テストと保守が容易です。
  • プロジェクトには、読み取り可能なコード、テスト、および時間パフォーマンスが必要な特別な背景があります。

たとえば、いくつかのメソッド(x4)を呼び出すこのようなコードは、次の1つのメソッドよりも遅くなります。

from operator import add

class Vector:
    def __init__(self,list_of_3):
        self.coordinates = list_of_3

    def move(self,movement):
        self.coordinates = list( map(add, self.coordinates, movement))
        return self.coordinates

    def revert(self):
        self.coordinates = self.coordinates[::-1]
        return self.coordinates

    def get_coordinates(self):
        return self.coordinates

## Operation with one vector
vec3 = Vector([1,2,3])
vec3.move([1,1,1])
vec3.revert()
vec3.get_coordinates()

これと比較して:

from operator import add

def move_and_revert_and_return(vector,movement):
    return list( map(add, vector, movement) )[::-1]

move_and_revert_and_return([1,2,3],[1,1,1])

そのようなものを並列化しようとすると、パフォーマンスを失うことはかなり客観的です。これは単なる例です。私のプロジェクトには、そのような数学を使用したいくつかのミニルーチンがあります-作業ははるかに簡単ですが、プロファイラーはそれを嫌っています。


固有の実装が直接影響するため、Pythonのパフォーマンスを損なうことなくSRPをどのように、どこで採用するのですか?

何かをリリースのためにインライン化する何らかのプリプロセッサのような回避策はありますか?

またはPythonは単にコードの内訳を完全に処理するのが単に悪いですか?

12
lucasgcb

Pythonは、コードの内訳を完全に処理するだけでは不十分ですか?

残念ながら、はいPythonは遅く、関数をインライン化してコードを醜くすることでパフォーマンスを大幅に向上させるという逸話がたくさんあります。

Pythonのコンパイル済みバージョンであり、はるかに高速なCythonという回避策があります。

-編集私はコメントやその他の回答のいくつかを取り上げたかっただけです。それらの推力はおそらくpython特定ではありませんが、より一般的な最適化ですが。

  1. 問題が発生するまで最適化せず、ボトルネックを探す

    一般的に良いアドバイス。しかし、仮定は、「通常の」コードは通常、高性能であるということです。これは常にそうであるとは限りません。個々の言語とフレームワークにはそれぞれ独自の特異性があります。この場合、関数呼び出し。

  2. ほんの数ミリ秒ですが、他のものは遅くなります

    強力なデスクトップコンピューターでコードを実行している場合は、シングルユーザーコードが数秒で実行される限り、気にしないでください。

    しかし、ビジネスコードは複数のユーザーに対して実行される傾向があり、負荷をサポートするには複数のマシンが必要です。コードが2倍の速度で実行される場合、ユーザー数は2倍、マシン数は半分になります。

    マシンとデータセンターを所有している場合、通常、CPUパワーのオーバーヘッドの大きなチャンクがあります。コードの実行が少し遅い場合は、少なくとも2台目のマシンを購入する必要があるまで、コードを吸収できます。

    必要な計算能力のみを使用し、それ以上は使用しない今日のクラウドコンピューティングでは、非パフォーマンスコードに直接的なコストがかかります。

    パフォーマンスの向上は、クラウドベースのビジネスの主要な費用を大幅に削減することができ、パフォーマンスは真に前倒しでなければなりません。

17
Ewan

多くの潜在的なパフォーマンスの懸念は実際には実際には問題ではありません。あなたが提起する問題はそれらの1つかもしれません。自国語では、それらが実際の問題であることを証明せずにそれらの問題について心配することを呼びます時期尚早な最適化

Webサービスのフロントエンドを作成している場合、ネットワーク経由でデータを送信するコストはメソッド呼び出しにかかる時間をはるかに超えるため、パフォーマンスは関数呼び出しの影響をあまり受けません。

ビデオ画面を毎秒60回更新するタイトなループを作成している場合は、問題になる可能性があります。しかし、その時点で、Pythonを使用しようとすると、より大きな問題が発生すると主張します。Python -適合。

いつものように、見つける方法はmeasure。パフォーマンスプロファイラーまたはいくつかのタイマーをコードで実行します。それが実際に問題であるかどうかを確認してください。


単一責任原則は法律または義務ではありません。それはガイドラインまたは原則です。ソフトウェア設計は常にトレードオフについてです。絶対的なものはありません。読みやすさや保守性をスピードとトレードオフすることは珍しいことではないため、パフォーマンスの祭壇でSRPを犠牲にする必要があるかもしれません。ただし、パフォーマンスに問題がある知っているでない限り、このトレードオフを行わないでください。

50
Robert Harvey

まず、いくつかの明確化:Pythonは言語です。Python言語で記述されたコードを実行できるいくつかの異なるインタープリターがあります。参照実装(CPython)は通常、誰かが「Python」について話すとき、それは実装であるかのように参照されますが、パフォーマンス特性について話すときは、実装間で大きく異なる可能性があるため、正確であることが重要です。

Pythonのパフォーマンスを損なうことなく、SRPをどのように、どこで採用しますか?その固有の実装が直接、SRPに影響を与えますか?

ケース1。)純粋なPythonコード(<= Python言語バージョン3.5、3.6には、純粋なPython=モジュールにのみ依存する「ベータレベルのサポート」があります。SRPをあらゆる場所で採用し、PyPyを使用して実行できます。PyPy( https:/ /morepypy.blogspot.com/2019/03/pypy-v71-released-now-uses-utf-8.html )はPythonジャストインタイムコンパイラを備えたインタプリタです(JIT)実行されたコードを追跡して「ウォームアップ」するのに十分な時間があれば(数秒IIRC)、関数呼び出しのオーバーヘッドを削除できます。**

CPythonインタープリターの使用に制限されている場合は、遅い関数をCで記述された拡張機能に抽出できます。これはプリコンパイルされ、インタープリターのオーバーヘッドの影響を受けません。どこでもSRPを使用できますが、コードはPythonとCの間で分割されます。これは、SRPを選択的に破棄するよりも保守性が良いか悪いか、Pythonコードはチームによって異なりますが、コードのパフォーマンスクリティカルセクションがある場合、CPythonによって解釈される最も最適化された純粋なPythonコードよりも間違いなく高速になります。Pythonの多くの最速のコード数学ライブラリはこの方法を使用します(numpyおよびscipy IIRC)。これは、ケース2の素敵なセグエです...

ケース2。)Python C拡張機能を使用するコード(またはC拡張機能を使用するライブラリに依存する)がある場合) 、PyPyは、それらがどのように記述されているかに応じて、役立つ場合とそうでない場合があります。詳細については http://doc.pypy.org/en/latest/extending.html を参照してください。 CTypesが遅い間、オーバーヘッドは最小限です(PyPyで使用すると、CPythonよりもさらに遅くなる場合があります)

Cython( https://cython.org/ )は、私があまり経験がない別のオプションです。私は完全を期すためにそれについて言及しているので、私の答えは「それ自体で成り立つ」ことができますが、専門知識を主張することはありません。私の限られた使用法から、PyPyで「無料で」得ることができるのと同じ速度の向上を得るためにもっと努力しなければならなかったように感じました、そして私がPyPyより良い何かを必要とするなら、私自身のC拡張を書くのと同じくらい簡単でした(これは、コードを他の場所で再利用したり、その一部をライブラリに抽出したりする場合に利点があります。すべてのコードは、Pythonインタープリターの下で実行でき、Cythonで実行する必要はありません) 。

Cythonに「ロックイン」されるのが怖いですが、PyPy用に作成されたコードはすべてCPythonでも実行できます。

**本番環境でのPyPyに関する追加の注意事項

大規模なコードベースでPyPyに「ロックイン」する実際的な効果がある選択を行う場合は、十分に注意してください。一部の(非常に人気があり有用な)サードパーティライブラリは、前述の理由でニースを再生しないため、これらのライブラリの1つが必要であるとわかった場合、後で非常に難しい決定を引き起こす可能性があります。私の経験は、主にPyPyを使用して、本番環境にごくわずかな複雑さを加える企業環境でパフォーマンスに敏感な一部(すべてではない)のマイクロサービスを高速化することです(すでに複数の言語がデプロイされており、一部は2.7や3.5とにかく実行する)。

PyPyとCPythonの両方を使用すると、言語仕様自体による保証にのみ依存し、いつでも変更される可能性のある実装の詳細に依存しないコードを書くことを余儀なくされました。あなたはそのような詳細について余分な負担であると考えるかもしれませんが、私はそれが私の専門能力開発において貴重であると思いました、そして私はそれがPythonエコシステム全体として「健康」であると思います。

2
Steven Jackson