ztk 2.3.1 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b8e1ebec45b236ad05a903e06863a0d6579a60d0
4
- data.tar.gz: 44b923bde167cd85317add07f1a2a42f9657563e
3
+ metadata.gz: fbbba71c8a07c8110549bfcee7445288c8ed3172
4
+ data.tar.gz: 8c725fa5f1de381ce76f668e52c7735d87a1429f
5
5
  SHA512:
6
- metadata.gz: 3985319ebe5dab0ade521e48fcd4a1d108f74f11d639aa6c9e2bd77d2ecb8b2599d14002108be5faf602f538887484ef999432eef20235642ad47b9b395623b2
7
- data.tar.gz: ecedf4dd5f8777404e151a4753e350c1e6bdd029b86882a4ad498dcb0be478ae762a81858a7dff727107fa21597000229e48783c988fbdbc2f6558408d97c9c7
6
+ metadata.gz: 4ebd5505c5e8607536a054788d545432011aae08f3243cf9614e9c87c17567009784f014d6dbbc0141e0f117dab5ea3fa0b88dc93f0ed6163a5b280cb81d4de1
7
+ data.tar.gz: 96e9aa8493a4336e5723df3f3f6aed28856108cef55f16c76208cea07cff583895e92ed122d3125c3bc50276806678a957c3250a03747516b301d3507c71ce6f
data/README.md CHANGED
@@ -44,6 +44,10 @@ Zachary's Tool Kit contains a collection of reusable classes meant to simplify d
44
44
 
