cast_off 0.3.7 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +81 -513
- data/README.ja +177 -0
- data/bin/cast_off +12 -37
- data/cast_off.gemspec +6 -3
- data/ext/cast_off/cast_off.c.rb +186 -116
- data/ext/cast_off/generated_c_include/inline_api.h +0 -165
- data/ext/cast_off/generated_c_include/unbox_api.h.rb +1 -1
- data/lib/cast_off.rb +1 -0
- data/lib/cast_off/compile.rb +150 -208
- data/lib/cast_off/compile/code_manager.rb +0 -49
- data/lib/cast_off/compile/configuration.rb +8 -8
- data/lib/cast_off/compile/hook_invocation.rb +1 -0
- data/lib/cast_off/compile/ir/call_ir.rb +21 -13
- data/lib/cast_off/compile/translator.rb +6 -7
- data/lib/cast_off/suggestion.rb +1 -1
- metadata +10 -12
- data/README.en +0 -228
data/README
CHANGED
@@ -1,565 +1,133 @@
|
|
1
|
-
*
|
2
|
-
|
3
|
-
CastOff
|
4
|
-
|
5
|
-
|
6
|
-
対象となるメソッドを高速化することができます。
|
7
|
-
本 README では、CastOff の基本機能について紹介します。
|
8
|
-
ご質問、ご要望等があれば、shiba@rvm.jp もしくは
|
9
|
-
http://github.com/soba1104/CastOff/issues まで、ご連絡ください。
|
1
|
+
* About CastOff
|
2
|
+
CastOff is a compiler for Ruby1.9.3.
|
3
|
+
CastOff compiles Ruby method (method written in Ruby) into C extension (method written in C)
|
4
|
+
CastOff can reduce Ruby virtual machine overhead, so by use of CastOff,
|
5
|
+
the performance of compilation target method can improve.
|
10
6
|
|
7
|
+
This README document introduce basic functionality of CastOff.
|
8
|
+
If you have any questions, comments, or suggestions please send email to shiba@rvm.jp,
|
9
|
+
or use http://github.com/soba1104/CastOff/issues.
|
11
10
|
|
12
11
|
|
13
|
-
* ライセンス
|
14
|
-
Ruby 処理系のライセンスに従います。
|
15
12
|
|
13
|
+
* License
|
14
|
+
Same as the license of Ruby runtime.
|
16
15
|
|
17
16
|
|
18
|
-
|
17
|
+
|
18
|
+
* Installation
|
19
19
|
$gem install cast_off
|
20
20
|
|
21
|
-
|
22
|
-
このため、gem コマンド経由で容易にインストールすることができます。
|
23
|
-
ただし、脱最適化などの処理が処理系の実装依存になっているため、Ruby 1.9.3 のみの対応となっています。
|
24
|
-
一応 Ruby 1.9.2 でも動作しますが、Ruby 1.9.3 よりも不安定かもしれません。
|
25
|
-
Ruby1.9.2 と Ruby1.9.3 以外のバージョンの Ruby 処理系では動作しないため、ご注意ください。
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
* CastOff の利用における注意点
|
30
|
-
|
31
|
-
** 利用すると非互換になる機能
|
32
|
-
現状、CastOff を用いた場合、Ruby 処理系との非互換性が生じる可能性があります。
|
33
|
-
ここでは、現時点で把握できている、Ruby 処理系との非互換が生じる機能、
|
34
|
-
特にコンパイルエラーを出すことが出来ない機能について列挙します。
|
35
|
-
ここで列挙した機能を使用するプログラムやメソッドに対しては、CastOff を利用するべきではありません。
|
36
|
-
ここに列挙した機能以外で非互換になる点を発見された方は、
|
37
|
-
お手数ですが、shiba@rvm.jp もしくは http://github.com/soba1104/CastOff/issues まで、ご報告をお願い申し上げます。
|
38
|
-
|
39
|
-
-継続(Continuation)
|
40
|
-
Ruby の継続(Continuation) を用いた場合、実行コンテキストの保存に失敗することが確認できています。
|
41
|
-
継続を使用するプログラムでは、CastOff を利用しないでください。
|
42
|
-
|
43
|
-
-定数の再定義
|
44
|
-
CastOff は、コンパイルしたコードの読み込み時、もしくは最初に実行したときに定数解決を行います。
|
45
|
-
性能上の理由により、CastOff は定数解決後は常に同じ値を使いまわすため、定数の再定義に対応することができません。
|
46
|
-
定数の上書きを行うようなプログラムでは、CastOff を利用しないでください。
|
47
|
-
定数の上書きのフック、もしくは RubyVM が管理する世代番号のチェックが高速にできるようになった場合、
|
48
|
-
この非互換性は解消する予定です。
|
49
|
-
|
50
|
-
-メソッドや Proc のパラメータ取得
|
51
|
-
コンパイル済みメソッドや Proc に対する情報を取得しようとした場合、
|
52
|
-
コンパイル前と異なる挙動を示すメソッドがいくつかあります。
|
53
|
-
例えば、Method#arity や Proc#arity などの、メソッドや Proc の引数に
|
54
|
-
関する情報を取得しようとした場合、コンパイル前とコンパイル後では異なる値になります。
|
55
|
-
|
56
|
-
|
57
|
-
** 起動時間
|
58
|
-
CastOff は Ruby で実装しているので、CastOff を用いると、CastOff の読み込みというオーバヘッドが発生します。
|
59
|
-
このため、実行時間が短いプログラムに対してCastOff を利用すると、逆に遅くなる可能性があります。
|
60
|
-
|
61
|
-
また、CastOff を用いた場合、通常の require などの処理に加えて、CastOff がコンパイルしたメソッドの数だけ、コンパイル済みコードの読み込み、
|
62
|
-
および、メソッド上書きのフックなどの処理(以降、初期化処理と呼ぶ)が走ります。
|
63
|
-
コマンドラインから CastOff を利用した場合、閾値の設定次第では数多くのメソッドがコンパイルされるため、初期化処理に時間がかかります。
|
64
|
-
このため、ボトルネックとなるメソッドが分かっている場合は、スクリプトから CastOff を利用し、
|
65
|
-
コンパイル対象のメソッドを直接指定して利用した方が高速に動作します。
|
66
|
-
|
67
|
-
|
68
|
-
** コンパイル時間
|
69
|
-
CastOff は Ruby で実装しており、実装コストの兼ね合いから、コンパイル時間には配慮していません。
|
70
|
-
このため、CastOff によるコンパイルは非常に時間がかかります。
|
71
|
-
起動時間に関する注意でも述べたように、コマンドラインから CastOff を利用した場合、
|
72
|
-
閾値の設定次第では数多くのメソッドがコンパイルされます。
|
73
|
-
閾値を低く設定しすぎると、コンパイルに非常に時間がかかるという点に、ご注意ください。
|
74
|
-
|
75
|
-
また、コマンドラインから CastOff を利用する場合、対象プログラムを実行し、プロファイル情報を取得する必要があります。
|
76
|
-
このため、コンパイル対象の実行に数時間かかるようなプログラムに対しては、コマンドライン経由で CastOff を利用するべきではありません。
|
77
|
-
このようなプログラムに対しては、実行に時間がかからないような入力を与えるか、スクリプトから CastOff を利用してください。
|
78
|
-
|
79
|
-
|
80
|
-
** コンパイル済みコードの読み込み
|
81
|
-
CastOff がコンパイル済みコードを読み込むためには、コンパイルしたメソッドが定義されている必要があります。
|
82
|
-
メソッドを定義し終わるまでは、コンパイル済みコードを読み込むことはできません。
|
83
|
-
|
84
|
-
CastOff をコマンドラインから利用した場合、CastOff は、クラス定義とメソッド定義をフックし、
|
85
|
-
コンパイルしたメソッドが定義済みかどうかを確認します。
|
86
|
-
そして、コンパイルしたメソッドが定義済みだった場合、コンパイル済みコードを読み込みます。
|
87
|
-
メソッド定義のフックには、BasicObject.method_added を使用しています。
|
88
|
-
コンパイル対象のスクリプト内で method_added を使用している場合、
|
89
|
-
(特に Ruby 1.9.2 では)コンパイル済みコードが正常に読み込まれない可能性があります。
|
90
|
-
|
91
|
-
|
92
|
-
** 特異メソッドの取り扱い
|
93
|
-
CastOff は、インスタンスメソッドと特異メソッド両方のコンパイルを扱えますが、
|
94
|
-
基本的にインスタンスメソッドのコンパイルの方が得意です。
|
95
|
-
なるべく特異メソッドに対しては CastOff を使用しないことをおすすめします。
|
96
|
-
|
97
|
-
得意メソッドの取り扱いが苦手なのは、特異クラスが Marshal.dump に対応していないためです。
|
98
|
-
CastOff は、コンパイル時に扱った情報を Marshal.dump で保存し、ロード時に Marshal.load で読み込みます。
|
99
|
-
特異クラスは Marshal で取り扱うことができないため、特異クラスの情報は、
|
100
|
-
無かったものとして扱うことになります。このため、特異メソッドのコンパイルでは、
|
101
|
-
self に関する型情報を扱うことができず、(特異メソッドの self が内部的に参照するクラスは特異クラスであるため)
|
102
|
-
インスタンスメソッドのコンパイルと比較して遅くなってしまいます。
|
103
|
-
|
104
|
-
例えば、次の2つのスクリプト A, B を CastOff でコンパイルし、実行時間を比較した場合、
|
105
|
-
32bit GNU/Linux GCC4.4.1 の環境では、A の方が B よりも約3.5倍高速です。
|
106
|
-
|
107
|
-
------------------------------------------------------
|
108
|
-
# スクリプト A
|
109
|
-
class Fib
|
110
|
-
def fib n
|
111
|
-
(n < 3) ? 1 : (fib(n-1) + fib(n-2))
|
112
|
-
end
|
113
|
-
end
|
114
|
-
Fib.new.fib(40)
|
115
|
-
------------------------------------------------------
|
21
|
+
Command line tool cast_off is available after installation.
|
116
22
|
|
117
|
-
|
118
|
-
|
119
|
-
def fib n
|
120
|
-
(n < 3) ? 1 : (fib(n-1) + fib(n-2))
|
121
|
-
end
|
122
|
-
fib(40)
|
123
|
-
------------------------------------------------------
|
23
|
+
Currently, CastOff supports Ruby1.9.3 only.
|
24
|
+
So, if you attempt to use CastOff, please install CastOff under Ruby1.9.3 runtime.
|
124
25
|
|
125
26
|
|
126
|
-
* CastOff の利用方法
|
127
|
-
CastOff は Ruby のメソッドを C に変換し、高速化を実現するためのツールです。
|
128
|
-
CastOff の利用方法には、コマンドラインからの利用とスクリプトからの利用の2種類があります。
|
129
|
-
ここでは、これら2種類の利用方法について簡単に説明します。
|
130
27
|
|
28
|
+
* Attention
|
29
|
+
Currently, CastOff is alpha version. So, you must not use CastOff in critical mission.
|
131
30
|
|
132
|
-
**
|
31
|
+
** Incompatibility
|
32
|
+
-Constant redefinition
|
33
|
+
Currently, CastOff cannot handle constant re-definition.
|
34
|
+
So, you should not use CastOff to your program which re-defines constants.
|
133
35
|
|
134
|
-
|
135
|
-
CastOff
|
136
|
-
|
137
|
-
詳しくは下で解説しますが、コマンドラインからの CastOff の利用は、
|
138
|
-
次のようなコマンドを繰り返し実行することで行います。
|
36
|
+
-Continuation
|
37
|
+
CastOff causes problem about capture of continuation (callcc).
|
38
|
+
So, you should not use CastOff to your program which uses Continuation.
|
139
39
|
|
140
|
-
|
141
|
-
|
142
|
-
|
40
|
+
-Built-in functions related with Method and Proc
|
41
|
+
CastOff compiles Ruby method and proc into C extension.
|
42
|
+
So, built-in functions related with Method and Proc (such as Method#arity, Proc#arity)
|
43
|
+
return different values.
|
143
44
|
|
144
|
-
|
45
|
+
# example
|
46
|
+
class Foo
|
47
|
+
def foo(a, b = :b, *c); end
|
48
|
+
end
|
49
|
+
f = Foo.new
|
50
|
+
puts (f.method(:foo).arity) # => -2
|
51
|
+
CastOff.compile(Foo, :foo)
|
52
|
+
puts (f.method(:foo).arity) # => -1
|
145
53
|
|
146
|
-
$ruby foo.rb bar
|
147
54
|
|
148
|
-
|
149
|
-
|
55
|
+
** Startup time
|
56
|
+
When you use CastOff, you pay following extra overhead.
|
57
|
+
So, you should not use CastOff to your program which takes very small execution time.
|
150
58
|
|
151
|
-
|
59
|
+
-1: Load time of CastOff
|
60
|
+
CastOff is almost written with Ruby, so load time of CastOff takes msec order time.
|
152
61
|
|
153
|
-
|
154
|
-
|
155
|
-
2:コンパイル対象のプロファイル情報を収集し、コンパイル
|
156
|
-
この2つのステップそれぞれで対象プログラムを実行します。
|
157
|
-
このため、上の例の場合、foo.rb を、コンパイルのために2度実行します。
|
158
|
-
実行の回数は、今後、1-2の手順をまとめることで、削減する予定です。
|
62
|
+
-2: Load time of compiled codes.
|
63
|
+
When CastOff loads compiled codes, CastOff uses Marshal.load many times.
|
159
64
|
|
160
|
-
コンパイルした後は、--run オプションを用いることで、コンパイルしたコードを読み込んで動作させることができます。
|
161
|
-
上の例の場合、次のようなコマンドを実行することで、コンパイル済みコードを用いて foo.rb を実行することができます。
|
162
65
|
|
163
|
-
|
66
|
+
** Compilation time
|
67
|
+
CastOff is almost written with Ruby, so compilation time is
|
68
|
+
in seconds(when CastOff compiles simple program) or in minutes(when CastOff compiles complex program).
|
164
69
|
|
165
|
-
また、コマンドラインからの利用で注意する必要があるのは、コンパイル時とは異なる引数を用いて実行する場合の挙動です。
|
166
|
-
上の例では、コンパイル時に bar という引数を与えています。
|
167
|
-
CastOff は、bar を引数として foo.rb を実行したときのプロファイル情報を基にコンパイルを行うため、
|
168
|
-
異なる引数を与えた場合、クラス情報の不整合を起こし、例外、もしくは脱最適化を発生させる可能性があります。
|
169
70
|
|
170
|
-
|
171
|
-
|
71
|
+
|
72
|
+
* Usage
|
73
|
+
By use of command line tool cast_off, you can improve performance of your Ruby program easily.
|
74
|
+
If you want to improve performance of your Ruby program, you should execute following command repeatedly.
|
172
75
|
|
173
76
|
-----------------------------------------------------
|
174
|
-
|
175
|
-
def sample(o)
|
176
|
-
puts o.inspect
|
177
|
-
end
|
178
|
-
case ARGV.shift
|
179
|
-
when 'bar'
|
180
|
-
sample('bar')
|
181
|
-
when 'baz'
|
182
|
-
sample(:baz)
|
183
|
-
end
|
77
|
+
$cast_off PathOfTargetProgram ArgumentsOfTargetProgram
|
184
78
|
-----------------------------------------------------
|
185
79
|
|
186
|
-
|
187
|
-
|
188
|
-
そして、sample メソッドに渡されるオブジェクトが String オブジェクトであるという前提に基づいたコードを生成します。
|
189
|
-
このため、foo.rb に baz という引数を渡した場合、sample メソッドに対し、想定していなかった Symbol オブジェクトが
|
190
|
-
渡ってきてしまい、コンパイルの前提条件が崩れてしまいます。
|
191
|
-
CastOff は、コンパイルの前提条件が崩れたことを検出したときに、例外の発生、もしくは脱最適化を行います。
|
192
|
-
例外を発生させた場合は実行を継続させることができず、脱最適化を行った場合はパフォーマンスに対するペナルティが発生してしまいます。
|
193
|
-
|
194
|
-
このような場合には、
|
80
|
+
For example, when you want to improve performance of Ruby program "foo.rb"
|
81
|
+
(in this example, "foo.rb" recieves one argument "bar" or "baz"), you should execute following commands.
|
195
82
|
|
83
|
+
-----------------------------------------------------
|
196
84
|
$cast_off foo.rb bar
|
85
|
+
$cast_off foo.rb baz
|
86
|
+
-----------------------------------------------------
|
197
87
|
|
198
|
-
|
88
|
+
When you execute these commands, CastOff does followings to compile foo.rb and related libraries.
|
199
89
|
|
200
|
-
|
90
|
+
1: Executes "foo.rb" with argument "bar" to get profile information.
|
91
|
+
2: Compiles "foo.rb" and related libraries.
|
92
|
+
3: Executes "foo.rb" with argument "baz" to get and update profile information.
|
93
|
+
4: Compiles "foo.rb" and related libraries.
|
201
94
|
|
202
|
-
|
203
|
-
|
204
|
-
プロファイル情報やコンパイル結果を削除したい場合は、--clear という引数を与えて実行してください。
|
95
|
+
After CastOff finishes compilation, you can run target program with --run option.
|
96
|
+
In above example, you can run target program with compiled codes by use of following command.
|
205
97
|
|
98
|
+
$cast_off --run foo.rb bar
|
99
|
+
|
100
|
+
|
101
|
+
*** Command line arguments
|
206
102
|
|
207
|
-
|
208
|
-
cast_off [options] [programfile] [arguments]
|
103
|
+
cast_off [options] PathOfTargetProgram ArgumentsOfTargetProgram
|
209
104
|
|
210
105
|
|
211
|
-
|
106
|
+
*** Command line options
|
212
107
|
--run
|
213
|
-
|
108
|
+
Execute target program with compiled methods.
|
214
109
|
|
215
110
|
--clear
|
216
|
-
|
217
|
-
name
|
111
|
+
Clear profile information and delete compiled methods.
|
112
|
+
If you want to clear profile information and compiled methods of target name "foo",
|
113
|
+
you should execute following command.
|
218
114
|
$cast_off --clear --name=foo
|
219
115
|
|
220
116
|
--threshold=COUNT
|
221
|
-
COUNT
|
222
|
-
|
117
|
+
Compile method which is executed more than COUNT.
|
118
|
+
Default value is 100.
|
223
119
|
|
224
120
|
--name=NAME
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
に変更が無かった場合、CastOff はコンパイル済みコードを再利用します。
|
229
|
-
name オプションを使用しなかった場合、CastOff は File.basename([programfile]) の結果を名前として使用します。
|
121
|
+
Name compiled methods NAME.
|
122
|
+
This name is used for search of compiled methods.
|
123
|
+
If you don't use this option, CastOff uses File.basename([programfile]) as name.
|
230
124
|
|
231
125
|
--verbose
|
232
|
-
|
126
|
+
Show compilation progress and internal information.
|
233
127
|
|
234
128
|
-h, --help
|
235
|
-
|
129
|
+
Show help.
|
236
130
|
|
237
131
|
--version
|
238
|
-
CastOff
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
** スクリプトからの利用
|
243
|
-
|
244
|
-
*** スクリプトからの利用の流れ
|
245
|
-
CastOff をスクリプトから用いる場合、コンパイルのタイミングやコンパイル対象のメソッド、コンパイルオプションを、
|
246
|
-
CastOff に対して直接指定することができます。
|
247
|
-
詳しくは下で解説しますが、スクリプトからの CastOff の利用は、次のようなメソッドを用いて行います。
|
248
|
-
|
249
|
-
-----------------------------------------------------
|
250
|
-
CastOff.compile(クラス,メソッド名,binding,クラス情報)
|
251
|
-
-----------------------------------------------------
|
252
|
-
|
253
|
-
例えば、次のようなメソッドの実行を高速化したい場合、
|
254
|
-
|
255
|
-
-----------------------------------------------------
|
256
|
-
class Tarai
|
257
|
-
def tarai( x, y, z )
|
258
|
-
if x <= y
|
259
|
-
then y
|
260
|
-
else tarai(tarai(x-1, y, z),
|
261
|
-
tarai(y-1, z, x),
|
262
|
-
tarai(z-1, x, y))
|
263
|
-
end
|
264
|
-
end
|
265
|
-
end
|
266
|
-
-----------------------------------------------------
|
267
|
-
|
268
|
-
tarai メソッドを定義した後に、次のように記述することで、
|
269
|
-
tarai メソッドを Ruby の C 拡張にコンパイルし、
|
270
|
-
コンパイル済みの C 拡張に tarai メソッドを置き換えることができます。
|
271
|
-
|
272
|
-
-----------------------------------------------------
|
273
|
-
CastOff.compile(Tarai, :tarai, [:x, :y, :z] => Fixnum, Fixnum => {:- => Fixnum})
|
274
|
-
-----------------------------------------------------
|
275
|
-
|
276
|
-
ここでの CastOff.compile に対する引数はそれぞれ次のような意味をもっています。
|
277
|
-
第一引数: コンパイルしたいメソッドが Tarai クラスに定義されていることを指定しています。
|
278
|
-
第二引数: コンパイルしたいメソッドの名前が tarai であることを指定しています。
|
279
|
-
第三引数: コンパイル対象である Tarai#tarai メソッド内のクラス情報を指定しています。
|
280
|
-
[:x, :y, :z] => Fixnum は、ローカル変数 x, y, z が、常に Fixnum オブジェクトであることを指定しています。
|
281
|
-
Fixnum => {:- => Fixnum} は、Fixnum#- が、常に Fixnum オブジェクトを返すことを指定しています。
|
282
|
-
ローカル変数 x, y, z や Fixnum#- の返り値は Bignum オブジェクトであることも想定できますが、
|
283
|
-
たらい回し関数にそのような入力をあたえることはまず無いと判断し、常に Fixnum であることを指定しています。
|
284
|
-
このように、第三引数では、想定する用途において渡ってくるオブジェクトのみを指定します。
|
285
|
-
|
286
|
-
このように、CastOff.compile などの、CastOff へのコンパイル指定を行うメソッドを用いることで、
|
287
|
-
ボトルネックとなっているメソッドをコンパイルしていくことができます。
|
288
|
-
コマンドラインからの利用よりも、コンパイル対象やコンパイルの条件をより細かく指定できるのが、スクリプトからの利用の利点です。
|
289
|
-
|
290
|
-
コンパイルして得た C 拡張のコードは、コンパイルのための条件や、
|
291
|
-
コンパイル対象のメソッドを定義したファイルに変更が加えられていなかった場合に、自動的に再利用されます。
|
292
|
-
このため、1度コンパイルが済んだ後では、コンパイルにかかる時間を気にする必要はありません。
|
293
|
-
|
294
|
-
CastOff をスクリプトから利用するうえで強くおすすめするのは、CastOff.compile の呼び出しを、高速化したいプログラムとは別ファイルに記述するという点です。
|
295
|
-
このようにした方が、CastOff への依存を簡単に無くすことができ、CastOff によってトラブルが発生した場合の対処が容易になります。
|
296
|
-
また、コンパイル済みの C 拡張コードを再利用するためには、コンパイル対象のファイルに変更が加えられていない必要があるため、
|
297
|
-
コンパイル済みコードの再利用が容易になります。
|
298
|
-
例えば、高速化したいプログラムに対しては、次のように、patch.rb の require 文のみを追記してください。
|
299
|
-
|
300
|
-
-----------------------------------------------------
|
301
|
-
# 高速化したいプログラム
|
302
|
-
|
303
|
-
# 一通りのメソッド定義
|
304
|
-
class Foo
|
305
|
-
def foo
|
306
|
-
...
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
class Bar
|
311
|
-
def bar
|
312
|
-
...
|
313
|
-
end
|
314
|
-
end
|
315
|
-
...
|
316
|
-
|
317
|
-
require 'patch' # この行だけ追記
|
318
|
-
-----------------------------------------------------
|
319
|
-
|
320
|
-
そして、patch.rb の中から、CastOff.compile を呼び出してください。
|
321
|
-
|
322
|
-
-----------------------------------------------------
|
323
|
-
# patch.rb
|
324
|
-
|
325
|
-
require 'cast_off'
|
326
|
-
|
327
|
-
class Foo
|
328
|
-
CastOff.compile(self, :foo, binding, クラス情報)
|
329
|
-
end
|
330
|
-
|
331
|
-
class Bar
|
332
|
-
CastOff.compile(self, :bar, binding, クラス情報)
|
333
|
-
end
|
334
|
-
-----------------------------------------------------
|
335
|
-
|
336
|
-
このようにすることで、require 'patch' の1行を削除するだけで、容易に CastOff への依存を解消することができます。
|
337
|
-
また、Foo#foo のコンパイルに用いるクラス情報を更新しても、Bar#bar の再コンパイルが走ることが無くなります。
|
338
|
-
|
339
|
-
|
340
|
-
***クラス情報の指定
|
341
|
-
CastOff に対するクラス情報の指定は、次のように行います。
|
342
|
-
|
343
|
-
-変数のクラス情報の指定:
|
344
|
-
--ローカル変数、引数
|
345
|
-
:ローカル変数名 => クラス
|
346
|
-
:ローカル変数名 => [クラス1, クラス2, ...]
|
347
|
-
[:ローカル変数名1, :ローカル変数名2, ...] => クラス
|
348
|
-
[:ローカル変数名1, :ローカル変数名2, ...] => [クラス1, クラス2, ...]
|
349
|
-
|
350
|
-
--インスタンス変数
|
351
|
-
:@インスタンス変数名 => クラス
|
352
|
-
:@インスタンス変数名 => [クラス1, クラス2, ...]
|
353
|
-
[:@インスタンス変数名1, :@インスタンス変数名2, ...] => クラス
|
354
|
-
[:@インスタンス変数名1, :@インスタンス変数名2, ...] => [クラス1, クラス2, ...]
|
355
|
-
|
356
|
-
--クラス変数
|
357
|
-
:@@クラス変数名 => クラス
|
358
|
-
:@@クラス変数名 => [クラス1, クラス2, ...]
|
359
|
-
[:@@クラス変数名1, :@@クラス変数名2, ...] => クラス
|
360
|
-
[:@@クラス変数名1, :@@クラス変数名2, ...] => [クラス1, クラス2, ...]
|
361
|
-
|
362
|
-
--グローバル変数
|
363
|
-
:$グローバル変数名 => クラス
|
364
|
-
:$グローバル変数名 => [クラス1, クラス2, ...]
|
365
|
-
[:$グローバル変数名1, :$グローバル変数名2, ...] => クラス
|
366
|
-
[:$グローバル変数名1, :$グローバル変数名2, ...] => [クラス1, クラス2, ...]
|
367
|
-
|
368
|
-
|
369
|
-
-メソッドの返り値のクラス情報の指定:
|
370
|
-
クラス => {:メソッド名1 => 返り値のクラス, :メソッド名2 => [返り値のクラス1, 返り値のクラス2, ...], ...}
|
371
|
-
|
372
|
-
|
373
|
-
-定数のクラス情報の指定:
|
374
|
-
定数のクラス情報の指定は、変数やメソッドの返り値とは異なります。
|
375
|
-
定数のクラス情報の指定は、定数解決に使用できる Binding オブジェクトを渡すことで行います。
|
376
|
-
|
377
|
-
例えば、次のような Sample#sample メソッドをコンパイルする場合、
|
378
|
-
|
379
|
-
-----------------------------------------------------
|
380
|
-
COUNT = 1000000
|
381
|
-
class Sample
|
382
|
-
def sample()
|
383
|
-
COUNT.times do
|
384
|
-
...
|
385
|
-
end
|
386
|
-
end
|
387
|
-
end
|
388
|
-
-----------------------------------------------------
|
389
|
-
|
390
|
-
次のように指定することで、COUNT という定数が Fixnum オブジェクトであることを指定することができます。
|
391
|
-
|
392
|
-
-----------------------------------------------------
|
393
|
-
class Sample
|
394
|
-
CastOff.compile(self, :sample, binding, クラス情報)
|
395
|
-
end
|
396
|
-
-----------------------------------------------------
|
397
|
-
|
398
|
-
上のように、CastOff.compile の引数に Binding オブジェクトを渡すと、CastOff はコンパイル時に、
|
399
|
-
与えられた Binding オブジェクトを用いて定数を参照し、定数のクラス情報を解決します。
|
400
|
-
ここで与える Binding オブジェクトは定数解決にのみ使用するため、
|
401
|
-
定数の解決に使用できる Binding オブジェクトならば、どのようなものを渡してもかまいません。
|
402
|
-
上の例では、CastOff.compile の呼び出しを、Sample クラスのクラス定義文の中で行うことで、
|
403
|
-
Sample#sample メソッドと同様の定数スコープを構築し、CastOff に渡しています。
|
404
|
-
|
405
|
-
Ruby では、クラス定義文を好きな場所で呼び出し、既存のクラスの定数スコープを得ることができます。
|
406
|
-
このため、Sample#sample メソッドを定義した箇所と、CastOff.compile を呼び出す箇所は、別ファイルでもかまいません。
|
407
|
-
CastOff への依存を簡単に無くすためにも、CastOff.compile の呼び出しは、高速化したいプログラムとは別ファイルに
|
408
|
-
まとめて記述したほうが使いやすいと思います。これについては、「スクリプトからの利用の流れ」を参照してください。
|
409
|
-
|
410
|
-
|
411
|
-
*** コンパイルの指定
|
412
|
-
ここでは、CastOff にコンパイルを指定するための方法を簡単に解説します。
|
413
|
-
クラス情報の指定方法については、上記のスクリプトからの利用の流れを参照してください。
|
414
|
-
|
415
|
-
-Ruby のインスタンスメソッドのコンパイル指定
|
416
|
-
--指定方法
|
417
|
-
CastOff.compile(クラス or モジュール, メソッド名, binding)
|
418
|
-
CastOff.compile(クラス or モジュール, メソッド名, binding, クラス情報)
|
419
|
-
CastOff.compile(クラス or モジュール, メソッド名, クラス情報)
|
420
|
-
--備考
|
421
|
-
Ruby のメソッドをコンパイルし、C 拡張に変換、対象のメソッドを上書きします。
|
422
|
-
メソッド名は Symbol オブジェクトで指定してください。
|
423
|
-
第三引数で与える Binding オブジェクトは、定数の解決に使用します。
|
424
|
-
|
425
|
-
-Ruby の特異メソッドのコンパイル指定
|
426
|
-
--指定方法
|
427
|
-
CastOff.compile_singleton_method(オブジェクト, メソッド名, binding)
|
428
|
-
CastOff.compile_singleton_method(オブジェクト, メソッド名, binding, クラス情報)
|
429
|
-
CastOff.compile_singleton_method(オブジェクト, メソッド名, クラス情報)
|
430
|
-
--備考
|
431
|
-
特異メソッドのコンパイルは、CastOff.compile ではなくこちらを使用してください。
|
432
|
-
CastOff.compile と同様に、対象のメソッドを上書きします。
|
433
|
-
メソッド名は Symbol オブジェクトで指定してください。
|
434
|
-
第三引数で与える Binding オブジェクトは、定数の解決に使用します。
|
435
|
-
|
436
|
-
-Ruby プログラムの一部をコンパイルし、実行させる指定
|
437
|
-
--指定方法
|
438
|
-
CastOff.execute(クラス情報) { ブロック }
|
439
|
-
--備考
|
440
|
-
与えられたブロックをコンパイルし、実行します。
|
441
|
-
|
442
|
-
|
443
|
-
*** コンパイルオプションに関する指定
|
444
|
-
CastOff をスクリプトから用いる場合、コンパイルの条件(コンパイルオプション)について様々な指定を行うことができます。
|
445
|
-
ここでは、CastOff に対して指定できるコンパイルオプションについて簡単に解説します。
|
446
|
-
|
447
|
-
-実行時にクラス情報のチェックを行うガードの有無
|
448
|
-
--指定方法
|
449
|
-
CastOff.inject_guard(true or false)
|
450
|
-
---デフォルト値
|
451
|
-
true
|
452
|
-
---備考
|
453
|
-
クラス情報に関するガードを挿入する(true)かしない(false)かを設定します。
|
454
|
-
クラス情報に関するガードとは、プログラマが手動で与えたクラス情報や、
|
455
|
-
プロファイルによって得たクラス情報が正しいかどうかを、実行時に検査するためのものです。
|
456
|
-
ガードでの検査に失敗した場合のデフォルトの挙動は例外ですが、
|
457
|
-
CastOff.deoptimize(true) とすることで、脱最適化を有効にすることができます。
|
458
|
-
|
459
|
-
|
460
|
-
--脱最適化
|
461
|
-
---指定方法
|
462
|
-
CastOff.deoptimize(true or false)
|
463
|
-
---デフォルト値
|
464
|
-
true
|
465
|
-
---備考
|
466
|
-
ガードでの検査に失敗した場合に、脱最適化を行う(true)か、例外を発生させる(false)かを設定します。
|
467
|
-
脱最適化を有効にすることで、ガードでの検査失敗時にも実行を継続させることができます。
|
468
|
-
しかし、脱最適化に必要な情報を保持する必要があり、CastOff による高速化の度合いが低下します。
|
469
|
-
|
470
|
-
|
471
|
-
--コンパイル条件のチェックのスキップ
|
472
|
-
---指定方法
|
473
|
-
CastOff.skip_configuration_check(true or false)
|
474
|
-
---デフォルト値
|
475
|
-
false
|
476
|
-
---備考
|
477
|
-
コンパイル済みコードを再利用していいかどうかを判定するときに、
|
478
|
-
コンパイル条件(コンパイルオプションや CastOff に与えるクラス情報など)
|
479
|
-
のチェックをスキップする(true)かスキップしない(false)かを設定します。
|
480
|
-
|
481
|
-
CastOff は、デフォルトでは、コンパイル済みコードを再利用していいかどうかを判定するときに、
|
482
|
-
指定されたコンパイル条件が、コンパイル済みのものと現在与えられているもので同一かどうかの判定を行います。
|
483
|
-
このとき、コンパイル条件が異なっていた場合は再度コンパイルを行います。
|
484
|
-
CastOff.skip_configuration_check(true) とすると、このコンパイル条件のチェックをスキップします。
|
485
|
-
|
486
|
-
コンパイル条件のチェックには Marshal.load などの実行コストの高い処理を複数回呼び出すため、時間がかかります。
|
487
|
-
CastOff に与えるコンパイル条件が決定した場合は、このオプションを使用して、
|
488
|
-
コンパイル条件のチェックをスキップし、ロード時間を短縮することをおすすめします。
|
489
|
-
|
490
|
-
|
491
|
-
--コンパイル済みコードの再利用
|
492
|
-
---指定方法
|
493
|
-
CastOff.reuse_compiled_code(true or false)
|
494
|
-
---デフォルト値
|
495
|
-
true
|
496
|
-
---備考
|
497
|
-
コンパイル済みコードの再利用をする(true)かしない(false)かを設定します。
|
498
|
-
再コンパイルを強制したい場合は、false に設定してください。
|
499
|
-
|
500
|
-
|
501
|
-
--定数の先読み
|
502
|
-
---指定方法
|
503
|
-
CastOff.prefetch_constant()
|
504
|
-
---デフォルト値
|
505
|
-
true
|
506
|
-
---備考
|
507
|
-
定数の先読みを行う(true)か行わない(false)かを設定します。
|
508
|
-
定数の先読みを行わせるためには、Binding オブジェクトを、コンパイル時に与える必要があります。
|
509
|
-
定数の先読みを指定した場合、CastOff は、定数の解決をロード時、もしくは最初に実行されたときに行います。
|
510
|
-
そして、先読みを行った定数を常に使用します。
|
511
|
-
このため、先読みを行った場合、定数を上書きした場合も、上書き前の値を使用してしまいます。
|
512
|
-
定数の上書きを使用するプログラムをコンパイルする場合、定数の先読みをオフにしてください。
|
513
|
-
ただし、定数の先読みをオフにした場合、定数の参照に rb_const_get を複数回使用するため、
|
514
|
-
定数参照がボトルネックになる可能性があります。
|
515
|
-
|
516
|
-
|
517
|
-
--コンパイル経過や CastOff の内部情報表示の指定
|
518
|
-
---指定方法
|
519
|
-
CastOff.verbose(true or false)
|
520
|
-
---デフォルト値
|
521
|
-
false
|
522
|
-
---備考
|
523
|
-
コンパイルの経過や CastOff の内部情報を表示する(true)かしない(false)かを設定します。
|
524
|
-
ここでの CastOff の内部情報とは、次のようなものです。
|
525
|
-
1:クラス情報を解決できなかった変数やメソッドの返り値
|
526
|
-
2:複製を削減できなかった文字列リテラル
|
527
|
-
|
528
|
-
|
529
|
-
--組み込み変数に対する非互換性の許容
|
530
|
-
---指定方法
|
531
|
-
CastOff.allow_builtin_variable_incompatibility(true or false)
|
532
|
-
---デフォルト値
|
533
|
-
false
|
534
|
-
---備考
|
535
|
-
$1 などの、正規表現に関する組み込み変数の非互換性を許容する(true)か、許容しない(false)かを設定します。
|
536
|
-
$1 などの、正規表現に関する組み込み変数は、メソッド呼び出し毎に個別のスコープを持ちます。
|
537
|
-
例えば、次のような foo と bar では、これらの組み込み変数に対し、それぞれ異なるスコープを持っています。
|
538
|
-
このため、foo 内で $1 の値が "foo" となるにも拘らず、bar 内の puts $1 で表示されるのは、"bar" となります。
|
539
|
-
|
540
|
-
-----------------------------------------------------
|
541
|
-
def foo()
|
542
|
-
"this is foo" =~ /(foo)/ # $1 = "foo" となる
|
543
|
-
end
|
544
|
-
|
545
|
-
def bar()
|
546
|
-
"this is bar" =~ /(bar)/ # $1 = "bar" となる
|
547
|
-
foo()
|
548
|
-
puts $1 # bar と表示
|
549
|
-
end
|
550
|
-
|
551
|
-
def baz()
|
552
|
-
"this is baz" =~ /(baz)/ # $1 = "baz" となる
|
553
|
-
puts $1 # baz と表示
|
554
|
-
end
|
555
|
-
-----------------------------------------------------
|
556
|
-
|
557
|
-
これに対し、CastOff を用いた場合、foo と bar のこれらの組み込み変数に対するスコープが共有されてしまいます。
|
558
|
-
つまり、CastOff を使用すると、foo によって $1 の値が "foo" に上書きされ、bar 内の puts $1 で表示されるのが、"foo" となってしまいます。
|
559
|
-
以上の理由により、CastOff では、コンパイル対象のメソッドが $1 などの組み込み変数を使用していた場合、コンパイルエラーを発生させます。
|
560
|
-
|
561
|
-
しかし、上の例の baz のように、$1 が上書きされないようなメソッドでは、このような非互換性は問題とはなりません。
|
562
|
-
baz メソッドのように、組み込み変数のスコープに対する非互換性が崩れていても問題ない場合は、このオプションを使用してください。
|
563
|
-
CastOff.allow_builtin_variable_incompatibility(true) とすると、
|
564
|
-
$1 などの組み込み変数を使用していても、コンパイルを行うことができます。
|
132
|
+
Show version number of CastOff.
|
565
133
|
|