スクリーン言語の最適化 link

Ren'Py は様々な技術でスクリーン言語の速度を最適化しています。 Ren'Py でシミュレーションゲームのような複雑なインターフェースを作成するなら、スクリーン言語の動作を理解することは最大のパフォーマンスを得る訳にたつでしょう。

このガイドは Ren'Py 6.18 から追加されたスクリーン言語の第二実装に当てはまります。 Ren'Py 6.17 以前で作成されたゲームでは、ランチャーから "Force Recompile" を選んでスクリーンを最新バージョンに更新する必要があります。

このガイドはプログラミングの練習には向きません。スクリーンがネストされたループを使用して非生産敵な作業をしているなら、スクリーンがそのような作業をしている場合と比べて遅くなるでしょう。このガイドのテクニックを理解することは重要です。

引数リスト link

最適な処理のために、すべてのスクリーンには引数リストが定義されるべきです。スクリーンが引数を取らないなら空の引数リストで定義すべきです。

screen test():
    vbox:
        for i in range(10):
            text "[i]"

上のスクリーンは下のスクリーンより高速です。

screen test:
    vbox:
        for i in range(10):
            text "[i]"

スクリーンが引数リストなしで定義されると、そのスクリーン内で使用されたどの名前もスクリーン表示時に再定義される可能性があります。このためそのスクリーンを Ren'Py が分析するときにより保守的であることが要求され、そのパフォーマンス最適化が制限されるかもしれません。

予測 link

スクリーンは前もって予測されるとパフォーマンスが向上します。これはスクリーン予測中にそのスクリーンを実行し、そのスクリーンで使用された画像をロードするためです。

スクリーンを自動的に予測する 2 つの方法が Ren'Py にはあります。 :

  • show screencall screen ステートメントで表示されるスクリーンを Ren'Py は予測します。

  • Show()ShowMenu() アクションで表示されるスクリーンを Ren'Py は予測します。

If screens are shown from Python, it's a good idea to start predicting the screen before it is shown. To start predicting a screen, use the renpy.start_predict_screen() function. To stop predicting a screen, use the renpy.stop_predict_screen() function.

Displayable の再利用 link

displayable を作成するスクリーン言語のステートメントを評価するとき、 Ren'Py はその displayable に指定された位置引数とプロパティーが、最後にそのステートメントが評価されたときに指定された位置引数とプロパティーと等しいか確認します。もしそうなら新しい displayable を作成する代わりに既存の displayable を Ren'Py は使用します。

displayable の再利用はパフォーマンスと多いに関連します。新しい displayable 作成のコスト節約は、多くの内部状態を持つ displayable に対して特に効果的です。さらに重要なことは displayable を再利用する場合、たいていは displayable を再レンダリングしてユーザーに表示する必要がなくなり、さらなる速度向上に繋がります。

位置引数とプロパティーを比較するため、 Ren'Py は python の == 演算子による等式の概念を使用します。 2 つのアクションが互いに見分けられないとき、どちらのアクションが使用されるか、選択または無効状態かが問題ではないときは等価であると判断して、この等式の概念をアクションにまで拡張しました。

Ren'Py から提供されるすべてのアクションはこの定義に従います。自身でアクションを定義するときは、この等式の概念を用意するとよいです。これは適切な __eq__ メソッドを提供して実現出来ます。例えば

class TargetShip(Action):
    def __init__(self, ship):
        self.ship = ship

    def __eq__(self, other):
        if not isinstance(other, TargetShip):
            return False

        return self.ship is other.ship

    def __call__(self):
        global target
        target = self.ship

__eq__ 関数は注意深く定義して、 (==) と (is) を適切に使用し、すべてのフィールドを比較しているか確認してください。

const 式と pure 関数 link

Ren'Py は const 変数と pure 関数を活用して、スクリーンの評価を高速化し、スクリーンの一部の評価を完全に省略出来ます。

定義 link

式が const であるとはいつ評価されても常に同じ値を表わすということです。 Ren'Py においては、以下の式の評価が常に同じ const 変数になるか、未定義であるということになります。 :

  • 単項、二項、三項演算子のその式への適用。提供される他の演算対象も const である。

  • その式でアクセスするフィールド

  • 数字かオブジェクトを使用したその式の索引

Python の数字と文字列は const で、すべての要素が const である list と tuple, set, dict も同様に const です。 Ren'Py は define ステートメントを使用して const として定義されて変数をマークします。 renpy.const()renpy.not_const() 関数を使用すれば Ren'Py が何を const として制御するかをさらに制御出来ます。デフォルトの const 名のリストが後述の Const 名 にあります。

けして変更されない変数があるなら、 define を使用してそれを定義するとよいです。例

define GRID_WIDTH = 20
define GRID_HEIGHT = 10

