trenza 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # Trenza
2
+
3
+ Trenza is the spanish word for *braid* or *plait*.
4
+
5
+ > plait |plāt, plat| (noun) a single length of hair or other flexible material made up of three or more interlaced strands.
6
+
7
+ ![Trenza](http://dl.dropbox.com/u/521377/trenza_cinco.jpg)
8
+
9
+ Trenza is also an experiment in dynamic programming inspired by the reading of Paolo Perrotta's *“Metaprogramming Ruby”* (an awesome book, by the way), and in evaluation models and strategies, inspired in my late adventures with Erlang and Haskell.
10
+
11
+ Trenza provides two methods to every Ruby object: `lazy` and `parallel`. Those two methods return an object that behaves exactly the same way the old one, except that, instead or evaluating its methods right away when they're called, they do it in a *lazy* or *parallel* way.
12
+
13
+ ## *Lazy* objects
14
+
15
+ *Lazy* objects defer the actual evaluation of its methods until the moment its really needed:
16
+
17
+ class Wadus
18
+ def calculate
19
+ # whatever
20
+ end
21
+ end
22
+
23
+ wadus1 = Wadus.new.lazy
24
+ wadus2 = Wadus.new.lazy
25
+
26
+ x = wadus1.calculate
27
+ y = wadus2.calculate
28
+ # no calculation is actually done
29
+
30
+ puts x # now wadus1.calculate is run in order to print it
31
+ # wadus2.calculate never gets run since its not needed
32
+
33
+ ## *Parallel* objects
34
+
35
+ *Parallel* objects are similar to *lazy* objects, but instead of deferring the whole evaluation of the method, they start it in the background and follow with your program. Whenever the actual return value is needed, then and only then will your program for the calculation to end (in case it hadn't ended already). This way your programs can become massively parallel without changing your programming style at all:
36
+
37
+ class Wadus
38
+ def calculate
39
+ # whatever
40
+ end
41
+ end
42
+
43
+ wadus1 = Wadus.new.parallel
44
+ wadus2 = Wadus.new.parallel
45
+
46
+ x = wadus1.calculate # calculation is started in the background, your program continues
47
+ y = wadus2.calculate # calculation is started in the background, your program continues
48
+
49
+ ...
50
+
51
+ puts x + y # in case they hadn't finished already, now your program will wait for the
52
+ # calculations to finished, since the return values are needed
53
+
54
+ Please note that Trenza uses the underlying Ruby's `Thread` class implementation, so the actual kind of parallelism achieved depends greatly on the Ruby implementation you're using. Check Ruby 1.8, Ruby 1.9 and JRuby documentation for further details.
55
+
56
+ ## Use cases
57
+
58
+ Trenza is an experiment and might not have any practical uses apart from that. But if you find one, let me know!
59
+
60
+ As for me, scripts with lots of I/O waiting (such as scripts that download files) seem a natural fit for `parallel` (see `examples/download.rb` for an example).
61
+
62
+ ## Usage
63
+
64
+ Nothing special: install the gem, require it, call `lazy` or `parallel` when initializing your objects.
65
+
66
+ ## License
67
+
68
+ Copyright © Sergio Gil, 2012
69
+
70
+ Licensed under the [MIT license](http://porras.mit-license.org/).
@@ -0,0 +1,22 @@
1
+ require 'open-uri'
2
+ require 'trenza'
3
+
4
+
5
+ class Download
6
+ def initialize(url)
7
+ @url = url
8
+ end
9
+
10
+ def size
11
+ open(@url).read.size
12
+ end
13
+ end
14
+
15
+ urls = [
16
+ 'http://google.es',
17
+ 'http://amazon.es',
18
+ 'http://bebanjo.com'
19
+ ]
20
+
21
+ puts urls.map { |url| Download.new(url).parallel.size }.reduce(:+)
22
+
@@ -0,0 +1,29 @@
1
+ require 'trenza'
2
+ require 'benchmark'
3
+
4
+ class Calculator
5
+ def add(a, b)
6
+ result = a + b
7
+ sleep 0.01 * result
8
+ result
9
+ end
10
+ end
11
+
12
+ def try(calc)
13
+ z = calc.add(10, 10)
14
+ a = calc.add(5, 7)
15
+ b = calc.add(3, 4)
16
+ c = calc.add(1, 2)
17
+ d = calc.add(3, 5)
18
+ f = calc.add(c, d)
19
+ e = calc.add(a, b)
20
+ g = calc.add(e, f)
21
+ g.to_s
22
+ end
23
+
24
+
25
+ Benchmark.bm(10) do |bm|
26
+ bm.report("Regular") { try Calculator.new }
27
+ bm.report("Lazy") { try Calculator.new.lazy }
28
+ bm.report("Parallel") { try Calculator.new.parallel }
29
+ end
@@ -0,0 +1,7 @@
1
+ module Trenza
2
+ module BlankSlate
3
+ def self.included(base)
4
+ base.send(:instance_methods).each { |m| base.send(:undef_method, m) unless m.to_s =~ /^__/ || m.to_s == 'object_id'}
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,31 @@
1
+ module Trenza
2
+ class Lazy
3
+ include BlankSlate
4
+
5
+ def initialize(object)
6
+ @object = object
7
+ end
8
+
9
+ def method_missing(meth, *args, &blk)
10
+ MethodCall.new do
11
+ @object.send meth, *args, &blk
12
+ end
13
+ end
14
+
15
+ class MethodCall
16
+ include BlankSlate
17
+
18
+ def initialize(&block)
19
+ @block = block
20
+ end
21
+
22
+ def method_missing(meth, *args, &blk)
23
+ value.send meth, *args, &blk
24
+ end
25
+
26
+ def value
27
+ @value ||= @block.call
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ module Trenza
2
+ class Parallel
3
+ include BlankSlate
4
+
5
+ def initialize(object)
6
+ @object = object
7
+ end
8
+
9
+ def method_missing(meth, *args, &blk)
10
+ MethodCall.new do
11
+ @object.send meth, *args, &blk
12
+ end
13
+ end
14
+
15
+ class MethodCall
16
+ include BlankSlate
17
+
18
+ def initialize(&block)
19
+ @thread = Thread.new(&block)
20
+ end
21
+
22
+ def method_missing(meth, *args, &blk)
23
+ @thread.value.send(meth, *args, &blk)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ module Trenza
2
+ module ProxyBuilder
3
+ def parallel
4
+ Parallel.new(self)
5
+ end
6
+
7
+ def lazy
8
+ Lazy.new(self)
9
+ end
10
+ end
11
+ end
12
+
13
+ include Trenza::ProxyBuilder
data/lib/trenza.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'trenza/blank_slate'
2
+ require 'trenza/lazy'
3
+ require 'trenza/parallel'
4
+ require 'trenza/proxy_builders'
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trenza
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sergio Gil
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-09 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email: sgilperez@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - README.md
21
+ - lib/trenza/blank_slate.rb
22
+ - lib/trenza/lazy.rb
23
+ - lib/trenza/parallel.rb
24
+ - lib/trenza/proxy_builders.rb
25
+ - lib/trenza.rb
26
+ - examples/downloads.rb
27
+ - examples/slow_calculator.rb
28
+ homepage: http://github.com/porras/trenza
29
+ licenses: []
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 1.8.10
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: Adds parallelism to any object in a transparent way
52
+ test_files: []