GithubHelp home page GithubHelp logo

Comments (5)

kaylareopelle avatar kaylareopelle commented on July 20, 2024 2

While pairing with @amhuntsman on this today, we determined Process.clock_gettime(Process::CLOCK_MONOTONIC) is our preferred value to replace Time.now when used as a float. Its purpose as defined by POSIX seems more appropriate than CLOCK_REALTIME for calculating the durations commonly recorded by the agent.

from newrelic-ruby-agent.

mwlang avatar mwlang commented on July 20, 2024 1

@viraptor thanks for the additional use-case where switching can be highly beneficial. We definitely want to do this, but felt it was best to deprecate support for Ruby 2.0 (which is happening with our upcoming 7.0 release) before tackling this issue.

from newrelic-ruby-agent.

mwlang avatar mwlang commented on July 20, 2024 1

With Ruby 2.0 and 2.1 deprecated for 7.0.0 release, this issue should be prioritized for inclusion an upcoming release.

Using either Process.clock_realtime (good enough and fastest) or more pedantically correct Process.clock_monotonic would improve all our duration calculations by as much as 2.7 times over Time.now

Benchmark Results

Allocations -------------------------------------
            Time.now       1/1  alloc/ret        0/0  strings/ret
Process.clock_realtime
                           0/0  alloc/ret        0/0  strings/ret
Process.clock_monotonic
                           0/0  alloc/ret        0/0  strings/ret
Warming up --------------------------------------
            Time.now    28.525k i/100ms
Process.clock_realtime
                        41.243k i/100ms
Process.clock_monotonic
                        41.683k i/100ms
Calculating -------------------------------------
            Time.now    512.386k (± 3.8%) i/s -      2.567M
Process.clock_realtime
                          1.413M (± 4.3%) i/s -      7.053M
Process.clock_monotonic
                          1.340M (± 4.1%) i/s -      6.711M

Comparison:
Process.clock_realtime:  1412578.4 i/s
Process.clock_monotonic:  1340018.5 i/s - same-ish: difference falls within error
            Time.now:   512385.8 i/s - 2.76x slower

Benchmark code for above results:

require 'benchmark/ips'
require 'benchmark/ipsa'

def process_clock_realtime
  now = Process.clock_gettime(Process::CLOCK_REALTIME)
  @realtime_start ||= now
  now - @realtime_start
end

def process_clock_monotonic
  now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  @monotonic_start ||= now
  now - @monotonic_start
end

def time_now
  now = Time.now
  @time_start ||= now
  (now - @time_start).to_f
end

def check_timing_math method_name
  yield
  sleep(1.0)
  results = yield
  return if (1.0..1.01).include?(results)
  raise "bad timing info for #{method_name} -- #{results} outside tolerance window"
end

check_timing_math("Time.now") { time_now }
check_timing_math("Process.clock_realtime") { process_clock_realtime }
check_timing_math("Process.clock_monotonic") { process_clock_monotonic }

Benchmark.ipsa do |x|
  x.report("Time.now") { time_now }
  x.report("Process.clock_realtime") { process_clock_realtime }
  x.report("Process.clock_monotonic") { process_clock_monotonic }

  x.compare!
end

from newrelic-ruby-agent.

rachelleahklein avatar rachelleahklein commented on July 20, 2024

Hi, @sdemjanenko - thank you for your suggestion! We have brought this up with our Product Manager, who will determine whether it will be added to our roadmap, and if so, what its priority will be.

from newrelic-ruby-agent.

viraptor avatar viraptor commented on July 20, 2024

Additional benefits for this change - Process.clock_gettime(Process::CLOCK_MONOTONIC) returns a float which can be used directly by most of the duration-calculating code. This means the agent can stop constructing Time.now all over the place. In my case that's ~1000 new Time objects on each request just from the tracing which uses Time.now.to_f to calculate duration.

from newrelic-ruby-agent.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.