• Stars
    star
    156
  • Rank 239,589 (Top 5 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 6 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A sensible interface to monotonic time in Ruby

Gem Version Build Status Inline docs Yard Docs

Monotime

A sensible interface to Ruby's monotonic clock, inspired by Rust.

Installation

Add this line to your application's Gemfile:

gem 'monotime'

And then execute:

$ bundle

Or install it yourself as:

$ gem install monotime

Monotime is tested on Ruby 2.5—3.1, TruffleRuby, and recent JRuby 9.x releases.

Usage

require 'monotime'
# or, to automatically include Monotime::* in the global scope,
# as used by these examples:
require 'monotime/include'

Monotime offers a Duration type for describing spans of time, and an Instant type for describing points in time. Both operate at nanosecond resolution to the limits of whatever your Ruby implementation supports.

For example, to measure an elapsed time, either create an Instant to mark the start point, perform the action and then ask for the Duration that has elapsed since:

start = Instant.now
do_something
elapsed = start.elapsed

Or use a convenience method:

elapsed = Duration.measure { do_something }
# or
return_value, elapsed = Duration.with_measure { compute_something }

Duration offers formatting:

Duration.millis(42).to_s       # => "42ms"
Duration.nanos(12345).to_s     # => "12.345μs"
Duration.secs(1.12345).to_s(2) # => "1.12s"

Conversions:

Duration.secs(10).millis    # => 10000.0
Duration.micros(12345).secs # => 0.012345

And basic mathematical operations:

(Duration.millis(42) + Duration.secs(1)).to_s  # => "1.042s"
(Duration.millis(42) - Duration.secs(1)).to_s  # => "-958ms"
(Duration.secs(42) * 2).to_s                   # => "84s"
(Duration.secs(42) / 2).to_s                   # => "21s"

Instant does some simple maths too:

# Instant - Duration => Instant
(Instant.now - Duration.secs(1)).elapsed.to_s      # => "1.000014627s"

# Instant - Instant => Duration
(Instant.now - Instant.now).to_s                   # => "-5.585μs"

Duration and Instant are also Comparable with other instances of their type, and can be used in hashes, sets, and similar structures.

Sleeping

Duration can be used to sleep a thread, assuming it's positive (time travel is not yet implemented):

# Equivalent
sleep(Duration.secs(1).secs)  # => 1
Duration.secs(1).sleep        # => 1

So can Instant, taking a Duration and sleeping until the given Duration past the time the Instant was created, if any. This can be useful for maintaining a precise cadence between tasks:

interval = Duration.secs(60)
start = Instant.now
loop do
  do_stuff
  start.sleep(interval)
  start += interval
end

Or you can declare an Instant in the future and sleep to that point:

interval = Duration.secs(60)
deadline = Instant.now + interval
loop do
  do_stuff
  deadline.sleep
  deadline += interval
end

Instant#sleep returns a Duration which was slept, or a negative Duration indicating that the desired sleep point was in the past.

Duration duck typing

Operations taking a Duration can also accept any type which implements #to_nanos, returning an (Integer) number of nanoseconds the value represents.

For example, to treat built-in numeric types as second durations, you could do:

class Numeric
  def to_nanos
    Integer(self * 1_000_000_000)
  end
end

(Duration.secs(1) + 41).to_s  # => "42s"
(Instant.now - 42).to_s       # => "42.000010545s"

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/Freaky/monotime.

License

The gem is available as open source under the terms of the MIT License.

See Also

Core Ruby

For a zero-dependency alternative, see Process.clock_gettime. monotime currently only uses Process::CLOCK_MONOTONIC, but others may offer higher precision depending on platform.

Other Gems

hitimes is a popular and mature alternative which also includes a variety of features for gathering statistics about measurements, and may offer higher precision on some platforms.

More Repositories

1

Compactor

A user interface for Windows 10 filesystem compression
Rust
1,148
star
2

tarssh

A simple SSH tarpit inspired by endlessh
Rust
127
star
3

cw

A Rust wc clone
Rust
101
star
4

rtss

Relative TimeStamps for Stuff
Rust
51
star
5

zfsnapr

Recursive ZFS snapshot mounter
Ruby
24
star
6

rust-linereader

A fast Rust line reader
Rust
23
star
7

borg-backup.sh

A simple shell script for driving BorgBackup
Shell
20
star
8

fast-memchr

A port of rust-memchr's fallback and SSE2 memchr() to C
C
19
star
9

faccess

Cross-platform file access checks in Rust
Rust
16
star
10

rust-proctitle

A safe cross-platform interface to setting process titles
Rust
16
star
11

checkrestart

sysutils/checkrestart: A FreeBSD tool to find stale processes that may need restarting after an upgrade
C
14
star
12

gcstool

A small tool for creating and searching Golomb Compressed Sets
Rust
13
star
13

rust-filesize

Physical disk use retrieval
Rust
12
star
14

pqsort

A generic partial quicksort macro for C99.
C++
12
star
15

run-one

A BSD-compatible reimplementation of Ubuntu's run-one
Shell
11
star
16

compresstimator

Simple and fast compressibility tester
Rust
10
star
17

mkjail

Create minimal jail environments on FreeBSD
Ruby
9
star
18

elite_shield_tester

A Rust port of Down To Earth Astronomy's Elite Dangerous shield tester
Rust
8
star
19

mkpass

Generates reasonably secure passwords
Rust
5
star
20

annoirc

A bot to annotate IRC with information about posted links
Rust
5
star
21

portacl-rc

A FreeBSD rc(8) script for mac_portacl(4)
Roff
4
star
22

pkg-cruft

Find cruft on pkgng systems like FreeBSD
Ruby
4
star
23

TerraIntrimmer

Trim the notification queue from Terra Invicta saves
Rust
3
star
24

fast-bytecount

A port of the Rust bytecount SSE2 and AVX2 algorithms to C
M4
3
star
25

ruby-reattempt

Yet another Ruby retry library.
Ruby
3
star
26

rust-bitrw

A Rust library for bit-level reading and writing
Rust
3
star
27

esc

Email Search Command, because Email Sucks Completely
Rust
3
star
28

blooming-rust

Disk-backed Bloom Filters for Rust
Rust
3
star
29

par_qsort

A quick and dirty parallel quicksort in Rust
Rust
2
star
30

simplepass

Simple Ruby and Rust password generation
Rust
2
star
31

tikibar

Prototypical Ruby progress bar library
Ruby
2
star
32

ruby-capsicum

A Ruby interface to Capsicum sandboxing
Ruby
2
star
33

blooming-ruby

Ruby BitArray and BloomFilter library
Ruby
1
star
34

quickhash

Multithreaded stream hashing
Rust
1
star
35

IMSErious

Execute commands in response to Dovecot's Internet Message Store Event notifications
Rust
1
star
36

ruby-filemon

A Ruby interface to FreeBSD's filemon(4) device
Ruby
1
star
37

numastat

FreeBSD NUMA domain memory monitor
Python
1
star
38

nfo.fcgi

Newzbin's ancient FastCGI NFO service
Ruby
1
star
39

123-spellcheck

An email spellchecker I made for a friend
Rust
1
star
40

unprivileged

Privilege dropping for Rust
Rust
1
star
41

precache

Read the contents of a directory tree and hope it has useful side-effects
Rust
1
star
42

ruby-gcs

A small Ruby library for creating and searching Golomb Compressed Sets
Ruby
1
star
43

swapflush

Flush swap devices on FreeBSD
C
1
star