benelux 0.3.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -18,18 +18,23 @@ module Benelux
18
18
  # regions = Benelux.timeline(track_id).regions(:execute)
19
19
  #
20
20
  class Timeline < Array
21
+ include Selectable
22
+
21
23
  attr_accessor :ranges
24
+ attr_accessor :counts
22
25
  attr_accessor :stats
23
26
  attr_accessor :default_tags
24
27
  attr_reader :caller
25
28
  def initialize(*args)
26
29
  @caller = Kernel.caller
27
- @ranges, @default_tags = [], Benelux::Tags.new
30
+ @counts = SelectableArray.new
31
+ @ranges = SelectableArray.new
32
+ @default_tags = Selectable::Tags.new
28
33
  @stats = Benelux::Stats.new
29
34
  add_default_tag :thread_id => Thread.current.object_id.abs
30
35
  super
31
36
  end
32
- def add_default_tags(tags=Benelux::Tags.new)
37
+ def add_default_tags(tags=Selectable::Tags.new)
33
38
  @default_tags.merge! tags
34
39
  end
35
40
  alias_method :add_default_tag, :add_default_tags
@@ -65,12 +70,8 @@ module Benelux
65
70
  end
66
71
  end
67
72
 
68
- def [](tags={})
69
- #tags = Benelux::TagHelpers.normalize tags
70
- marks = self.select do |mark|
71
- mark.tags >= tags
72
- end
73
- tl = Benelux::Timeline.new marks
73
+ def [](*tags)
74
+ tl = super
74
75
  tl.ranges = @ranges.select do |region|
75
76
  region.tags >= tags
76
77
  end
@@ -87,7 +88,7 @@ module Benelux
87
88
  # obj.ranges(:do_request) =>
88
89
  # [[:do_request_a, :do_request_z], [:do_request_a, ...]]
89
90
  #
90
- def ranges(name=nil, tags=Benelux::Tags.new)
91
+ def ranges(name=nil, tags=Selectable::Tags.new)
91
92
  return @ranges if name.nil?
92
93
  @ranges.select do |range|
93
94
  ret = name.to_s == range.name.to_s &&
@@ -96,11 +97,19 @@ module Benelux
96
97
  end
97
98
  end
98
99
 
100
+ def counts(name=nil, tags=Selectable::Tags.new)
101
+ return @counts if name.nil?
102
+ @counts.select do |count|
103
+ ret = name.to_s == count.name.to_s &&
104
+ (tags.nil? || count.tags >= tags)
105
+ ret
106
+ end
107
+ end
99
108
  #
100
- # obj.ranges(:do_request) =>
101
- # [[:do_request_a, :get_body, :do_request_z], [:do_request_a, ...]]
109
+ # obj.regions(:do_request) =>
110
+ #
102
111
  #
103
- def regions(name=nil, tags=Benelux::Tags.new)
112
+ def regions(name=nil, tags=Selectable::Tags.new)
104
113
  return self if name.nil?
105
114
  self.ranges(name, tags).collect do |base_range|
106
115
  marks = self.sort.select do |mark|
@@ -124,46 +133,47 @@ module Benelux
124
133
  super
125
134
  end
126
135
 
136
+ # TODO: Remove Benelux::Count. Just use Stats!
137
+ def add_count(name, count, tags={})
138
+ tags = tags.merge self.default_tags
139
+ c = Benelux::Count.new(name, count)
140
+ c.add_tags tags
141
+ self.stats.add_group(name)
142
+ self.stats.sample(name, count, c.tags)
143
+ c
144
+ end
145
+
127
146
  def add_mark(name)
128
147
  mark = Benelux::Mark.now(name)
129
- mark.add_tags Benelux.thread_timeline.default_tags
130
148
  mark.add_tags self.default_tags
131
- Benelux.thread_timeline << mark
132
149
  self << mark
133
150
  mark
134
151
  end
135
152
 
136
153
  def add_range(name, from, to)
137
154
  range = Benelux::Range.new(name, from, to)
138
- range.add_tags Benelux.thread_timeline.default_tags
139
155
  range.add_tags self.default_tags
