fastruby 0.0.1

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 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
+