fastruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,142 @@
1
+ = Fastruby - fast execution of ruby code
2
+
3
+ Fastruby is a gem which allows to execute ruby code faster than normal (about 100X of the MRI1.8)
4
+
5
+ Fastruby IS NOT a separated ruby interpreter. Then, the design is simple
6
+
7
+ Fastruby IS NOT a DSL to generate C code using ruby or a Ruby to C translator, the goal of fastruby is to execute RUBY code
8
+
9
+ *************************************************************************************************************
10
+
11
+ The current version of fastruby is a Proof of Concept and it's not ready to go to production
12
+
13
+ *************************************************************************************************************
14
+
15
+ == Core Concepts
16
+
17
+ === Native build
18
+
19
+ All code processed by fastruby ends with a native representation, in the current version, this is acomplished using RubyParser to parse rubycode.
20
+ The ruby code is translated to C and then processed with RubyInline
21
+
22
+ === Transparent multimethods (and multiblocks)
23
+
24
+ The methods processed by fastruby has multiple internal implementations depending on the type of the arguments.
25
+ Each possible signature has a version of the method and this are built in runtime when the method is called with a new signature.
26
+ The same concept will be applied to blocks (anonymous methods) in future releases
27
+
28
+ === Type inference
29
+
30
+ Each version of a method is built for a specific signature, so, the builder can asume a type for the arguments and build method calls using that assumption.
31
+ Whereever the translator can asume a type for a expression involved in a method call (used as argument or as receiver), this information can be used to encode
32
+ direct calls instead of normal and expensive ruby calls.
33
+
34
+ The currently implementation only can infer types for method and block arguments, and for literals
35
+
36
+ === Customization through build directives and API
37
+
38
+ To compensate for the described limitations, fastruby suport a few build directives to allow the programmer help the inference.
39
+ The syntaxis of these directives are the same as normal ruby call (see examples)
40
+ Also, fastruby will define a API to customize aspects of fastruby internals. E.g the build method to invoke the build of methods with a specific signature (see examples)
41
+
42
+ == Installation
43
+
44
+ The install is as simple as execute the well-known gem install:
45
+
46
+ sudo gem install fastruby
47
+
48
+ == Documentation
49
+
50
+ Since this first version of fastruby is in part an spike/PoC, there is no stable API to document.
51
+ So, I recommend not to develop other software on top of fastruby since its API could change in any moment.
52
+ But I will try as much as possible keep the backward compatibility in the near future
53
+
54
+ I will stabilize the API and document it for next releases. I promise
55
+
56
+ == Known Limitations & Issues
57
+
58
+ * fastruby only can be called from inside a class scope, and only can be used to define instance methods (no class methods)
59
+ * fastruby invokations can't take more than one method
60
+ * monkey patching does not work with fastruby methods
61
+ * calls with blocks to ruby or cruby methods are almost as slow as normal ruby (if the called method is defined by fastruby, the call it's pretty fast)
62
+ * does not support singleton methods (both define & call)
63
+ * does not support methods with variable number of arguments
64
+ * does not support exception handling (rescue, ensure, etc...)
65
+
66
+ == Usage
67
+
68
+ The basic method is fastruby, fastruby takes a string with ruby code and compile it
69
+
70
+ === Example 1: How invoke fastruby
71
+
72
+ require "fastruby"
73
+
74
+ class X
75
+ fastruby '
76
+ def foo
77
+ print "hello world\n"
78
+ end
79
+ '
80
+ end
81
+
82
+ X.new.foo
83
+
84
+ === Example 2: Prebuild
85
+
86
+ Normally, the method is built at runtime when is called with a new signature, You can prebuild the method to prevent this when the method is called for first time
87
+
88
+ require "fastruby"
89
+
90
+ class X
91
+ fastruby '
92
+ def foo(a,b)
93
+ a+b
94
+ end
95
+ '
96
+ end
97
+
98
+ X.build([X,String,String] , :foo)
99
+
100
+ p X.new.foo("fast", "ruby") # will use the prebuilded method
101
+ p X.new.foo(["fast"], ["ruby"]) # will build foo for X,Array,Array signature and then execute it
102
+
103
+ === Example 3: Explicit inference
104
+
105
+ Current fastruby allows to explictly define a type for a expression, a basic example show as tell to fastruby to assume that the result of to_s is of type String in the following case:
106
+
107
+ require "fastruby"
108
+
109
+ class X
110
+ fastruby '
111
+ def foo(a)
112
+ a.to_s.infer(String) + "_"
113
+ end
114
+ '
115
+ end
116
+
117
+ p X.new.foo(9)
118
+
119
+ When fastruby can infer the type of an expression, the method calls that involve that expression can be accelerated. This is not necessary for arguments passed to a method or block
120
+
121
+ === Example 4: Variable types
122
+
123
+ Like static languages, you can define a type for a variable to help the inference and gain some performance. This can be done by using lvar_type directive
124
+
125
+ class X
126
+ fastruby '
127
+ def foo
128
+ lvar_type(i, Fixnum)
129
+ i = 100
130
+ while (i > 0)
131
+ i = i - 1
132
+ end
133
+ nil
134
+ end
135
+ '
136
+ end
137
+
138
+ With no lvar_type, the calls to Fixnum#> and Fixnum#- will be dynamic and more expensive
139
+
140
+ == Copying
141
+
142
+ Copyright (c) 2011 Dario Seminara, released under the GPL License (see LICENSE)
data/Rakefile ADDED
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/gempackagetask'
6
+ require "rspec/core/rake_task"
7
+
8
+ spec = Gem::Specification.new do |s|
9
+ s.name = 'fastruby'
10
+ s.version = '0.0.1'
11
+ s.author = 'Dario Seminara'
12
+ s.email = 'robertodarioseminara@gmail.com'
13
+ s.platform = Gem::Platform::RUBY
14
+ s.summary = 'fast execution of ruby code'
15
+ s.homepage = "http://github.com/tario/fastruby"
16
+ s.add_dependency "RubyInline", "= 3.9.0"
17
+ s.add_dependency "ruby_parser", "= 2.0.6"
18
+ s.has_rdoc = true
19
+ s.extra_rdoc_files = [ 'README' ]
20
+ # s.rdoc_options << '--main' << 'README'
21
+ s.files = Dir.glob("{benchmarks,examples,lib,spec}/**/*") +
22
+ [ 'LICENSE', 'AUTHORS', 'README', 'Rakefile', 'TODO' ]
23
+ end
24
+
25
+ desc 'Run tests'
26
+
27
+ RSpec::Core::RakeTask.new("test:units") do |t|
28
+ t.pattern= 'spec/**/*.rb'
29
+ end
30
+
31
+ desc 'Generate RDoc'
32
+ Rake::RDocTask.new :rdoc do |rd|
33
+ rd.rdoc_dir = 'doc'
34
+ rd.rdoc_files.add 'lib', 'README'
35
+ rd.main = 'README'
36
+ end
37
+
38
+ desc 'Build Gem'
39
+ Rake::GemPackageTask.new spec do |pkg|
40
+ pkg.need_tar = true
41
+ end
42
+
43
+ desc 'Clean up'
44
+ task :clean => [ :clobber_rdoc, :clobber_package ]
45
+
46
+ desc 'Clean up'
47
+ task :clobber => [ :clean ]
data/TODO ADDED
@@ -0,0 +1,31 @@
1
+ Basic functionality:
2
+
3
+ * Flow control setences: case
4
+ * Exceptions
5
+ * Defining and call of methods with variable number of arguments
6
+ * Blocks with variable number of arguments
7
+ * call to monkey patched methods from fastruby code
8
+ * callcc
9
+
10
+ To improve:
11
+
12
+ * Inlining of methods
13
+ * Error check (e.g. calling a directive with invalid parameters)
14
+ * Fastruby builds himself to improve performance of dynamic builds
15
+ * Multiblocks
16
+ * Fastruby method allow defining many methods in only one call and allow define classes
17
+ * Oracle testing using normal ruby as oracle
18
+ * Inference using "return types" of methods when the implementation of the method is known
19
+ * RubySpec: make code executed by fastruby pass RubySpec
20
+
21
+ Refactor:
22
+
23
+ * hashes of methods on builder refactored into an only hash
24
+ * refactor anonoymous methods (tip: use ruby format string for names)
25
+ * Clean of duplicated code
26
+ * Remove ruby inline explicit dependency
27
+
28
+ Documentation:
29
+
30
+ * Builder directives
31
+ * Build API
@@ -0,0 +1,68 @@
1
+ require "rubygems"
2
+ require "fastruby"
3
+
4
+ class X
5
+ fastruby "
6
+ def foo(a,b)
7
+ return a+b
8
+ end
9
+ "
10
+ end
11
+
12
+ class Y
13
+ fastruby "
14
+ def bar(x)
15
+ i = 1000000
16
+
17
+ lvar_type(i,Fixnum)
18
+
19
+ ret = 0
20
+ while i > 0
21
+ ret = x.foo(i,i)
22
+ i = i - 1
23
+ end
24
+ return ret
25
+ end
26
+
27
+ "
28
+ end
29
+
30
+ class X2
31
+ def foo(a,b)
32
+ return a+b
33
+ end
34
+ end
35
+
36
+ class Y2
37
+ def bar(x)
38
+ i = 1000000
39
+ ret = 0
40
+ while i > 0
41
+ ret = x.foo(i,i)
42
+ i = i - 1
43
+ end
44
+ return ret
45
+ end
46
+
47
+ end
48
+
49
+
50
+ x = X.new
51
+ y = Y.new
52
+ y2 = Y2.new
53
+ x2 = X2.new
54
+
55
+ Y.build([Y,X],:bar)
56
+
57
+ require 'benchmark'
58
+
59
+ Benchmark::bm(20) do |b|
60
+
61
+ b.report("fastruby") do
62
+ y.bar(x)
63
+ end
64
+
65
+ b.report("ruby") do
66
+ y2.bar(x2)
67
+ end
68
+ end
@@ -0,0 +1,70 @@
1
+ require "rubygems"
2
+ require "fastruby"
3
+
4
+ class X
5
+ fastruby "
6
+ def foo
7
+ yield
8
+ end
9
+ "
10
+ end
11
+
12
+ class Y
13
+ fastruby "
14
+ def bar(x)
15
+ i = 1000000
16
+
17
+ lvar_type(i,Fixnum)
18
+
19
+ ret = 0
20
+ while i > 0
21
+ x.foo do
22
+ end
23
+ i = i - 1
24
+ end
25
+ 0
26
+ end
27
+
28
+ "
29
+ end
30
+
31
+ class X2
32
+ def foo
33
+ yield
34
+ end
35
+ end
36
+
37
+ class Y2
38
+ def bar(x)
39
+ i = 1000000
40
+
41
+ ret = 0
42
+ while i > 0
43
+ x.foo do
44
+ i = i - 1
45
+ end
46
+ end
47
+ 0
48
+ end
49
+ end
50
+
51
+
52
+ x = X.new
53
+ y = Y.new
54
+ y2 = Y2.new
55
+ x2 = X2.new
56
+
57
+ Y.build([Y,X],:bar)
58
+
59
+ require 'benchmark'
60
+
61
+ Benchmark::bm(20) do |b|
62
+
63
+ b.report("fastruby") do
64
+ y.bar(x)
65
+ end
66
+
67
+ b.report("ruby") do
68
+ y2.bar(x2)
69
+ end
70
+ end
@@ -0,0 +1,70 @@
1
+ require "rubygems"
2
+ require "fastruby"
3
+
4
+ class X
5
+ fastruby "
6
+ def foo
7
+ yield(1,2,3)
8
+ end
9
+ "
10
+ end
11
+
12
+ class Y
13
+ fastruby "
14
+ def bar(x)
15
+ i = 1000000
16
+
17
+ lvar_type(i,Fixnum)
18
+
19
+ ret = 0
20
+ while i > 0
21
+ x.foo do |a,b,c|
22
+ end
23
+ i = i - 1
24
+ end
25
+ 0
26
+ end
27
+
28
+ "
29
+ end
30
+
31
+ class X2
32
+ def foo
33
+ yield
34
+ end
35
+ end
36
+
37
+ class Y2
38
+ def bar(x)
39
+ i = 1000000
40
+
41
+ ret = 0
42
+ while i > 0
43
+ x.foo do
44
+ i = i - 1
45
+ end
46
+ end
47
+ 0
48
+ end
49
+ end
50
+
51
+
52
+ x = X.new
53
+ y = Y.new
54
+ y2 = Y2.new
55
+ x2 = X2.new
56
+
57
+ Y.build([Y,X],:bar)
58
+
59
+ require 'benchmark'
60
+
61
+ Benchmark::bm(20) do |b|
62
+
63
+ b.report("fastruby") do
64
+ y.bar(x)
65
+ end
66
+
67
+ b.report("ruby") do
68
+ y2.bar(x2)
69
+ end
70
+ end
@@ -0,0 +1,94 @@
1
+ require "rubygems"
2
+ require "fastruby"
3
+
4
+ class Y
5
+ fastruby "
6
+ def bar
7
+ i = 1000000
8
+
9
+ lvar_type(i,Fixnum)
10
+
11
+ ret = 0
12
+ while i > 0
13
+ $a = 9
14
+ i = i - 1
15
+ end
16
+ 0
17
+ end
18
+
19
+ "
20
+ end
21
+
22
+ class Y2
23
+ def bar
24
+ i = 1000000
25
+
26
+ ret = 0
27
+ while i > 0
28
+ $a = 9
29
+ i = i - 1
30
+ end
31
+ 0
32
+ end
33
+ end
34
+
35
+
36
+ class Y_
37
+ fastruby "
38
+ def bar
39
+ i = 1000000
40
+
41
+ lvar_type(i,Fixnum)
42
+
43
+ ret = 0
44
+ while i > 0
45
+ i = i - 1
46
+ end
47
+ 0
48
+ end
49
+
50
+ "
51
+ end
52
+
53
+ class Y2_
54
+ def bar
55
+ i = 1000000
56
+
57
+ ret = 0
58
+ while i > 0
59
+ i = i - 1
60
+ end
61
+ 0
62
+ end
63
+ end
64
+
65
+
66
+ y = Y.new
67
+ y2 = Y2.new
68
+ y_ = Y_.new
69
+ y2_ = Y2_.new
70
+
71
+ Y.build([Y],:bar)
72
+ Y_.build([Y_],:bar)
73
+
74
+ require 'benchmark'
75
+
76
+ Benchmark::bm(20) do |b|
77
+
78
+ b.report("fastruby") do
79
+ y.bar
80
+ end
81
+
82
+ b.report("ruby") do
83
+ y2.bar
84
+ end
85
+
86
+ b.report("lfastruby") do
87
+ y_.bar
88
+ end
89
+
90
+ b.report("lruby") do
91
+ y2_.bar
92
+ end
93
+
94
+ end
@@ -0,0 +1,80 @@
1
+ require "rubygems"
2
+ require "fastruby"
3
+
4
+ class X
5
+ fastruby "
6
+ def bar
7
+ end
8
+ "
9
+
10
+ fastruby "
11
+ def foo
12
+ yield(self)
13
+ end
14
+ "
15
+ end
16
+
17
+ class Y
18
+ fastruby "
19
+ def bar(x)
20
+ i = 1000000
21
+
22
+ lvar_type(i,Fixnum)
23
+
24
+ x2 = 0
25
+ ret = 0
26
+ while i > 0
27
+ x.foo do |x2|
28
+ x2.bar
29
+ end
30
+ i = i - 1
31
+ end
32
+ 0
33
+ end
34
+
35
+ "
36
+ end
37
+
38
+ class X2
39
+ def bar
40
+ end
41
+
42
+ def foo
43
+ yield(self)
44
+ end
45
+ end
46
+
47
+ class Y2
48
+ def bar(x)
49
+ i = 1000000
50
+
51
+ ret = 0
52
+ while i > 0
53
+ x.foo do |x2|
54
+ x2.bar
55
+ end
56
+ i = i - 1
57
+ end
58
+ 0
59
+ end
60
+ end
61
+
62
+
63
+ x = X.new
64
+ y = Y.new
65
+ y2 = Y2.new
66
+ x2 = X2.new
67
+
68
+ Y.build([Y,X],:bar)
69
+
70
+ require 'benchmark'
71
+
72
+ Benchmark::bm(20) do |b|
73
+ b.report("fastruby") do
74
+ y.bar(x)
75
+ end
76
+
77
+ b.report("ruby") do
78
+ y2.bar(x2)
79
+ end
80
+ end
@@ -0,0 +1,64 @@
1
+ require "rubygems"
2
+ require "fastruby"
3
+
4
+ class X
5
+ fastruby '
6
+ def foo
7
+ "65535".to_i
8
+ end
9
+ '
10
+ end
11
+
12
+ class Y
13
+ fastruby "
14
+ def bar(x)
15
+ i = 1000000
16
+ lvar_type(i,Fixnum)
17
+
18
+ while i > 0
19
+ x.foo
20
+ i = i - 1
21
+ end
22
+ 0
23
+ end
24
+
25
+ "
26
+ end
27
+
28
+ class X2
29
+ def foo
30
+ "65535".to_i
31
+ end
32
+ end
33
+
34
+ class Y2
35
+ def bar(x)
36
+ i = 1000000
37
+
38
+ while i > 0
39
+ x.foo
40
+ i = i - 1
41
+ end
42
+ 0
43
+ end
44
+ end
45
+
46
+
47
+ x = X.new
48
+ y = Y.new
49
+ y2 = Y2.new
50
+ x2 = X2.new
51
+
52
+ Y.build([Y,X],:bar)
53
+
54
+ require 'benchmark'
55
+
56
+ Benchmark::bm(20) do |b|
57
+ b.report("fastruby") do
58
+ y.bar(x)
59
+ end
60
+
61
+ b.report("ruby") do
62
+ y2.bar(x2)
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ require "fastruby"
2
+
3
+ class X
4
+ fastruby '
5
+ def foo
6
+ print "hello world\n"
7
+ end
8
+ '
9
+ end
10
+
11
+ X.new.foo
12
+
@@ -0,0 +1,14 @@
1
+ require "fastruby"
2
+
3
+ class X
4
+ fastruby '
5
+ def foo(a,b)
6
+ a+b
7
+ end
8
+ '
9
+ end
10
+
11
+ X.build([X,String,String] , :foo)
12
+
13
+ p X.new.foo("fast", "ruby") # will use the prebuilded method
14
+ p X.new.foo(["fast"], ["ruby"]) # will build foo for X,Array,Array signature and then execute it
@@ -0,0 +1,12 @@
1
+ require "fastruby"
2
+
3
+ class X
4
+ fastruby '
5
+ def foo(a)
6
+ a.to_s + "_"
7
+ end
8
+ '
9
+ end
10
+
11
+ p X.new.foo(9)
12
+