45
45
  Easily turn linear iterative tasks into parallel tasks and leverage multiple cores to speed up processing of your large sets of data. Read more at the [ZTK::Parallel](http://zpatten.github.io/ztk/ZTK/Parallel.html) documentation.
46
46
 
47
+ - **ZTK::Profiler**
48
+
49
+ Build timing profiles easily with this class. Allows for arbitrary nesting of profiles and provides full reporting. Read more at the [ZTK::Profiler](http://zpatten.github.io/ztk/ZTK/Profiler.html) documentation.
50
+
47
51
  - **ZTK::Report**
48
52
 
49
53
  Console based reporting class which allows you to easily output either list or spreadsheet based reports from sets of data. Read more at the [ZTK::Report](http://zpatten.github.io/ztk/ZTK/Report.html) documentation.
data/lib/ztk.rb CHANGED
@@ -26,6 +26,7 @@ module ZTK
26
26
  require 'ztk/locator'
27
27
  require 'ztk/logger'
28
28
  require 'ztk/parallel'
29
+ require 'ztk/profiler'
29
30
  require 'ztk/pty'
30
31
  require 'ztk/report'
31
32
  require 'ztk/rescue_retry'
@@ -18,7 +18,7 @@ module ZTK
18
18
  # use this library like so:
19
19
  # LOG_LEVEL=DEBUG bin/cucumber-chef ssh
20
20
  #
21
- # = Typical usage:
21
+ # *Typical usage*:
22
22
  #
23
23
  # $logger = ZTK::Logger.new("/dev/null")
24
24
  #
@@ -28,7 +28,7 @@ module ZTK
28
28
  # $logger.error { "This is a error message!" }
29
29
  # $logger.fatal { "This is a fatal message!" }
30
30
  #
31
- # = Simple logger chain:
31
+ # *Simple logger chain*:
32
32
  #
33
33
  # logger = ZTK::Logger.new
34
34
  # logger.loggers << ::Logger.new(STDOUT)
@@ -36,7 +36,7 @@ module ZTK
36
36
  #
37
37
  # logger.debug { "This will be written to STDOUT as well as test.log!" }
38
38
  #
39
- # = Alternate logger chaining:
39
+ # *Alternate logger chaining*:
40
40
  #
41
41
  # logger = ZTK::Logger.new(STDOUT)
42
42
  # logger.loggers << ::Logger.new('test.log')
@@ -0,0 +1,110 @@
1
+ require 'benchmark'
2
+
3
+ module ZTK
4
+
5
+ # Profiler Error Class
6
+ #
7
+ # @author Zachary Patten <zachary AT jovelabs DOT com>
8
+ class ProfilerError < Error; end
9
+
10
+ # Profiler Class
11
+ #
12
+ # A comprehensive timing profiler, this class functions using method_missing
13
+ # to allow the consumer to define timing profiles in an ad hoc manner using
14
+ # a block.
15
+ #
16
+ # *Example Code*:
17
+ #
18
+ # ZTK::Profiler.reset
19
+ #
20
+ # ZTK::Profiler.operation_alpha do
21
+ # ZTK::Profiler.operation_one do
22
+ # ZTK::Profiler.operation_a do
23
+ # sleep(0.1)
24
+ # end
25
+ # ZTK::Profiler.operation_b do
26
+ # sleep(0.1)
27
+ # end
28
+ # ZTK::Profiler.operation_c do
29
+ # sleep(0.1)
30
+ # end
31
+ # end
32
+ # ZTK::Profiler.operation_two do
33
+ # ZTK::Profiler.operation_d do
34
+ # sleep(0.1)
35
+ # end
36
+ # ZTK::Profiler.operation_e do
37
+ # sleep(0.1)
38
+ # end
39
+ # ZTK::Profiler.operation_f do
40
+ # sleep(0.1)
41
+ # end
42
+ # end
43
+ # end
44
+ # ZTK::Profiler.operation_beta do
45
+ # ZTK::Profiler.operation_three do
46
+ # ZTK::Profiler.operation_a do
47
+ # sleep(0.1)
48
+ # end
49
+ # ZTK::Profiler.operation_b do
50
+ # sleep(0.1)
51
+ # end
52
+ # ZTK::Profiler.operation_c do
53
+ # sleep(0.1)
54
+ # end
55
+ # end
56
+ # end
57
+ #
58
+ # ZTK::Profiler.report
59
+ #
60
+ # *Example Output*:
61
+ #
62
+ # --+ OperationAlpha 0.6070s
63
+ # |--+ OperationOne 0.3035s
64
+ # | |--+ OperationA 0.1011s
65
+ # | |--+ OperationB 0.1011s
66
+ # | |--+ OperationC 0.1011s
67
+ # |--+ OperationTwo 0.3035s
68
+ # | |--+ OperationD 0.1011s
69
+ # | |--+ OperationE 0.1011s
70
+ # | |--+ OperationF 0.1011s
71
+ # --+ OperationBeta 0.3034s
72
+ # |--+ OperationThree 0.3034s
73
+ # | |--+ OperationA 0.1011s
74
+ # | |--+ OperationB 0.1011s
75
+ # | |--+ OperationC 0.1011s
76
+ #
77
+ # OperationAlpha: 0.6070s (22.2%)
78
+ # OperationOne: 0.3035s (11.1%)
79
+ # OperationA: 0.2022s (7.4%)
80
+ # OperationB: 0.2022s (7.4%)
81
+ # OperationC: 0.2022s (7.4%)
82
+ # OperationTwo: 0.3035s (11.1%)
83
+ # OperationD: 0.1011s (3.7%)
84
+ # OperationE: 0.1011s (3.7%)
85
+ # OperationF: 0.1011s (3.7%)
86
+ # OperationBeta: 0.3034s (11.1%)
87
+ # OperationThree: 0.3034s (11.1%)
88
+ #
89
+ # Nested Time: 2.7306s
90
+ # Actual Time: 0.9110s
91
+ # Profiled Time: 0.9105s
92
+ # Missing Time: 0.0005s
93
+ #
94
+ # @author Zachary Patten <zachary AT jovelabs DOT com>
95
+ class Profiler
96
+
97
+ require 'ztk/profiler/core'
98
+ require 'ztk/profiler/private'
99
+ require 'ztk/profiler/timer'
100
+
101
+ extend ZTK::Profiler::Core
102
+
103
+ private
104
+
105
+ extend ZTK::Profiler::Private
106
+
107
+ end
108
+
109
+ end
110
+
@@ -0,0 +1,74 @@
1
+ module ZTK
2
+ class Profiler
3
+
4
+ # Profiler Core Functionality
5
+ module Core
6
+ require 'ztk/ui'
7
+
8
+ @@start_time ||= nil
9
+ @@end_time ||= nil
10
+ @@timer_stack ||= Array.new
11
+
12
+ def start
13
+ reset
14
+
15
+ true
16
+ end
17
+
18
+ def stop
19
+ @@end_time ||= Time.now.utc
20
+
21
+ true
22
+ end
23
+
24
+ def reset
25
+ @@start_time = Time.now.utc
26
+ @@end_time = nil
27
+ @@timer_stack = Array.new
28
+ Timer.reset
29
+
30
+ true
31
+ end
32
+
33
+ def method_missing(method_name, *method_args)
34
+ raise "You must supply a block to the profiler method #{method_name.inspect}!" unless block_given?
35
+
36
+ @@start_time ||= Time.now.utc
37
+
38
+ result = nil
39
+ timer = Timer.new(method_name, @@timer_stack.last)
40
+
41
+ @@timer_stack.push(timer)
42
+ timer.benchmark = ::Benchmark.realtime do
43
+ result = yield
44
+ end
45
+ @@timer_stack.pop
46
+
47
+ result
48
+ end
49
+
50
+ def total_time
51
+ stop
52
+ @@end_time - @@start_time
53
+ end
54
+
55
+ def report(options={})
56
+ options = Base.build_config({}, options)
57
+
58
+ stop
59
+
60
+ results = Array.new
61
+
62
+ report_timers(options)
63
+ options.ui.stdout.puts
64
+ results << report_timer_totals(options)
65
+ options.ui.stdout.puts
66
+ results << report_totals(options)
67
+
68
+ results
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,52 @@
1
+ module ZTK
2
+ class Profiler
3
+
4
+ # Profiler Private Functionality
5
+ module Private
6
+
7
+ def report_timers(options={}, parent=nil, depth=0)
8
+ child_timers = Timer.timers_by_parent[parent]
9
+ child_timers.each do |timer|
10
+ prefix = (' |' * (depth))
11
+
12
+ options.ui.stdout.print("%s--+ %s %0.4fs\n" % [ prefix, timer.name.to_s.camelize, timer.benchmark ])
13
+
14
+ report_timers(options, timer, (depth + 1))
15
+ end
16
+
17
+ true
18
+ end
19
+
20
+ def report_timer_totals(options={})
21
+ result = Hash.new
22
+ timer_names = Timer.timers_by_name.keys.compact
23
+ timer_names_camelize = timer_names.map(&:to_s).map(&:camelize)
24
+ max_timer_name_length = (timer_names_camelize.map(&:length).max + 1)
25
+ timer_names.each do |timer_name|
26
+ benchmark_nested = Timer.timers_by_name[timer_name].map(&:benchmark_nested).reduce(&:+)
27
+ result[timer_name] = benchmark_nested
28
+
29
+ options.ui.stdout.print("%#{max_timer_name_length}s: %0.4fs (%-3.1f%%)\n" % [timer_name.to_s.camelize, benchmark_nested, (benchmark_nested / Timer.benchmark_nested_total) * 100])
30
+ end
31
+ result
32
+ end
33
+
34
+ def report_totals(options={})
35
+ times = {
36
+ 'Nested Time' => Timer.benchmark_nested_total,
37
+ 'Actual Time' => Profiler.total_time,
38
+ 'Profiled Time' => Timer.total_time,
39
+ 'Missing Time' => (Profiler.total_time - Timer.total_time)
40
+ }
41
+ max_key_length = (times.keys.map(&:length).max + 1)
42
+ time_format = "%#{max_key_length}s: %0.4fs\n"
43
+
44
+ times.each do |name, time|
45
+ options.ui.stdout.print(time_format % [ name, time ])
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,33 @@
1
+ module ZTK
2
+ class Profiler
3
+
4
+ # Profiler Timer Functionality
5
+ class Timer
6
+ require 'ztk/profiler/timer/class_methods'
7
+
8
+ extend ZTK::Profiler::Timer::ClassMethods
9
+
10
+ attr_accessor :name
11
+ attr_accessor :parent
12
+ attr_accessor :benchmark
13
+
14
+ def initialize(name, parent=nil)
15
+ self.name = name
16
+ self.parent = parent
17
+
18
+ self.class.add(self)
19
+ end
20
+
21
+ def nested_time
22
+ @nested_time ||= self.class.nested_time(self.name, self)
23
+ @nested_time
24
+ end
25
+
26
+ def benchmark_nested
27
+ (self.benchmark - self.nested_time)
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,76 @@
1
+ module ZTK
2
+ class Profiler
3
+ class Timer
4
+
5
+ # Profiler Timer Class Functionality
6
+ module ClassMethods
7
+
8
+ @@timers ||= Array.new
9
+ @@timers_by_name ||= Hash.new { |hash, key| hash[key] = Array.new }
10
+ @@timers_by_parent ||= Hash.new { |hash, key| hash[key] = Array.new }
11
+ @@benchmark_total ||= nil
12
+ @@benchmark_nested_total ||= nil
13
+
14
+ def timers
15
+ @@timers
16
+ end
17
+
18
+ def timers_by_parent
19
+ @@timers_by_parent
20
+ end
21
+
22
+ def timers_by_name
23
+ @@timers_by_name
24
+ end
25
+
26
+ def add(timer)
27
+ @@timers << timer
28
+
29
+ @@timers_by_parent[timer.parent] << timer
30
+ @@timers_by_name[timer.name] << timer
31
+
32
+ true
33
+ end
34
+
35
+ def reset
36
+ @@timers = Array.new
37
+ @@timers_by_name = Hash.new { |hash, key| hash[key] = Array.new }
38
+ @@timers_by_parent = Hash.new { |hash, key| hash[key] = Array.new }
39
+
40
+ true
41
+ end
42
+
43
+ def nested_time(name=nil, parent=nil)
44
+ result = 0.0
45
+
46
+ child_timers = @@timers_by_parent[parent]
47
+ child_timers.each do |child_timer|
48
+ if (child_timer.name == name)
49
+ result += child_timer.benchmark_nested
50
+ end
51
+ result += nested_time(name, child_timer)
52
+ end
53
+
54
+ result
55
+ end
56
+
57
+ def benchmark_total
58
+ @@benchmark_total ||= @@timers.map(&:benchmark).reduce(&:+)
59
+ @@benchmark_total
60
+ end
61
+
62
+ def benchmark_nested_total
63
+ @@benchmark_nested_total ||= @@timers.map(&:benchmark_nested).reduce(&:+)
64
+ @@benchmark_nested_total
65
+ end
66
+
67
+ def total_time
68
+ @@total_time ||= @@timers_by_parent[nil].map(&:benchmark).reduce(&:+)
69
+ @@total_time
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -1,6 +1,6 @@
1
1
  module ZTK
2
2
 
3
3
  # ZTK Version String
4
- VERSION = "2.3.1"
4
+ VERSION = "2.4.0"
5
5
 
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ztk
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zachary Patten
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-25 00:00:00.000000000 Z
11
+ date: 2014-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -315,6 +315,11 @@ files:
315
315
  - lib/ztk/locator.rb
316
316
  - lib/ztk/logger.rb
317
317
  - lib/ztk/parallel.rb
318
+ - lib/ztk/profiler.rb
319
+ - lib/ztk/profiler/core.rb
320
+ - lib/ztk/profiler/private.rb
321
+ - lib/ztk/profiler/timer.rb
322
+ - lib/ztk/profiler/timer/class_methods.rb
318
323
  - lib/ztk/pty.rb
319
324
  - lib/ztk/rake/docs.rb
320
325
  - lib/ztk/report.rb