benelux 0.3.2 → 0.4.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/CHANGES.txt +15 -0
- data/README.rdoc +1 -1
- data/benelux.gemspec +15 -4
- data/lib/benelux.rb +141 -172
- data/lib/benelux/count.rb +29 -0
- data/lib/benelux/mark.rb +2 -11
- data/lib/benelux/mixins/symbol.rb +8 -0
- data/lib/benelux/mixins/thread.rb +1 -1
- data/lib/benelux/packer.rb +138 -0
- data/lib/benelux/range.rb +2 -2
- data/lib/benelux/reporter.rb +89 -0
- data/lib/benelux/stats.rb +70 -47
- data/lib/benelux/timeline.rb +45 -35
- data/lib/benelux/track.rb +20 -0
- data/lib/selectable.rb +72 -0
- data/lib/selectable/global.rb +63 -0
- data/lib/selectable/object.rb +42 -0
- data/lib/{benelux → selectable}/tags.rb +19 -45
- data/tryouts/10_stats_tryouts.rb +21 -4
- data/tryouts/{11_tags_tryouts.rb → 11_selectable_tryouts.rb} +38 -2
- data/tryouts/12_selectable_global_tryouts.rb +23 -0
- data/tryouts/20_tracks_tryouts.rb +106 -0
- data/tryouts/30_reporter_tryouts.rb +34 -0
- data/tryouts/30_timeline_tryouts.rb +38 -3
- data/tryouts/proofs/array_performance.rb +33 -0
- metadata +16 -5
- data/tryouts/20_class_methods_tryouts.rb +0 -69
data/lib/benelux/timeline.rb
CHANGED
@@ -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
|
-
@
|
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=
|
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
|
-
|
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=
|
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.
|
101
|
-
#
|
109
|
+
# obj.regions(:do_request) =>
|
110
|
+
#
|
102
111
|
#
|
103
|
-
def regions(name=nil, tags=
|
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
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
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
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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
|
-
|
170
|
+
self
|
161
171
|
end
|
172
|
+
|
162
173
|
def +(other)
|
163
|
-
self
|
164
|
-
self.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
|
data/lib/selectable.rb
ADDED
@@ -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
|
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
|
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
|
-
|
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)
|
96
|
-
def <(other) (self <=> other)
|
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 :"
|
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
|
data/tryouts/10_stats_tryouts.rb
CHANGED
@@ -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
|
-
|
11
|
-
|
12
|
-
|
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
|