benelux 0.2.0.001

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.txt ADDED
@@ -0,0 +1,4 @@
1
+ BENELUX, CHANGES
2
+
3
+
4
+ #### 0.2.0 (2009-09-??) ###############################
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2009 Solutious Inc, Delano Mandelbaum
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,36 @@
1
+ = Benelux v0.1
2
+
3
+ <b></b>
4
+
5
+
6
+ == Features
7
+
8
+
9
+
10
+ == Installation
11
+
12
+ Get it in one of the following ways:
13
+
14
+ $ gem install benelux
15
+ $ git clone git://github.com/delano/benelux.git
16
+ $ gem install delano-benelux --source http://gems.github.com
17
+
18
+
19
+ == More Information
20
+
21
+ * Codes[http://github.com/delano/benelux]
22
+ * RDocs[http://delano.github.com/benelux]
23
+
24
+ == Credits
25
+
26
+ * Delano Mandelbaum (http://solutious.com)
27
+
28
+
29
+ == Thanks
30
+
31
+ * Alexis Sellier for fielding my Ruby questions
32
+
33
+
34
+ == License
35
+
36
+ See LICENSE.txt
data/Rakefile ADDED
@@ -0,0 +1,73 @@
1
+
2
+ require 'rake/clean'
3
+ require 'rake/gempackagetask'
4
+ require 'hanna/rdoctask'
5
+ require 'rake/testtask'
6
+ require 'shoulda/tasks'
7
+ require 'rake/runtest'
8
+ require 'monkeyspecdoc' # http://jgre.org/2008/09/03/monkeyspecdoc/
9
+ require 'fileutils'
10
+ include FileUtils
11
+
12
+ task :default => :test
13
+
14
+
15
+ # PACKAGE =============================================================
16
+
17
+ name = "benelux"
18
+ load "#{name}.gemspec"
19
+
20
+ version = @spec.version
21
+
22
+ Rake::GemPackageTask.new(@spec) do |p|
23
+ p.need_tar = true if RUBY_PLATFORM !~ /mswin/
24
+ end
25
+
26
+ task :release => [ "publish:gem", :clean, "publish:rdoc" ] do
27
+ $: << File.join(File.dirname(__FILE__), 'lib')
28
+ require "rudy"
29
+ abort if Drydock.debug?
30
+ end
31
+
32
+ task :install => [ :rdoc, :package ] do
33
+ sh %{sudo gem install pkg/#{name}-#{version}.gem}
34
+ end
35
+
36
+ task :uninstall => [ :clean ] do
37
+ sh %{sudo gem uninstall #{name}}
38
+ end
39
+
40
+
41
+ # Rubyforge Release / Publish Tasks ==================================
42
+
43
+ #about 'Publish website to rubyforge'
44
+ task 'publish:rdoc' => 'doc/index.html' do
45
+ sh "scp -rp doc/* rubyforge.org:/var/www/gforge-projects/#{name}/"
46
+ end
47
+
48
+ #about 'Public release to rubyforge'
49
+ task 'publish:gem' => [:package] do |t|
50
+ sh <<-end
51
+ rubyforge add_release -o Any -a CHANGES.txt -f -n README.rdoc #{name} #{name} #{@spec.version} pkg/#{name}-#{@spec.version}.gem &&
52
+ rubyforge add_file -o Any -a CHANGES.txt -f -n README.rdoc #{name} #{name} #{@spec.version} pkg/#{name}-#{@spec.version}.tgz
53
+ end
54
+ end
55
+
56
+
57
+ Rake::RDocTask.new do |t|
58
+ t.rdoc_dir = 'doc'
59
+ t.title = @spec.summary
60
+ t.options << '--line-numbers' << '-A cattr_accessor=object'
61
+ t.options << '--charset' << 'utf-8'
62
+ t.rdoc_files.include('LICENSE.txt')
63
+ t.rdoc_files.include('README.rdoc')
64
+ t.rdoc_files.include('CHANGES.txt')
65
+ #t.rdoc_files.include('Rudyfile') # why is the formatting f'd?
66
+ t.rdoc_files.include('bin/*')
67
+ t.rdoc_files.include('lib/**/*.rb')
68
+ end
69
+
70
+ CLEAN.include [ 'pkg', '*.gem', '.config', 'doc', 'coverage*' ]
71
+
72
+
73
+
data/benelux.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ @spec = Gem::Specification.new do |s|
2
+ s.name = "benelux"
3
+ s.rubyforge_project = 'benelux'
4
+ s.version = "0.2.0.001"
5
+ s.summary = "Benelux: Little freakin' timers for your Ruby codes"
6
+ s.description = s.summary
7
+ s.author = "Delano Mandelbaum"
8
+ s.email = "delano@solutious.com"
9
+ s.homepage = "http://github.com/delano/benelux"
10
+
11
+ s.extra_rdoc_files = %w[README.rdoc LICENSE.txt CHANGES.txt]
12
+ s.has_rdoc = true
13
+ s.rdoc_options = ["--line-numbers", "--title", s.summary, "--main", "README.rdoc"]
14
+ s.require_paths = %w[lib]
15
+
16
+ s.add_dependency 'hexoid'
17
+
18
+ # = MANIFEST =
19
+ # git ls-files
20
+ s.files = %w(
21
+ CHANGES.txt
22
+ LICENSE.txt
23
+ README.rdoc
24
+ Rakefile
25
+ benelux.gemspec
26
+ lib/benelux.rb
27
+ lib/benelux/mark.rb
28
+ lib/benelux/mixins/thread.rb
29
+ lib/benelux/timeline.rb
30
+ tryouts/basic_tryouts.rb
31
+ )
32
+
33
+
34
+ end
data/lib/benelux.rb ADDED
@@ -0,0 +1,130 @@
1
+ require 'attic'
2
+ require 'thread'
3
+ require 'hexoid'
4
+
5
+ module Benelux
6
+ NOTSUPPORTED = [Class, Object, Kernel]
7
+ SUFFIX_START = :a.freeze
8
+ SUFFIX_END = :z.freeze
9
+
10
+ require 'benelux/timeline'
11
+ require 'benelux/mark'
12
+ require 'benelux/mixins/thread'
13
+
14
+ @@timed_methods = {}
15
+ @@thread_timelines = []
16
+ @@timeline = Benelux::Timeline.new
17
+ @@mutex = Mutex.new
18
+
19
+ class BeneluxError < RuntimeError; end
20
+ class NotSupported < BeneluxError; end
21
+
22
+ def benelux_timers
23
+ Benelux.timed_methods[self.class]
24
+ end
25
+
26
+ def Benelux.supported?(klass)
27
+ !NOTSUPPORTED.member?(klass)
28
+ end
29
+
30
+ def Benelux.store_thread_reference
31
+ return if Benelux.thread_timelines.member? Thread.current
32
+ @@mutex.synchronize do
33
+ Benelux.thread_timelines << Thread.current
34
+ end
35
+ end
36
+
37
+ def Benelux.timed_methods
38
+ @@timed_methods
39
+ end
40
+
41
+ def Benelux.thread_timelines
42
+ @@thread_timelines
43
+ end
44
+
45
+ def Benelux.timeline
46
+ @@timeline = Benelux.generate_timeline if @@timeline.empty?
47
+ @@timeline
48
+ end
49
+
50
+ def Benelux.generate_timeline
51
+ @@mutex.synchronize do
52
+ timeline = Benelux::Timeline.new
53
+ Benelux.thread_timelines.each { |t| timeline << t.benelux }
54
+ timeline.flatten.sort
55
+ end
56
+ end
57
+
58
+ def Benelux.thread_timeline(thread_id=nil)
59
+ Thread.current.benelux ||= Benelux::Timeline.new
60
+ Thread.current.benelux
61
+ end
62
+
63
+
64
+ def Benelux.included(klass)
65
+ timed_methods[klass] = [] unless timed_methods.has_key? klass
66
+ end
67
+
68
+ def Benelux.timed_method? klass, meth
69
+ !timed_methods[klass].nil? && timed_methods[klass].member?(meth)
70
+ end
71
+
72
+ def Benelux.add_timer klass, meth
73
+ raise NotSupported, klass unless Benelux.supported? klass
74
+ raise AlreadyTimed, klass if Benelux.timed_method? klass, meth
75
+ prepare_object klass
76
+ meth_alias = rename_method klass, meth
77
+ timed_methods[klass] << meth
78
+ klass.module_eval generate_timer_str(meth_alias, meth)
79
+ end
80
+
81
+ def Benelux.add_tally obj, meth
82
+ end
83
+
84
+ def Benelux.name(*names)
85
+ names.flatten.collect { |n| n.to_s }.join('_')
86
+ end
87
+
88
+ private
89
+ def Benelux.prepare_object obj
90
+ obj.extend Attic unless obj.kind_of?(Attic)
91
+ unless obj.kind_of?(Benelux)
92
+ obj.attic :benelux
93
+ obj.send :include, Benelux
94
+ end
95
+ end
96
+
97
+ def Benelux.rename_method(obj, meth)
98
+ ## NOTE: This is commented out so we can include
99
+ ## Benelux definitions before all classes are loaded.
100
+ ##unless obj.respond_to? meth
101
+ ## raise NoMethodError, "undefined method `#{meth}' for #{obj}:Class"
102
+ ##end
103
+ thread_id, call_id = Thread.current.object_id.abs, obj.object_id.abs
104
+ meth_alias = "__benelux_#{meth}_#{thread_id}_#{call_id}"
105
+ obj.module_eval do
106
+ alias_method meth_alias, meth
107
+ end
108
+ meth_alias
109
+ end
110
+
111
+ def Benelux.generate_timer_str(meth_alias, meth)
112
+ %Q{
113
+ def #{meth}(*args, &block)
114
+ # We only need to do these things once.
115
+ if self.benelux.nil?
116
+ self.benelux = Benelux::Timeline.new
117
+ Benelux.store_thread_reference
118
+ end
119
+ ref = self.object_id.abs.to_s << args.object_id.abs.to_s
120
+ self.benelux.add_mark_open ref, :'#{meth}'
121
+ ret = #{meth_alias}(*args, &block)
122
+ self.benelux.add_mark_close ref, :'#{meth}'
123
+ ret
124
+ end
125
+ }
126
+ end
127
+
128
+ end
129
+
130
+
@@ -0,0 +1,37 @@
1
+ module Benelux
2
+ class Mark < Time
3
+ attr_accessor :name
4
+ attr_accessor :thread_id
5
+ attr_accessor :call_id
6
+ def self.now(n=nil,c=nil,t=nil)
7
+ v = super()
8
+ v.name, v.call_id, v.thread_id = n, c, t
9
+ v
10
+ end
11
+ def inspect(reftime=nil)
12
+ val = reftime.nil? ? self.to_f : (self.to_f - reftime.to_f)
13
+ args = [self.class, self.hexoid, self.name, val, thread_id, call_id]
14
+ "#<%s:%s name=%s at=%f thread_id=%s call_id=%s>" % args
15
+ end
16
+ def to_s(reftime=nil)
17
+ val = reftime.nil? ? self.to_f : (self.to_f - reftime.to_f)
18
+ val.to_s
19
+ end
20
+ def ==(other)
21
+ return false unless other.respond_to? :call_id
22
+ self.name == other.name &&
23
+ self.thread_id == other.thread_id &&
24
+ self.call_id == other.call_id &&
25
+ self.to_f == self.to_f
26
+ end
27
+ def same_timeline?(other)
28
+ return false unless other.respond_to? :thread_id
29
+ self.thread_id == other.thread_id
30
+ end
31
+ def same_call?(other)
32
+ return false unless other.respond_to? :call_id
33
+ self.thread_id == other.thread_id &&
34
+ self.call_id == other.call_id
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,6 @@
1
+
2
+
3
+ class Thread
4
+ extend Attic
5
+ attic :benelux
6
+ end
@@ -0,0 +1,84 @@
1
+
2
+ module Benelux
3
+ #
4
+ # |------+----+--+----+----|
5
+ # |
6
+ # 0.02
7
+ class Timeline < Array
8
+
9
+ def each(*args, &blk)
10
+ if args.empty?
11
+ super(&blk)
12
+ else
13
+ self.marks(*args).each(&blk)
14
+ end
15
+ end
16
+
17
+ ##def between(*names)
18
+ ## name_s, name_e = *names.collect { |n| Benelux.name n }
19
+ ## time_s, time_e = at(name_s), at(name_e)
20
+ ## time_e.first.to_f - time_s.first.to_f
21
+ ##end
22
+ ##def duration(*names)
23
+ ## name = Benelux.name *names
24
+ ## name_s, name_e = "#{name}_a", "#{name}_z"
25
+ ## between(name_s, name_e)
26
+ ##end
27
+
28
+ #
29
+ # obj.region(:execute) =>
30
+ # [[:execute_a, :execute_z], [:execute_a, :execute_z]]
31
+ #
32
+ def regions(*names)
33
+
34
+ end
35
+
36
+ #
37
+ # obj.marks(:execute_a, :execute_z, :do_request_a) =>
38
+ # [:execute_a, :do_request_a, :do_request_a, :execute_z]
39
+ #
40
+ def marks(*names)
41
+ names = names.flatten.collect { |n| n.to_s }
42
+ self.benelux.select do |mark|
43
+ names.member? mark.name.to_s
44
+ end
45
+ end
46
+
47
+ def duration(name)
48
+ name_s = Benelux.name name, SUFFIX_START
49
+ name_e = Benelux.name name, SUFFIX_END
50
+ end
51
+
52
+ def add_mark(call_id, name)
53
+ thread_id = Thread.current.object_id.abs
54
+ mark = Benelux::Mark.now(name, call_id, thread_id)
55
+ Benelux.thread_timeline << mark
56
+ self << mark
57
+ end
58
+
59
+ def add_mark_open(call_id, name)
60
+ add_mark call_id, Benelux.name(name, SUFFIX_START)
61
+ end
62
+
63
+ def add_mark_close(call_id, name)
64
+ add_mark call_id, Benelux.name(name, SUFFIX_END)
65
+ end
66
+
67
+ def to_line
68
+ marks = self.sort
69
+ str, prev = [], marks.first
70
+ marks.each do |mark|
71
+ str << "%s(%s):%.4f" % [mark.name, mark.thread_id, mark.to_s(prev)]
72
+ prev = mark
73
+ end
74
+ str.join('; ')
75
+ end
76
+ def +(other)
77
+ self << other
78
+ self.flatten
79
+ end
80
+ # Needs to compare thread id and call id.
81
+ #def <=>(other)
82
+ #end
83
+ end
84
+ end
@@ -0,0 +1,69 @@
1
+
2
+ group "Benelux"
3
+
4
+ library :benelux, 'lib'
5
+
6
+ tryouts "Basics" do
7
+
8
+ setup do
9
+ class ::Sleeper
10
+ def do_something() sleep rand/3 end
11
+ end
12
+ end
13
+
14
+ drill "Add timers to existing objects", true do
15
+ Benelux.add_timer Sleeper, :do_something
16
+ Sleeper.new.respond_to? :benelux
17
+ end
18
+
19
+ dream :class, Hash
20
+ dream { Hash[ Sleeper => [:do_something] ] }
21
+ drill "Benelux keeps track of timed objects" do
22
+ Benelux.timed_objects
23
+ end
24
+
25
+ dream [:do_something]
26
+ drill "A Benelux object has a benelux_timers method" do
27
+ Sleeper.new.benelux_timers
28
+ end
29
+
30
+ dream :class, Benelux::Timeline
31
+ dream :size, 10 # 5 * 2 = 10 (marks are stored for the method start and end)
32
+ drill "Creates a timeline" do
33
+ sleeper = Sleeper.new
34
+ 5.times { sleeper.do_something }
35
+ sleeper.benelux
36
+ end
37
+
38
+ dream :size, 4
39
+ drill "Timelines are stored per object" do
40
+ sleeper = Sleeper.new
41
+ Thread.new do
42
+ 2.times { sleeper.do_something }
43
+ end.join
44
+ sleeper.benelux
45
+ end
46
+
47
+ dream :class, Benelux::Timeline
48
+ dream :size, 10
49
+ drill "Creates a timeline for the thread" do
50
+ Benelux.thread_timeline
51
+ end
52
+
53
+ dream :class, Benelux::Timeline
54
+ dream :size, 14
55
+ drill "Creates a global timeline" do
56
+ Benelux.timeline
57
+ end
58
+
59
+ end
60
+
61
+
62
+ tryouts "Not supported" do
63
+
64
+ dream :exception, Benelux::NotSupported
65
+ drill "Class is not supported" do
66
+ Benelux.add_timer Class, :new
67
+ end
68
+
69
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: benelux
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0.001
5
+ platform: ruby
6
+ authors:
7
+ - Delano Mandelbaum
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-21 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hexoid
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: "Benelux: Little freakin' timers for your Ruby codes"
26
+ email: delano@solutious.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ - LICENSE.txt
34
+ - CHANGES.txt
35
+ files:
36
+ - CHANGES.txt
37
+ - LICENSE.txt
38
+ - README.rdoc
39
+ - Rakefile
40
+ - benelux.gemspec
41
+ - lib/benelux.rb
42
+ - lib/benelux/mark.rb
43
+ - lib/benelux/mixins/thread.rb
44
+ - lib/benelux/timeline.rb
45
+ - tryouts/basic_tryouts.rb
46
+ has_rdoc: true
47
+ homepage: http://github.com/delano/benelux
48
+ licenses: []
49
+
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --line-numbers
53
+ - --title
54
+ - "Benelux: Little freakin' timers for your Ruby codes"
55
+ - --main
56
+ - README.rdoc
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ requirements: []
72
+
73
+ rubyforge_project: benelux
74
+ rubygems_version: 1.3.2
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: "Benelux: Little freakin' timers for your Ruby codes"
78
+ test_files: []
79
+