140
- @stats.add_keeper(name)
141
- @stats.send(name).sample(range.duration, range.tags)
142
- @ranges << range
143
- Benelux.thread_timeline.ranges << range
144
- Benelux.thread_timeline.stats.add_keeper(name)
145
- Benelux.thread_timeline.stats.send(name).sample(range.duration, range.tags)
156
+ range.add_tags from.tags
157
+ range.add_tags to.tags
158
+ self.ranges << range
159
+ self.stats.add_group(name)
160
+ self.stats.sample(name, range.duration, range.tags)
146
161
  range
147
162
  end
148
163
 
149
- def to_line
150
- marks = self.sort
151
- end
152
-
153
- def to_line2
154
- marks = self.sort
155
- str, prev = [], marks.first
156
- marks.each do |mark|
157
- str << "%s(%s):%.4f" % [mark.name, mark.thread_id, mark.to_s(prev)]
158
- prev = mark
164
+ def merge!(*timelines)
165
+ timelines.each do |tl|
166
+ self.push *tl
167
+ self.ranges.push *tl.ranges
168
+ self.stats += tl.stats
159
169
  end
160
- str.join('; ')
170
+ self
161
171
  end
172
+
162
173
  def +(other)
163
- self << other
164
- self.ranges += other.ranges
174
+ self.push *other
175
+ self.ranges.push *other.ranges
165
176
  self.stats += other.stats
166
- self.flatten!
167
177
  self
168
178
  end
169
179
  # Needs to compare thread id and call id.
