pretty_stopwatch 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/Rakefile +10 -10
- data/lib/pretty_stopwatch/version.rb +5 -5
- data/lib/pretty_stopwatch.rb +152 -160
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7fcddcb209f62c6aa2dd5590919a588c549cd40a9d2b5719870b9d2d5d5b8f22
|
|
4
|
+
data.tar.gz: 36244820de0bcee5d516eb7c78691dfd0dd3c1b4ad45d35a8e9151da79c41aa3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cb1fc44fb109dd7ed499330f537274071fbdbcae2c9fc0f4ca6811635f63a16fd64c41a3eba3007a137facaa9501866083ed9a320dfec9c36ab4565be8971834
|
|
7
|
+
data.tar.gz: 7fb43e0f69b476c2dc2ab6d41cfed5b85f84501d3044749f129ad161db8f073292618f96d205e52af35f2ddd0e0c7f929fea1e259ec97d703ecd29bc0699d51c
|
data/Rakefile
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "bundler/gem_tasks"
|
|
4
|
-
require "rspec/core/rake_task"
|
|
5
|
-
|
|
6
|
-
RSpec::Core::RakeTask.new(:spec)
|
|
7
|
-
|
|
8
|
-
require "standard/rake"
|
|
9
|
-
|
|
10
|
-
task default: %i[spec standard]
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "rspec/core/rake_task"
|
|
5
|
+
|
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
7
|
+
|
|
8
|
+
require "standard/rake"
|
|
9
|
+
|
|
10
|
+
task default: %i[spec standard]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module PrettyStopwatch
|
|
4
|
-
VERSION = "0.1.
|
|
5
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PrettyStopwatch
|
|
4
|
+
VERSION = "0.1.2"
|
|
5
|
+
end
|
data/lib/pretty_stopwatch.rb
CHANGED
|
@@ -1,160 +1,152 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "pretty_stopwatch/version"
|
|
4
|
-
|
|
5
|
-
#
|
|
6
|
-
# Based on the Guava Stopwatch com.google.common.base.Stopwatch
|
|
7
|
-
# Credit: The Guava Authors
|
|
8
|
-
#
|
|
9
|
-
# = Basic Example:
|
|
10
|
-
# stopwatch = Stopwatch::create_started
|
|
11
|
-
# sleep(0.1)
|
|
12
|
-
# stopwatch.stop # optional
|
|
13
|
-
# puts "slept for #{stopwatch}" # to_s optional
|
|
14
|
-
# Output: "slept for 0.1014ms"
|
|
15
|
-
#
|
|
16
|
-
# = Named Example:
|
|
17
|
-
# stopwatch = Stopwatch::create_started(:foo)
|
|
18
|
-
# sleep(0.1)
|
|
19
|
-
# puts "slept for #{stopwatch.get(:foo)}"
|
|
20
|
-
# Output: "slept for 0.1014ms"
|
|
21
|
-
#
|
|
22
|
-
# = Block Example:
|
|
23
|
-
# stopwatch = Stopwatch::time{sleep 0.1}
|
|
24
|
-
#
|
|
25
|
-
# = Lambda Example:
|
|
26
|
-
# lambda = -> {sleep 0.15}
|
|
27
|
-
# stopwatch = Stopwatch::time(lambda)
|
|
28
|
-
#
|
|
29
|
-
# = Proc Example:
|
|
30
|
-
# proc = Proc.new {sleep 0.15}
|
|
31
|
-
# stopwatch = Stopwatch::time(proc)
|
|
32
|
-
|
|
33
|
-
# stopwatch = Stopwatch::create_started(:foo)
|
|
34
|
-
# sleep(0.1)
|
|
35
|
-
# puts "slept for #{stopwatch.get(:foo)}"
|
|
36
|
-
# Output: "slept for 0.1014ms"
|
|
37
|
-
class Stopwatch
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
@
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def
|
|
56
|
-
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
{
|
|
129
|
-
{
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
def
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
private def format_float(float)
|
|
154
|
-
sprintf('%f', float.round(3)).sub(/\.?0*$/, '')
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "pretty_stopwatch/version"
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# Based on the Guava Stopwatch com.google.common.base.Stopwatch
|
|
7
|
+
# Credit: The Guava Authors
|
|
8
|
+
#
|
|
9
|
+
# = Basic Example:
|
|
10
|
+
# stopwatch = Stopwatch::create_started
|
|
11
|
+
# sleep(0.1)
|
|
12
|
+
# stopwatch.stop # optional
|
|
13
|
+
# puts "slept for #{stopwatch}" # to_s optional
|
|
14
|
+
# Output: "slept for 0.1014ms"
|
|
15
|
+
#
|
|
16
|
+
# = Named Example:
|
|
17
|
+
# stopwatch = Stopwatch::create_started(:foo)
|
|
18
|
+
# sleep(0.1)
|
|
19
|
+
# puts "slept for #{stopwatch.get(:foo)}"
|
|
20
|
+
# Output: "slept for 0.1014ms"
|
|
21
|
+
#
|
|
22
|
+
# = Block Example:
|
|
23
|
+
# stopwatch = Stopwatch::time{sleep 0.1}
|
|
24
|
+
#
|
|
25
|
+
# = Lambda Example:
|
|
26
|
+
# lambda = -> {sleep 0.15}
|
|
27
|
+
# stopwatch = Stopwatch::time(lambda)
|
|
28
|
+
#
|
|
29
|
+
# = Proc Example:
|
|
30
|
+
# proc = Proc.new {sleep 0.15}
|
|
31
|
+
# stopwatch = Stopwatch::time(proc)
|
|
32
|
+
|
|
33
|
+
# stopwatch = Stopwatch::create_started(:foo)
|
|
34
|
+
# sleep(0.1)
|
|
35
|
+
# puts "slept for #{stopwatch.get(:foo)}"
|
|
36
|
+
# Output: "slept for 0.1014ms"
|
|
37
|
+
class Stopwatch
|
|
38
|
+
# Stopwatch methods are not idempotent; it is an error to start or stop a stopwatch that is already in the desired state.
|
|
39
|
+
class IllegalStateError < StandardError
|
|
40
|
+
end
|
|
41
|
+
attr_reader :name
|
|
42
|
+
attr_reader :running
|
|
43
|
+
|
|
44
|
+
def initialize(name = nil, elapsed_nanos = 0) # optional variable
|
|
45
|
+
@name = name
|
|
46
|
+
@start_nanos = nil
|
|
47
|
+
@running = false
|
|
48
|
+
@elapsed_nanos = elapsed_nanos
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def running?
|
|
52
|
+
@running
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def stopped?
|
|
56
|
+
!@running
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private_class_method :new # private constructor
|
|
60
|
+
|
|
61
|
+
class << self
|
|
62
|
+
def create_started(name = nil, elapsed_nanos: 0)
|
|
63
|
+
new(name, elapsed_nanos).start
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def create_unstarted(name = nil, elapsed_nanos: 0)
|
|
67
|
+
new(name, elapsed_nanos)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def time(callable = nil, &block)
|
|
71
|
+
stopwatch = create_started
|
|
72
|
+
if callable
|
|
73
|
+
callable.call
|
|
74
|
+
elsif block
|
|
75
|
+
block.call # yield also valid
|
|
76
|
+
else
|
|
77
|
+
raise "no callable/block given" # todo
|
|
78
|
+
end
|
|
79
|
+
stopwatch.stop
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def start
|
|
84
|
+
raise IllegalStateError, "Stopwatch is already running" if @running
|
|
85
|
+
@running = true
|
|
86
|
+
@start_nanos = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
|
|
87
|
+
self
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def stop
|
|
91
|
+
raise IllegalStateError, "Stopwatch is already stopped" unless @running
|
|
92
|
+
@elapsed_nanos += Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - @start_nanos
|
|
93
|
+
@running = false
|
|
94
|
+
self
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# reset the elapsed time and stop the stopwatch
|
|
98
|
+
def reset
|
|
99
|
+
@running = false
|
|
100
|
+
@elapsed_nanos = 0
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def elapsed_nanos
|
|
104
|
+
if running?
|
|
105
|
+
now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
|
|
106
|
+
return (now - @start_nanos) + @elapsed_nanos
|
|
107
|
+
end
|
|
108
|
+
@elapsed_nanos
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def elapsed_millis
|
|
112
|
+
elapsed_nanos / 1_000_000
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def to_s
|
|
116
|
+
value_with_unit = PrettyUnitFormatter.scale_nanos_with_unit(elapsed_nanos)
|
|
117
|
+
return "'#{@name}' elapsed: #{value_with_unit}" if @name
|
|
118
|
+
value_with_unit.to_s
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class PrettyUnitFormatter
|
|
122
|
+
@units = [
|
|
123
|
+
{name: "day", divisor: 1_000_000_000 * 60 * 60 * 24},
|
|
124
|
+
{name: "hour", divisor: 1_000_000_000 * 60 * 60},
|
|
125
|
+
{name: "min", divisor: 1_000_000_000 * 60},
|
|
126
|
+
{name: "s", divisor: 1_000_000_000},
|
|
127
|
+
{name: "ms", divisor: 1_000_000},
|
|
128
|
+
{name: "μs", divisor: 1_000},
|
|
129
|
+
{name: "ns", divisor: 1}
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
class << self
|
|
133
|
+
def get_unit(nanos)
|
|
134
|
+
found_unit = @units.find { |unit| nanos >= unit[:divisor] }
|
|
135
|
+
raise "No matching unit found for #{nanos}" if found_unit.nil?
|
|
136
|
+
found_unit
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def scale_nanos_with_unit(nanos)
|
|
140
|
+
return "0 ns" if nanos.zero?
|
|
141
|
+
unit = get_unit(nanos)
|
|
142
|
+
value = nanos / unit[:divisor].to_f
|
|
143
|
+
"#{format_float(value)} #{unit[:name]}"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# format float to 3dp & remove trailing zeros
|
|
147
|
+
private def format_float(float)
|
|
148
|
+
sprintf("%f", float.round(3)).sub(/\.?0*$/, "")
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|