utilrb 2.0.2.b2 → 2.1.0.rc1

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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.boring +40 -0
  3. data/.gitignore +13 -0
  4. data/.travis.yml +5 -0
  5. data/CMakeLists.txt +18 -0
  6. data/Gemfile +3 -0
  7. data/Makefile +8 -0
  8. data/Manifest.txt +0 -8
  9. data/{README.rd → README.md} +11 -7
  10. data/Rakefile +16 -63
  11. data/benchmarks/validate_options.rb +79 -0
  12. data/ext/utilrb/extconf.rb +1 -17
  13. data/ext/utilrb/utilrb.cc +0 -23
  14. data/lib/utilrb/column_formatter.rb +8 -5
  15. data/lib/utilrb/common.rb +1 -6
  16. data/lib/utilrb/enumerable/uniq.rb +2 -8
  17. data/lib/utilrb/event_loop.rb +5 -10
  18. data/lib/utilrb/kernel/load_dsl_file.rb +1 -2
  19. data/lib/utilrb/kernel/options.rb +25 -29
  20. data/lib/utilrb/logger/hierarchy.rb +0 -1
  21. data/lib/utilrb/logger/io.rb +3 -3
  22. data/lib/utilrb/logger/root.rb +12 -6
  23. data/lib/utilrb/module/ancestor_p.rb +0 -12
  24. data/lib/utilrb/module/is_singleton.rb +6 -0
  25. data/lib/utilrb/module/singleton_class_p.rb +14 -0
  26. data/lib/utilrb/object/attribute.rb +33 -65
  27. data/lib/utilrb/object/singleton_class.rb +1 -20
  28. data/lib/utilrb/pkgconfig.rb +21 -10
  29. data/lib/utilrb/socket/tcp_server.rb +2 -2
  30. data/lib/utilrb/spawn.rb +1 -1
  31. data/lib/utilrb/test.rb +65 -0
  32. data/lib/utilrb/thread_pool.rb +11 -13
  33. data/lib/utilrb/timepoints.rb +15 -0
  34. data/lib/utilrb/value_set.rb +10 -1
  35. data/lib/utilrb/version.rb +4 -0
  36. data/lib/utilrb/weakref.rb +11 -12
  37. data/lib/utilrb/yard.rb +0 -111
  38. data/lib/utilrb.rb +6 -1
  39. data/lib/yard-utilrb.rb +1 -0
  40. data/manifest.xml +19 -0
  41. data/package.xml +29 -0
  42. data/utilrb.gemspec +27 -0
  43. metadata +56 -107
  44. data/ext/utilrb/proc.c +0 -39
  45. data/ext/utilrb/readline.c +0 -52
  46. data/ext/utilrb/weakref.cc +0 -143
  47. data/lib/utilrb/models/inherited_enumerable.rb +0 -341
  48. data/lib/utilrb/models/registration.rb +0 -115
  49. data/lib/utilrb/module/inherited_enumerable.rb +0 -6
  50. data/lib/utilrb/objectstats.rb +0 -193
  51. data/lib/utilrb/ruby_object_graph.rb +0 -384
  52. data/test/data/test_pkgconfig.pc +0 -9
  53. data/test/data/test_pkgconfig_empty.pc +0 -10
  54. data/test/test_array.rb +0 -15
  55. data/test/test_config.rb +0 -4
  56. data/test/test_dir.rb +0 -22
  57. data/test/test_enumerable.rb +0 -119
  58. data/test/test_event_loop.rb +0 -407
  59. data/test/test_exception.rb +0 -38
  60. data/test/test_gc.rb +0 -34
  61. data/test/test_hash.rb +0 -102
  62. data/test/test_kernel.rb +0 -300
  63. data/test/test_logger.rb +0 -204
  64. data/test/test_misc.rb +0 -42
  65. data/test/test_models.rb +0 -212
  66. data/test/test_module.rb +0 -126
  67. data/test/test_object.rb +0 -77
  68. data/test/test_objectstats.rb +0 -26
  69. data/test/test_pkgconfig.rb +0 -84
  70. data/test/test_proc.rb +0 -31
  71. data/test/test_set.rb +0 -19
  72. data/test/test_thread_pool.rb +0 -409
  73. data/test/test_time.rb +0 -47
  74. data/test/test_unbound_method.rb +0 -23
  75. data/test/test_weakref.rb +0 -81