@@ -0,0 +1,20 @@
1
+
2
+
3
+ module Benelux
4
+ class Track
5
+ attr_reader :name
6
+ attr_reader :thread_group
7
+ attr_reader :timeline
8
+ def initialize(n,g=nil)
9
+ @name, @thgrp = n, (g || ThreadGroup.new)
10
+ @timeline = Benelux::Timeline.new
11
+ end
12
+ def add_thread(t=Thread.current)
13
+ @thgrp.add t
14
+ t
15
+ end
16
+ def threads
17
+ @thgrp.list
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,72 @@
1
+
2
+ # = Selectable
3
+ #
4
+ # <strong>Note: Classes that include Selectable must also
5
+ # subclass Array</strong>
6
+ #
7
+ # class Something < Array
8
+ # include Selectable
9
+ # end
10
+ #
11
+ module Selectable
12
+
13
+ class SelectableError < RuntimeError; end
14
+ class TagsNotInitialized < SelectableError; end
15
+
16
+ require 'selectable/tags'
17
+ require 'selectable/object'
18
+
19
+ # Returns a Hash or Array
20
+ def Selectable.normalize(*tags)
21
+ tags.flatten!
22
+ tags = tags.first if tags.first.kind_of?(Hash) || tags.first.kind_of?(Array)
23
+ if tags.is_a?(Hash)
24
+ tags = Hash[tags.collect { |n,v| [n, v.to_s] }]
25
+ else
26
+ tags.collect! { |v| v.to_s }
27
+ end
28
+ tags
29
+ end
30
+
31
+ # Return the objects that match the given tags.
32
+ # This process is optimized for speed so there
33
+ # as few conditions as possible. One result of
34
+ # that decision is that it does not gracefully
35
+ # handle error conditions. For example, if the
36
+ # tags in an object have not been initialized,
37
+ # you will see this error:
38
+ #
39
+ # undefined method `>=' for nil:NilClass
40
+ #
41
+ def filter(*tags)
42
+ tags = Selectable.normalize tags
43
+ # select returns an Array. We want a Selectable.
44
+ items = self.select { |obj| obj.tags >= tags }
45
+ self.class.new items
46
+ end
47
+
48
+
49
+ def filter!(*tags)
50
+ tags = Selectable.normalize tags
51
+ self.delete_if { |obj| obj.tags < tags }
52
+ end
53
+
54
+ def tags
55
+ t = Selectable::Tags.new
56
+ self.each { |o| t.merge o.tags }
57
+ t
58
+ end
59
+
60
+ # Creates an alias for +filter+ called +[]+, but
61
+ # only if [] doesn't already exist in +obj+.
62
+ def self.included(obj)
63
+ alias_method :[], :filter unless obj.method_defined? :[]
64
+ end
65
+ end
66
+
67
+ class SelectableArray < Array
68
+ include Selectable
69
+ end
70
+ class SelectableHash < Hash
71
+ include Selectable
72
+ end
@@ -0,0 +1,63 @@
1
+ #
2
+ # module Selectable
3
+ #
4
+ # class Global
5
+ # attr_reader :names
6
+ # def initialize(*names)
7
+ # @names = []
8
+ # add_groups names
9
+ # end
10
+ # class << self
11
+ # def group_class
12
+ # @group_class || Group
13
+ # end
14
+ # attr_writer :group_class
15
+ # end
16
+ # def group(name)
17
+ # self.send name
18
+ # end
19
+ # # Each group
20
+ # def each(&blk)
21
+ # @names.each { |name| blk.call(group(name)) }
22
+ # end
23
+ # # Each group name, group
24
+ # def each_pair(&blk)
25
+ # @names.each { |name| blk.call(name, group(name)) }
26
+ # end
27
+ # def add_groups(*args)
28
+ # args.flatten.each do |meth|
29
+ # next if has_group? meth
30
+ # @names << meth
31
+ # self.class.send :attr_reader, meth
32
+ # (g = Group.new).name = meth
33
+ # instance_variable_set("@#{meth}", g)
34
+ # end
35
+ # end
36
+ # alias_method :add_group, :add_groups
37
+ # def has_group?(name)
38
+ # @names.member? name
39
+ # end
40
+ # def +(other)
41
+ # if !other.is_a?(Benelux::Stats)
42
+ # raise TypeError, "can't convert #{other.class} into Stats"
43
+ # end
44
+ # other.names.each do |name|
45
+ # add_group name
46
+ # a = self.send(name)
47
+ # a += other.send(name)
48
+ # a
49
+ # end
50
+ # self
51
+ # end
52
+ #
53
+ #
54
+ # class Group < Array
55
+ # include Selectable
56
+ # attr_accessor :name
57
+ # def self.extend(klass)
58
+ # p 111111111111111
59
+ # end
60
+ # end
61
+ #
62
+ # end
63
+ # end
@@ -0,0 +1,42 @@
1
+
2
+ module Selectable
3
+
4
+ # Helper methods for objects with a @tags instance var
5
+ #
6
+ # e.g.
7
+ #
8
+ # class Something
9
+ # include Selectable::Object
10
+ # end
11
+ #
12
+ module Object
13
+ attr_accessor :tags
14
+ def add_tags(tags)
15
+ init_tags!
16
+ @tags.merge! Selectable.normalize tags
17
+ end
18
+ alias_method :add_tag, :add_tags
19
+ def add_tags_quick(tags)
20
+ @tags.merge! tags
21
+ end
22
+ alias_method :add_tag_quick, :add_tags_quick
23
+ def remove_tags(*tags)
24
+ raise TagsNotInitialized if @tags.nil?
25
+ tags.flatten!
26
+ @tags.delete_if { |n,v| tags.member?(n) }
27
+ end
28
+ alias_method :remove_tag, :remove_tags
29
+ def tag_values(*tags)
30
+ raise TagsNotInitialized if @tags.nil?
31
+ tags.flatten!
32
+ ret = @tags.collect { |n,v|
33
+ v if tags.empty? || tags.member?(n)
34
+ }.compact
35
+ ret
36
+ end
37
+ def init_tags!
38
+ @tags ||= Selectable::Tags.new
39
+ end
40
+ end
41
+
42
+ end
@@ -1,47 +1,10 @@
1
1
 
2
2
 
3
- module Benelux
4
-
5
- # Helper methods for objects with a @tags instance var
6
- #
7
- # e.g.
8
- #
9
- # class Something
10
- # include Benelux::TagHelpers
11
- # end
12
- #
13
- module TagHelpers
14
- attr_accessor :tags
15
- def add_tags(tags)
16
- @tags ||= Benelux::Tags.new
17
- @tags.merge! tags
18
- end
19
- alias_method :add_tag, :add_tags
20
- def remove_tags(*tags)
21
- tags.flatten!
22
- @tags ||= Benelux::Tags.new
23
- @tags.delete_if { |n,v| tags.member?(n) }
24
- end
25
- alias_method :remove_tag, :remove_tags
26
- def tag_values(*tags)
27
- tags.flatten!
28
- @tags ||= Benelux::Tags.new
29
- ret = @tags.collect { |n,v|
30
- p [:n, v]
31
- v if tags.empty? || tags.member?(n)
32
- }.compact
33
- ret
34
- end
35
- def self.normalize(tags={})
36
- tags = tags.first if tags.kind_of?(Array) && tags.first.kind_of?(Hash)
37
- tags = [tags].flatten unless tags.kind_of?(Hash)
38
- tags
39
- end
40
- end
3
+ module Selectable
41
4
 
