benelux 0.3.2 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|