@@ -1,341 +0,0 @@
1
- require 'utilrb/object/attribute'
2
- require 'utilrb/object/singleton_class'
3
- require 'utilrb/enumerable/uniq'
4
- require 'utilrb/module/include'
5
-
6
- module Utilrb
7
- module Models
8
- # Helper method for inherited_enumerable
9
- #
10
- # It is called in the context of the singleton class of the module/class on
11
- # which inherited_enumerable is called
12
- def define_inherited_enumerable(name, attribute_name = name, options = Hash.new, &init) # :nodoc:
13
- # Set up the attribute accessor
14
- attribute(attribute_name, &init)
15
- class_eval { private "#{attribute_name}=" }
16
-
17
- promote = method_defined?("promote_#{name}")
18
- options[:enum_with] ||= :each
19
-
20
- class_eval <<-EOF, __FILE__, __LINE__+1
21
- def all_#{name}; each_#{name}.to_a end
22
- def self_#{name}; @#{attribute_name} end
23
- EOF
24
-
25
- if options[:map]
26
- class_eval <<-EOF, __FILE__, __LINE__+1
27
- def find_#{name}(key)
28
- raise ArgumentError, "nil cannot be used as a key in find_#{name}" if !key
29
- each_#{name}(key, true) do |value|
30
- return value
31
- end
32
- nil
33
- end
34
- def has_#{name}?(key)
35
- ancestors = self.ancestors
36
- if ancestors.first != self
37
- ancestors.unshift self
38
- end
39
- for klass in ancestors
40
- if klass.instance_variable_defined?(:@#{attribute_name})
41
- return true if klass.#{attribute_name}.has_key?(key)
42
- end
43
- end
44
- false
45
- end
46
- EOF
47
- end
48
-
49
- class_eval <<-EOF, __FILE__, __LINE__+1
50
- def clear_#{attribute_name}
51
- #{attribute_name}.clear
52
- for klass in ancestors
53
- if klass.instance_variable_defined?(:@#{attribute_name})
54
- klass.#{attribute_name}.clear
55
- end
56
- end
57
- end
58
- EOF
59
-
60
- if !promote
61
- if options[:map]
62
- define_inherited_enumerable_map_without_promotion(name, attribute_name, options)
63
- else
64
- define_inherited_enumerable_nomap_without_promotion(name, attribute_name, options)
65
- end
66
- else
67
- if options[:map]
68
- define_inherited_enumerable_map_with_promotion(name, attribute_name, options)
69
- else
70
- define_inherited_enumerable_nomap_with_promotion(name, attribute_name, options)
71
- end
72
- end
73
- end
74
-
75
- def define_inherited_enumerable_map_without_promotion(name, attribute_name, options)
76
- class_eval <<-EOF, __FILE__, __LINE__+1
77
- def each_#{name}(key = nil, uniq = true)
78
- if !block_given?
79
- return enum_for(:each_#{name}, key, uniq)
80
- end
81
-
82
- ancestors = self.ancestors
83
- if ancestors.first != self
84
- ancestors.unshift self
85
- end
86
- if key
87
- for klass in ancestors
88
- if klass.instance_variable_defined?(:@#{attribute_name})
89
- if klass.#{attribute_name}.has_key?(key)
90
- yield(klass.#{attribute_name}[key])
91
- return self if uniq
92
- end
93
- end
94
- end
95
- elsif !uniq
96
- for klass in ancestors
97
- if klass.instance_variable_defined?(:@#{attribute_name})
98
- klass.#{attribute_name}.#{options[:enum_with]} do |el|
99
- yield(el)
100
- end
101
- end
102
- end
103
- else
104
- seen = Set.new
105
- for klass in ancestors
106
- if klass.instance_variable_defined?(:@#{attribute_name})
107
- klass.#{attribute_name}.#{options[:enum_with]} do |el|
108
- unless seen.include?(el.first)
109
- seen << el.first
110
- yield(el)
111
- end
112
- end
113
- end
114
- end
115
-
116
- end
117
- self
118
- end
119
- EOF
120
- end
121
-
122
- def define_inherited_enumerable_nomap_without_promotion(name, attribute_name, options)
123
- class_eval <<-EOF, __FILE__, __LINE__+1
124
- def each_#{name}
125
- if !block_given?
126
- return enum_for(:each_#{name})
127
- end
128
-
129
- ancestors = self.ancestors
130
- if ancestors.first != self
131
- ancestors.unshift self
132
- end
133
- for klass in ancestors
134
- if klass.instance_variable_defined?(:@#{attribute_name})
135
- klass.#{attribute_name}.#{options[:enum_with]} { |el| yield(el) }
136
- end
137
- end
138
- self
139
- end
140
- EOF
141
- end
142
-
143
- def define_inherited_enumerable_map_with_promotion(name, attribute_name, options)
144
- class_eval <<-EOF, __FILE__, __LINE__+1
145
- def each_#{name}(key = nil, uniq = true)
146
- if !block_given?
147
- return enum_for(:each_#{name}, key, uniq)
148
- end
149
-
150
- ancestors = self.ancestors
151
- if ancestors.first != self
152
- ancestors.unshift self
153
- end
154
- if key
155
- promotions = []
156
- for klass in ancestors
157
- if klass.instance_variable_defined?(:@#{attribute_name})
158
- if klass.#{attribute_name}.has_key?(key)
159
- value = klass.#{attribute_name}[key]
160
- for p in promotions
161
- value = p.promote_#{name}(key, value)
162
- end
163
- yield(value)
164
- return self if uniq
165
- end
166
- end
167
- promotions.unshift(klass) if klass.respond_to?("promote_#{name}")
168
- end
169
- elsif !uniq
170
- promotions = []
171
- for klass in ancestors
172
- if klass.instance_variable_defined?(:@#{attribute_name})
173
- klass.#{attribute_name}.#{options[:enum_with]} do |key, value|
174
- for p in promotions
175
- value = p.promote_#{name}(key, value)
176
- end
177
- yield(key, value)
178
- end
179
- end
180
- promotions.unshift(klass) if klass.respond_to?("promote_#{name}")
181
- end
182
- else
183
- seen = Set.new
184
- promotions = []
185
- for klass in ancestors
186
- if klass.instance_variable_defined?(:@#{attribute_name})
187
- klass.#{attribute_name}.#{options[:enum_with]} do |key, value|
188
- unless seen.include?(key)
189
- for p in promotions
190
- value = p.promote_#{name}(key, value)
191
- end
192
- seen << key
193
- yield(key, value)
194
- end
195
- end
196
- end
197
- promotions.unshift(klass) if klass.respond_to?("promote_#{name}")
198
- end
199
- end
200
- self
201
- end
202
- EOF
203
- end
204
-
205
- def define_inherited_enumerable_nomap_with_promotion(name, attribute_name, options)
206
- class_eval <<-EOF, __FILE__, __LINE__+1
207
- def each_#{name}
208
- if !block_given?
209
- return enum_for(:each_#{name})
210
- end
211
-
212
- ancestors = self.ancestors
213
- if ancestors.first != self
214
- ancestors.unshift self
215
- end
216
- promotions = []
217
- for klass in ancestors
218
- if klass.instance_variable_defined?(:@#{attribute_name})
219
- klass.#{attribute_name}.#{options[:enum_with]} do |value|
220
- for p in promotions
221
- value = p.promote_#{name}(value)
222
- end
223
- yield(value)
224
- end
225
- end
226
- promotions.unshift(klass) if klass.respond_to?("promote_#{name}")
227
- end
228
- self
229
- end
230
- EOF
231
- end
232
-
233
- # Defines an attribute as being enumerable in the class instance and in the
234
- # whole class inheritance hierarchy. More specifically, it defines a
235
- # <tt>each_#{name}(&iterator)</tt> instance method and a <tt>each_#{name}(&iterator)</tt>
236
- # class method which iterates (in order) on
237
- # - the instance #{name} attribute
238
- # - the singleton class #{name} attribute
239
- # - the class #{name} attribute
240
- # - the superclass #{name} attribute
241
- # - the superclass' superclass #{name} attribute
242
- # ...
243
- #
244
- # This method can be used on modules, in which case the module is used as if
245
- # it was part of the inheritance hierarchy.
246
- #
247
- # The +name+ option defines the enumeration method name (+value+ will
248
- # define a +each_value+ method). +attribute_name+ defines the attribute
249
- # name. +init+ is a block called to initialize the attribute.
250
- # Valid options in +options+ are:
251
- # map::
252
- # If true, the attribute should respond to +[]+. In that case, the
253
- # enumeration method is each_value(key = nil, uniq = false) If +key+ is
254
- # given, we iterate on the values given by <tt>attribute[key]</tt>. If
255
- # +uniq+ is true, the enumeration will yield at most one value for each
256
- # +key+ found (so, if both +key+ and +uniq+ are given, the enumeration
257
- # yields at most one value). See the examples below
258
- # enum_with:: the enumeration method of the enumerable, if it is not +each+
259
- #
260
- # === Example
261
- # Let's define some classes and look at the ancestor chain
262
- #
263
- # class A; end
264
- # module M; end
265
- # class B < A; include M end
266
- # A.ancestors # => [A, Object, Kernel]
267
- # B.ancestors # => [B, M, A, Object, Kernel]
268
- #
269
- # ==== Attributes for which 'map' is not set
270
- #
271
- # class A
272
- # inherited_enumerable("value", "values") do
273
- # Array.new
274
- # end
275
- # end
276
- # module M
277
- # inherited_enumerable("mod") do
278
- # Array.new
279
- # end
280
- # end
281
- #
282
- # A.values << 1 # => [1]
283
- # B.values << 2 # => [2]
284
- # M.mod << 1 # => [1]
285
- # b = B.new
286
- # class << b
287
- # self.values << 3 # => [3]
288
- # self.mod << 4 # => [4]
289
- # end
290
- # M.mod << 2 # => [1, 2]
291
- #
292
- # A.enum_for(:each_value).to_a # => [1]
293
- # B.enum_for(:each_value).to_a # => [2, 1]
294
- # b.singleton_class.enum_for(:each_value).to_a # => [3, 2, 1]
295
- # b.singleton_class.enum_for(:each_mod).to_a # => [4, 1, 2]
296
- #
297
- # ==== Attributes for which 'map' is set
298
- #
299
- # class A
300
- # inherited_enumerable("mapped", "map", :map => true) do
301
- # Hash.new { |h, k| h[k] = Array.new }
302
- # end
303
- # end
304
- #
305
- # A.map['name'] = 'A' # => "A"
306
- # A.map['universe'] = 42
307
- # B.map['name'] = 'B' # => "B"
308
- # B.map['half_of_it'] = 21
309
- #
310
- # Let's see what happens if we don't specify the key option.
311
- # A.enum_for(:each_mapped).to_a # => [["name", "A"], ["universe", 42]]
312
- # If the +uniq+ option is set (the default), we see only B's value for 'name'
313
- # B.enum_for(:each_mapped).to_a # => [["half_of_it", 21], ["name", "B"], ["universe", 42]]
314
- # If the +uniq+ option is not set, we see both values for 'name'. Note that
315
- # since 'map' is a Hash, the order of keys in one class is not guaranteed.
316
- # Nonetheless, we have the guarantee that values from B appear before
317
- # those from A
318
- # B.enum_for(:each_mapped, nil, false).to_a # => [["half_of_it", 21], ["name", "B"], ["name", "A"], ["universe", 42]]
319
- #
320
- #
321
- # Now, let's see how 'key' behaves
322
- # A.enum_for(:each_mapped, 'name').to_a # => ["A"]
323
- # B.enum_for(:each_mapped, 'name').to_a # => ["B"]
324
- # B.enum_for(:each_mapped, 'name', false).to_a # => ["B", "A"]
325
- #
326
- def inherited_enumerable(name, attribute_name = name, options = Hash.new, &init)
327
- singleton_class.class_eval { define_inherited_enumerable(name, attribute_name, options, &init) }
328
-
329
- if is_a?(Module) && !is_a?(Class)
330
- unless const_defined_here?(:ClassExtension)
331
- const_set(:ClassExtension, Module.new)
332
- end
333
- class_extension = const_get(:ClassExtension)
334
- class_extension.class_eval do
335
- define_inherited_enumerable(name, attribute_name, options, &init)
336
- end
337
- end
338
- end
339
- end
340
- end
341
-
@@ -1,115 +0,0 @@
1
- require 'facets/kernel/call_stack'
2
- require 'utilrb/object/attribute'
3
- require 'utilrb/module/attr_predicate'
4
- module Utilrb
5
- module Models
6
-
7
- # Handling of registration of model hierarchies
8
- #
9
- # It depends on the mixed-in object to provide a #supermodel method that
10
- # returns the model that is parent of +self+
11
- module Registration
12
- # The place where this model got defined in the source code
13
- # The tuple is (file,lineno,method), and can be obtained with
14
- # facet's #call_stack
15
- # @return [Array<(String,Integer,Symbol)>]
16
- attr_accessor :definition_location
17
-
18
- # Tells {#clear_submodels} whether this model should be removed from
19
- # the model set or not. The default is false (it should be removed)
20
- #
21
- # @return [Boolean]
22
- attr_predicate :permanent_model?, true
23
-
24
- # [ValueSet] the set of models that are children of this one
25
- attribute(:submodels) { ValueSet.new }
26
-
27
- # Returns the model that is parent of this one
28
- #
29
- # The default implementation returns superclass if it is extended by
30
- # this Registration module, and nil otherwise
31
- def supermodel
32
- if superclass.respond_to?(:register_submodel)
33
- superclass
34
- end
35
- end
36
-
37
- # Call to register a model that is a submodel of +self+
38
- def register_submodel(klass)
39
- if !klass.definition_location
40
- klass.definition_location = call_stack
41
- end
42
-
43
- if klass.name && !klass.permanent_model?
44
- begin
45
- if constant("::#{klass.name}") == klass
46
- klass.permanent_model = true
47
- end
48
- rescue NameError
49
- end
50
- end
51
-
52
- submodels << klass
53
- if m = supermodel
54
- m.register_submodel(klass)
55
- end
56
- end
57
-
58
- # Enumerates all models that are submodels of this class
59
- def each_submodel
60
- return enum_for(:each_submodel) if !block_given?
61
- submodels.each do |obj|
62
- yield(obj)
63
- end
64
- end
65
-
66
- # Clears all registered submodels
67
- def clear_submodels
68
- children = self.submodels.find_all { |m| !m.permanent_model? }
69
- if !deregister_submodels(children)
70
- return
71
- end
72
-
73
- # This contains the permanent submodels
74
- #
75
- # We can call #clear_submodels while iterating here as it is a
76
- # constraint that all models in #submodels are permanent (and
77
- # will therefore not be removed)
78
- submodels.each { |m| m.clear_submodels }
79
- # And this the non-permanent ones
80
- children.each { |m| m.clear_submodels }
81
- true
82
- end
83
-
84
- # Deregisters a set of submodels on this model and all its
85
- # supermodels
86
- #
87
- # This is usually not called directly. Use #clear_submodels instead
88
- #
89
- # @param [ValueSet] set the set of submodels to remove
90
- def deregister_submodels(set)
91
- current_size = submodels.size
92
- submodels.difference!(set.to_value_set)
93
- if (submodels.size != current_size)
94
- if m = supermodel
95
- m.deregister_submodels(set)
96
- end
97
- true
98
- else false
99
- end
100
- end
101
-
102
- # Registers submodels when a subclass is created (when models are
103
- # represented as classes)
104
- def inherited(subclass)
105
- subclass.definition_location = call_stack
106
- super
107
- register_submodel(subclass)
108
- subclass.permanent_model = true
109
- end
110
- end
111
- end
112
- end
113
-
114
-
115
-
@@ -1,6 +0,0 @@
1
- require 'utilrb/models/inherited_enumerable'
2
-
3
- class Module
4
- include Utilrb::Models
5
- end
6
-
@@ -1,193 +0,0 @@
1
- require 'utilrb/gc/force'
2
- require 'utilrb/object/attribute'
3
- require 'utilrb/column_formatter'
4
-
5
- module ObjectStats
6
- # The count of objects currently allocated
7
- #
8
- # It allocates no objects, which means that if
9
- # a = ObjectStats.count
10
- # b = ObjectStats.count
11
- # then a == b
12
- def self.count
13
- count = 0
14
- ObjectSpace.each_object { |obj| count += 1 }
15
-
16
- count
17
- end
18
-
19
- # Returns a klass => count hash counting the currently allocated objects
20
- #
21
- # It allocates 1 Hash, which is included in the count
22
- def self.count_by_class(threshold = nil)
23
- by_class = Hash.new(0)
24
- ObjectSpace.each_object { |obj|
25
- by_class[obj.class] += 1
26
- by_class
27
- }
28
- if threshold
29
- by_class.delete_if { |kl, count| count < threshold }
30
- end
31
-
32
- by_class
33
- end
34
-
35
- LIVE_OBJECTS_KEY = :live_objects
36
-
37
- # Profiles how much objects has been allocated by the block. Returns a
38
- # klass => count hash like count_by_class
39
- #
40
- # If alive is true, then only live objects are returned.
41
- def self.profile(alive = false)
42
- if alive
43
- GC.force
44
- profile do
45
- yield
46
- GC.force
47
- end
48
- end
49
-
50
- already_disabled = GC.disable
51
- before = count_by_class
52
- if ObjectSpace.respond_to?(:live_objects)
53
- before_live_objects = ObjectSpace.live_objects
54
- end
55
- yield
56
- if ObjectSpace.respond_to?(:live_objects)
57
- after_live_objects = ObjectSpace.live_objects
58
- end
59
- after = count_by_class
60
- if after_live_objects
61
- before[LIVE_OBJECTS_KEY] = before_live_objects
62
- after[LIVE_OBJECTS_KEY] = after_live_objects - 1 # correction for yield
63
- end
64
- GC.enable unless already_disabled
65
-
66
- after[Hash] -= 1 # Correction for the call of count_by_class
67
- profile = before.
68
- merge(after) { |klass, old, new| new - old }.
69
- delete_if { |klass, count| count == 0 }
70
- end
71
- end
72
-
73
- # BenchmarkAllocation is a Benchmark-like interface to benchmark object allocation.
74
- #
75
- # == Formatting
76
- # BenchmarkAllocation formats its output in two ways (see examples below)
77
- # * first, each part of a class path is displayed in its own line, to reduce
78
- # the output width
79
- # * then, output is formatted so that it does not exceed
80
- # BenchmarkAllocation::SCREEN_WIDTH width
81
- #
82
- #
83
- # == Examples
84
- #
85
- # For instance,
86
- #
87
- # require 'utilrb/objectstats'
88
- #
89
- # module Namespace
90
- # class MyClass
91
- # end
92
- # end
93
- #
94
- # BenchmarkAllocation.bm do |x|
95
- # x.report("array") { Array.new }
96
- # x.report("hash") { Hash.new }
97
- # x.report("myclass") { MyClass.new }
98
- # end
99
- #
100
- # will produce the output
101
- #
102
- # Array Hash Namespace::
103
- # MyClass
104
- # array 1 - -
105
- # hash - 1 -
106
- # myclass - - 1
107
- #
108
- # Like Benchmark, a rehearsal benchmark method, BenchmarkAllocation.bmbm
109
- # is provided:
110
- #
111
- # require 'utilrb/objectstats'
112
- # require 'delegate'
113
- #
114
- # module Namespace
115
- # class MyClass
116
- # end
117
- # end
118
- #
119
- # delegate_klass = nil
120
- # BenchmarkAllocation.bmbm do |x|
121
- # x.report("array") { Array.new }
122
- # x.report("hash") { Hash.new }
123
- # x.report("myclass") { Namespace::MyClass.new }
124
- # x.report("delegate") do
125
- # delegate_klass ||= Class.new(DelegateClass(Namespace::MyClass)) do
126
- # def self.name; "Delegate(MyClass)" end
127
- # end
128
- # delegate_klass.new(Namespace::MyClass.new)
129
- # end
130
- # end
131
- #
132
- # produces
133
- #
134
- # Rehearsal --------------------------------------------------------------------------------
135
- #
136
- # Array Class Delegate(MyClass) Hash Namespace:: String
137
- # MyClass
138
- # array 1 - - - - -
139
- # hash - - - 1 - -
140
- # myclass - - - - 1 -
141
- # delegate 5 2 1 2 1 247
142
- # ------------------------------------------------------------------------------------------
143
- #
144
- # Array Delegate(MyClass) Hash Namespace::
145
- # MyClass
146
- # array 1 - - -
147
- # hash - - 1 -
148
- # myclass - - - 1
149
- # delegate - 1 - 1
150
- #
151
- class BenchmarkAllocation
152
- SCREEN_WIDTH = 90
153
- MARGIN = 2
154
-
155
- def self.bm(label_width = nil)
156
- yield(gather = new)
157
- gather.format
158
- end
159
- def self.bmbm(label_width = nil)
160
- yield(gather = new)
161
-
162
- title = "Rehearsal"
163
- puts title + " " + "-" * (SCREEN_WIDTH - title.length - 1)
164
- gather.format
165
- puts "-" * SCREEN_WIDTH
166
-
167
- yield(gather = new)
168
- gather.format
169
- end
170
-
171
- def format(screen_width = SCREEN_WIDTH, margin = MARGIN)
172
- data = profiles.map do |label, line_data|
173
- line_data['label'] = label
174
- line_data
175
- end
176
- ColumnFormatter.from_hashes(data, screen_width)
177
- end
178
-
179
- attribute(:profiles) { Array.new }
180
- def report(label)
181
- result = ObjectStats.profile do
182
- yield
183
- end
184
- result.inject({}) do |result, (klass, count)|
185
- klass = klass.to_s
186
- klass = "unknown" if !klass || klass.empty?
187
- result[klass] = count
188
- result
189
- end
190
- profiles << [label, result]
191
- end
192
- end
193
-