|
1 | 1 | module Concurrent
|
2 | 2 |
|
3 |
| - if defined?(Process::CLOCK_MONOTONIC) |
4 |
| - def monotonic_time |
5 |
| - Process.clock_gettime(Process::CLOCK_MONOTONIC) |
6 |
| - end |
7 |
| - elsif RUBY_PLATFORM == 'java' |
8 |
| - def monotonic_time |
9 |
| - java.lang.System.nanoTime() / 1_000_000_000.0 |
10 |
| - end |
11 |
| - else |
| 3 | + GLOBAL_MONOTONIC_CLOCK = Class.new { |
| 4 | + |
| 5 | + if defined?(Process::CLOCK_MONOTONIC) |
| 6 | + def get_time(other = 0.0) |
| 7 | + Process.clock_gettime(Process::CLOCK_MONOTONIC) - other.to_f |
| 8 | + end |
| 9 | + elsif RUBY_PLATFORM == 'java' |
| 10 | + def get_time(other = 0.0) |
| 11 | + (java.lang.System.nanoTime() / 1_000_000_000.0) - other.to_f |
| 12 | + end |
| 13 | + else |
12 | 14 |
|
13 |
| - require 'thread' |
| 15 | + require 'thread' |
14 | 16 |
|
15 |
| - # @!visibility private |
16 |
| - GLOBAL_MONOTONIC_CLOCK = Class.new { |
| 17 | + # @!visibility private |
17 | 18 | def initialize
|
18 | 19 | @mutex = Mutex.new
|
19 | 20 | @correction = 0
|
20 | 21 | @last_time = Time.now.to_f
|
21 | 22 | end
|
22 |
| - def get_time |
23 |
| - @mutex.synchronize do |
| 23 | + |
| 24 | + def get_time(other = 0.0) |
| 25 | + @mutex.synchronize { |
24 | 26 | @correction ||= 0 # compensating any back time shifts
|
25 | 27 | now = Time.now.to_f
|
26 | 28 | corrected_now = now + @correction
|
27 | 29 | if @last_time < corrected_now
|
28 |
| - return @last_time = corrected_now |
| 30 | + @last_time = corrected_now |
29 | 31 | else
|
30 | 32 | @correction += @last_time - corrected_now + 0.000_001
|
31 |
| - return @last_time = @correction + now |
| 33 | + @last_time = @correction + now |
32 | 34 | end
|
33 |
| - end |
| 35 | + } - other.to_f |
34 | 36 | end
|
35 |
| - }.new |
| 37 | + end |
| 38 | + }.new |
| 39 | + |
| 40 | + def monotonic_time(other = 0.0) |
| 41 | + GLOBAL_MONOTONIC_CLOCK.get_time(other) |
| 42 | + end |
| 43 | + module_function :monotonic_time |
| 44 | +end |
| 45 | + |
| 46 | +__END__ |
| 47 | + |
| 48 | +#!/usr/bin/env ruby |
| 49 | + |
| 50 | +# $ ./time_test.rb |
| 51 | +# Native: 1735.94062338, Ruby: 1425391307.2322402 |
| 52 | +# user system total real |
| 53 | +# Native time... |
| 54 | +# 0.310000 0.000000 0.310000 ( 0.306102) |
| 55 | +# Ruby time... |
| 56 | +# 1.750000 0.000000 1.750000 ( 1.757991) |
| 57 | +# Native interval... |
| 58 | +# 0.360000 0.010000 0.370000 ( 0.358779) |
| 59 | +# Ruby interval... |
| 60 | +# 1.850000 0.000000 1.850000 ( 1.857620) |
| 61 | +# Native: 1740.221591108, Ruby: 1425391312.2985182 |
| 62 | + |
| 63 | +$: << File.expand_path('./lib', __FILE__) |
| 64 | + |
| 65 | +require 'benchmark' |
| 66 | +require 'thread' |
| 67 | + |
| 68 | +class MonotonicClock |
| 69 | + def initialize |
| 70 | + @mutex = Mutex.new |
| 71 | + @correction = 0 |
| 72 | + @last_time = Time.now.to_f |
| 73 | + end |
| 74 | + |
| 75 | + def get_time_native |
| 76 | + Process.clock_gettime(Process::CLOCK_MONOTONIC) |
| 77 | + end |
36 | 78 |
|
37 |
| - def monotonic_time |
38 |
| - GLOBAL_MONOTONIC_CLOCK.get_time |
| 79 | + def get_interval_native(other) |
| 80 | + Process.clock_gettime(Process::CLOCK_MONOTONIC) - other.to_f |
| 81 | + end |
| 82 | + |
| 83 | + def get_time_ruby |
| 84 | + @mutex.synchronize do |
| 85 | + @correction ||= 0 # compensating any back time shifts |
| 86 | + now = Time.now.to_f |
| 87 | + corrected_now = now + @correction |
| 88 | + if @last_time < corrected_now |
| 89 | + return @last_time = corrected_now |
| 90 | + else |
| 91 | + @correction += @last_time - corrected_now + 0.000_001 |
| 92 | + return @last_time = @correction + now |
| 93 | + end |
39 | 94 | end
|
40 | 95 | end
|
41 | 96 |
|
42 |
| - module_function :monotonic_time |
| 97 | + def get_interval_ruby(other) |
| 98 | + get_time_ruby - other.to_f |
| 99 | + end |
43 | 100 | end
|
| 101 | + |
| 102 | +COUNT = 2_000_000 |
| 103 | +CLOCK = MonotonicClock.new |
| 104 | + |
| 105 | +native_now = CLOCK.get_time_native |
| 106 | +ruby_now = CLOCK.get_time_ruby |
| 107 | + |
| 108 | +puts "Native: #{native_now}, Ruby: #{ruby_now}" |
| 109 | + |
| 110 | +Benchmark.bm do |bm| |
| 111 | + |
| 112 | + puts "Native time..." |
| 113 | + bm.report do |
| 114 | + COUNT.times{ CLOCK.get_time_native } |
| 115 | + end |
| 116 | + |
| 117 | + puts "Ruby time..." |
| 118 | + bm.report do |
| 119 | + COUNT.times{ CLOCK.get_time_ruby } |
| 120 | + end |
| 121 | + |
| 122 | + puts "Native interval..." |
| 123 | + bm.report do |
| 124 | + COUNT.times{ CLOCK.get_interval_native(native_now) } |
| 125 | + end |
| 126 | + |
| 127 | + puts "Ruby interval..." |
| 128 | + bm.report do |
| 129 | + COUNT.times{ CLOCK.get_interval_ruby(ruby_now) } |
| 130 | + end |
| 131 | +end |
| 132 | + |
| 133 | +puts "Native: #{CLOCK.get_time_native}, Ruby: #{CLOCK.get_time_ruby}" |
0 commit comments