pretty_stopwatch 0.1.1 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfc13ff6a5acab33b4e2ddabd5b13132cebb33ab62e559ab93341326d228a85e
4
- data.tar.gz: 0c5cf9078b6c57adea68080d260c3b1527e2d5c89ab3151a313233fc1c7a7dee
3
+ metadata.gz: f6c38e209a9aed274b4b020c88f62f806d627b7f4f52b1bf6ac25c8d4ef90ca1
4
+ data.tar.gz: cbf674f15bd8ba525a3a22ed957f7de8eab06fe228c2dc749b9e56811cf97116
5
5
  SHA512:
6
- metadata.gz: 7be811ebd615a0a341cf6312d9c6ab2ae26f73afedb3bedcec0934c110aa67a0f8583df2b1bf34b405d1d07a8d5bc225590992a1a5cd34f0ea282735d69c6800
7
- data.tar.gz: 5752c08a7122c2f151ba9050df5a57a70f659eef2e79aa996b66663a4424084d36e1f18667cde9b38d46d096a564660b1a1335a6758e522dcacd1849365b3f02
6
+ metadata.gz: 6eea6338238a1def7bb6421e0183c9f19d7f5f22eb2909b293e8bdcda3809c32bd5f7cd9b9fb9bbd68e8c999ddcef423a59c5abb284b051766de4b5dc4ee19c4
7
+ data.tar.gz: 1caa1fd00ec324547fe0074deb304ebc3240abe4b314299a76440f8efadc823bb495c145c2cdfbd114ce9e1a62472b2ba4e829a62146eece0d7f25bd2770a475
data/README.md CHANGED
@@ -1,20 +1,27 @@
1
1
  # PrettyStopwatch
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ A simple Stopwatch with nanosecond precision and readable formatting.
4
4
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/pretty_stopwatch`. To experiment with that code, run `bin/console` for an interactive prompt.
5
+ Basic Usage:
6
+
7
+ stopwatch = Stopwatch::create_started
8
+ sleep(0.1)
9
+ stopwatch.stop # optional
10
+ puts "slept for #{stopwatch}" # to_s optional
11
+ # slept for 100.02 ms
6
12
 
7
- ## Installation
8
13
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
14
+ Based on the Guava Stopwatch com.google.common.base.Stopwatch. Credit: The Guava Authors
15
+
16
+ ## Installation
10
17
 
11
18
  Install the gem and add to the application's Gemfile by executing:
12
19
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
20
+ $ bundle add pretty_stopwatch
14
21
 
15
22
  If bundler is not being used to manage dependencies, install the gem by executing:
16
23
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
24
+ $ gem install pretty_stopwatch
18
25
 
19
26
  ## Usage
20
27
 
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.1"
5
- end
1
+ # frozen_string_literal: true
2
+
3
+ module PrettyStopwatch
4
+ VERSION = "0.1.3"
5
+ end
@@ -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
- # Stopwatch methods are not idempotent; it is an error to start or stop a stopwatch that is already in the desired state.
40
- class IllegalStateError < StandardError
41
- end
42
-
43
- @start_nanos
44
- attr_reader :name
45
- attr_reader :running
46
- attr_reader :elapsed_nanos
47
-
48
- def initialize(name = nil, elapsed_nanos) # optional variable
49
- @name = name
50
- @start_nanos = nil
51
- @running = false
52
- @elapsed_nanos = elapsed_nanos
53
- end
54
-
55
- def running?
56
- @running
57
- end
58
-
59
- def stopped?
60
- !@running
61
- end
62
-
63
- private_class_method :new # private constructor
64
-
65
- class << self
66
-
67
- def create_started(name = nil, elapsed_nanos: 0)
68
- self.new(name, elapsed_nanos).start
69
- end
70
-
71
- def create_unstarted(name = nil, elapsed_nanos: 0)
72
- self.new(name, elapsed_nanos)
73
- end
74
-
75
- def time(callable = nil, &block)
76
- stopwatch = self.create_started
77
- if callable
78
- callable.call
79
- elsif block_given?
80
- block.call # yield also valid
81
- else
82
- raise "no callable/block given" # todo
83
- end
84
- stopwatch.stop
85
- end
86
- end
87
-
88
- def start
89
- raise IllegalStateError, "Stopwatch is already running" if @running
90
- @running = true
91
- @start_nanos = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
92
- self
93
- end
94
-
95
- def stop
96
- raise IllegalStateError, "Stopwatch is already stopped" unless @running
97
- @elapsed_nanos += Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - @start_nanos
98
- @running = false
99
- self
100
- end
101
-
102
- # reset the elapsed time and stop the stopwatch
103
- def reset
104
- @running = false
105
- @elapsed_nanos = 0
106
- end
107
-
108
- def elapsed_nanos
109
- if running?
110
- now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
111
- return (now - @start_nanos) + @elapsed_nanos
112
- end
113
- @elapsed_nanos
114
- end
115
-
116
- def elapsed_millis
117
- elapsed_nanos / 1_000_000
118
- end
119
-
120
- def to_s
121
- value_with_unit = PrettyUnitFormatter::scale_nanos_with_unit(elapsed_nanos)
122
- return "'#{@name}' elapsed: #{value_with_unit}" if @name
123
- "#{value_with_unit}"
124
- end
125
-
126
- class PrettyUnitFormatter
127
- @units = [
128
- { name: 'day', divisor: 1_000_000_000 * 60 * 60 * 24 },
129
- { name: 'hour', divisor: 1_000_000_000 * 60 * 60 },
130
- { name: 'min', divisor: 1_000_000_000 * 60 },
131
- { name: 's', divisor: 1_000_000_000 },
132
- { name: 'ms', divisor: 1_000_000 },
133
- { name: 'μs', divisor: 1_000 },
134
- { name: 'ns', divisor: 1 }
135
- ]
136
-
137
- class << self
138
-
139
- def get_unit(nanos)
140
- found_unit = @units.find { |unit| nanos >= unit[:divisor] }
141
- raise "No matching unit found for #{nanos}" if found_unit.nil?
142
- found_unit
143
- end
144
-
145
- def scale_nanos_with_unit(nanos)
146
- return "0 ns" if nanos.zero?
147
- unit = get_unit(nanos)
148
- value = nanos / unit[:divisor].to_f
149
- "#{format_float(value)} #{unit[:name]}"
150
- end
151
-
152
- # format float to 3dp & remove trailing zeros
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pretty_stopwatch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Mcfadyen
@@ -24,7 +24,7 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.2'
27
- description: Pretty Stopwatch
27
+ description: A simple Stopwatch with nanosecond precision and readable formatting.
28
28
  email:
29
29
  - ben.mcfadyen3@gmail.com
30
30
  executables: []
@@ -65,5 +65,5 @@ requirements: []
65
65
  rubygems_version: 3.5.11
66
66
  signing_key:
67
67
  specification_version: 4
68
- summary: Pretty Stopwatch
68
+ summary: A simple Stopwatch with nanosecond precision and readable formatting.
69
69
  test_files: []