呼び出し可能な 関数やクラス、アクションは、そのすべての引数が const 値であるとき、常に同じ値を返すなら pure です。 const 式を引数に pure 関数を使用する式も const 式です。

多くのデフォルトの関数やクラス、アクションが pure としてマークされています。これらの関数は後述する Pure 名 でリストされています。

Functions are declared pure using the renpy.pure() function, which can be used as a decorator for functions declared in the default store.

const 式と pure 関数は以下のイベントでは同じ値を維持する必要はありません。 :

  • 初期化の終了

  • 言語の変更

  • スタイルの再ビルド

const のスクリーン言語最適化効果 link

スクリーン言語の引数とプロパティーが const だと保証することには 3 つの利点があります。

まず、初期化終了時やスクリーンが準備されるとき、言語変更時、スタイルの再ビルド時に const 引数とプロパティーは評価されます。その後はもう const 引数やプロパティーを評価するために時間を消費する必要はありません。

第 2 に displayable の再利用に const は最適です。その displayable のすべての引数とプロパティーが const であると、その displayable は常に再利用され、 displayable 再利用の利益が得られます。

最後に、すべての引数とプロパティーが const であり、制御に影響を与える式も const であるような displayable のツリー Ren'Py が発見すると、 Ren'Py は displayable の評価も作成もせずにツリーをまるごと再利用します。これは明らかなパフォーマンス向上に寄与します。

For example, the following screen does not execute any Python or create any displayables after the first time it is predicted or shown:

screen mood_picker():
    hbox:
        xalign 1.0
        yalign 0.0

        textbutton "Happy" action SetVariable("mood", "happy")
        textbutton "Sad" action SetVariable("mood", "sad")
        textbutton "Angry" action SetVariable("mood", "angry")

const テキスト link

テキストを定義するときは、新スタイルの補完を使用している文字列は const であることに注意してください。

$ t = "Hello, world."
text "[t]"

テキストの変数を直接与えると一般的には非 const になります。

$ t = "Hello, world."
text t

% による補完でも同様です。

$ t = "Hello, world."
text "%s" % t

最後に、 _ テキスト関数は pure であるため、文字列を含むと式全体が const になります。

text _("Your score is: [score]")

Const 関数 link

renpy.const(name) link

store の変数を const と宣言します。

変数はその値や、それを索引するかまたはそのアトリビュートにアクセスして得られる値が変更不可能ならば constant です。変数は define, init, translate python ブロック以外では変更してはいけません。

name

const と宣言する変数の名前の文字列です。

renpy.not_const(name) link

store の変数を非 const と宣言します。

renpy.const()renpy.pure() 呼び出しの影響を戻します。

name

非 const と宣言する変数の名前です。

renpy.pure(fn) link

pure として宣言する関数です。define, init, translate python ブロックを除いて、 pure 関数は同じ引数で呼び出されたときは常に同じ値を返すべきです。

fn

pure として宣言する関数の名前です。これは関数名の文字列か、関数自身です。

fn を返し、この関数はデコレーターとして使用出来ます。

プロファイリング link

Ren'Py は renpy.profile_screen 関数を使用してスクリーンプロファイリングの実行をサポートしています。

renpy.profile_screen(name, predict=False, show=False, update=False, request=False, time=False, debug=False, const=False) link

name を名前とするスクリーンに対してスクリーンプロファイリングをリクエストします。

name 以外のすべての引数はキーワード引数として与えられます。この関数は 3 グループの引数を取ります。

引数の最初のグループは何時プロファイリングするかを決定します。

predict

True なら、スクリーンが予測されるとプロファイリングを実行します。

show

True なら、スクリーンが最初に表示されるとプロファイリングを実行します。

update

True なら、スクリーンが更新されるとプロファイリングを実行します。

request

True なら、 F8 でリクエストされるとプロファイリングを実行します。

引数の第二グループは何をプロファイリングで出力するかを制御します。

time

True なら、スクリーンを制御するのにかかった時間を記録します。

debug

True なら、以下のどの項目についてどのようにスクリーンが評価されたかを記録します。 :

  • どの displayable を Ren'Py は constant と評価したか。

  • あるならばどの引数が評価を必要としたか。

  • どの displayable が再利用されたか。

このデバッグ情報の生成と保存には時間がかかるため、debug が設定されているなら time の情報はあてになりません。

引数の最後のグループは Ren'Py 実行毎になにを出力するか制御します。

const

const と non-const とマークされたそのスクリーンの変数を表示します。

すべてのプロファイリング結果はゲームディレクトリーの profile_screen.txt に保存されます。

const 名 link

以下の名前はデフォルトで const です。

  • False
  • None
  • True
  • config
  • style

pure 名 link

以下の名前はデフォルトで pure かつ const です。