42
5
  # An example of filtering an Array of tagged objects based
43
6
  # on a provided Hash of tags or Array of tag values. +obj+
44
- # in this case would be an object that includes TagHelpers.
7
+ # in this case would be an object that includes Taggable.
45
8
  #
46
9
  # class Something
47
10
  # def [](tags={})
@@ -67,9 +30,8 @@ module Benelux
67
30
  end
68
31
 
69
32
  def ==(other)
70
- # other = Benelux::TagHelpers.normalize other
71
33
  if other.is_a?(Array)
72
- (self.values & other).sort == other.sort
34
+ self.values.sort == other.sort
73
35
  else
74
36
  super(other)
75
37
  end
@@ -87,13 +49,12 @@ module Benelux
87
49
  # a > [2, 1] # => false
88
50
  #
89
51
  def <=>(b)
90
- #other = Benelux::TagHelpers.normalize other
91
52
  return 0 if self == b
92
53
  self.send :"compare_#{b.class}", b
93
54
  end
94
55
 
95
- def >(other) (self <=> other) > 0 end
96
- def <(other) (self <=> other) < 0 end
56
+ def >(other) (self <=> other) > 0 end
57
+ def <(other) (self <=> other) < 0 end
97
58
 
98
59
  def <=(other) (self <=> other) <= 0 end
99
60
  def >=(other) (self <=> other) >= 0 end
@@ -105,12 +66,25 @@ module Benelux
105
66
  return -1 unless (a.values_at(*b.keys) & b.values).size >= b.size
106
67
  1
107
68
  end
108
- alias_method :"compare_Benelux::Tags", :compare_Hash
69
+ alias_method :"compare_Selectable::Tags", :compare_Hash
109
70
 
110
71
  def compare_Array(b)
111
72
  return -1 unless (self.values & b).size >= b.size
112
73
  1
113
74
  end
75
+
76
+ def method_missing(meth, *args)
77
+ raise SelectableError, "#{meth}: #{args.first} is not a Hash or Array"
78
+ end
79
+
80
+ ## NOTE: This is helpful but defensive. Ponder!
81
+ ##def compare_forced_array(b)
82
+ ## compare_Array([b])
83
+ ##end
84
+ ##alias_method :compare_String, :compare_forced_array
85
+ ##alias_method :compare_Symbol, :compare_forced_array
86
+ ##alias_method :compare_Fixnum, :compare_forced_array
114
87
 
115
88
  end
89
+
116
90
  end
@@ -3,13 +3,30 @@ group "Benelux"
3
3
 
4
4
  library :benelux, 'lib'
5
5
  tryouts "Calculator" do
6
-
6
+ set :base, Benelux::Stats::Calculator.new
7
7
  dream :class, Benelux::Stats::Calculator
8
8
  dream :n, 10
9
+ dream :sum, 45
10
+ dream :sumsq, 285
11
+ dream :min, 0
12
+ dream :max, 9
13
+ dream :proc, lambda { |calc| calc.sd.to_i == 3 }
9
14
  drill "can keep stats" do
10
- keeper = Benelux::Stats::Calculator.new
11
- 10.times { keeper.sample(rand) }
12
- keeper
15
+ 10.times { |i| base.sample(i) }
16
+ base
17
+ end
18
+
19
+ dream true
20
+ drill "can add stats" do
21
+ by_sample = Benelux::Stats::Calculator.new
22
+ 10.times { |i| by_sample.sample(i) }
23
+ by_sample += base
24
+ by_merge = Benelux::Stats::Calculator.new
25
+ by_merge.merge! base
26
+ by_merge.merge! base
27
+ stash :sample, by_sample
28
+ stash :merge, by_merge
29
+ by_sample == by_merge
13
30
  end
14
31
 
15
32
  end