Comments (5)
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.
@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.
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.
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.
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)
- browser_monitoring throws exception on non string HTTP header Content-Type HOT 7
- [Spike] Prototype streaming support for Bedrock (AI SDK) HOT 1
- Concurrent Ruby: Stop assuming a version number is available where we expect it to be HOT 4
- OpenAI: implement streaming support HOT 2
- Rails 7.1 ArgumentError: wrong number of arguments (given 3, expected 2) HOT 3
- Remove plumbing for `conversation_id` HOT 2
- Serverless: Get Ruby layers published HOT 1
- Serverless: Update Lambda CLI tool HOT 2
- Serverless: Update extension repo HOT 2
- Serverless: Update public docs site content HOT 2
- Serverless: Work with GTS to beta test HOT 2
- Instrument Solid Queue HOT 3
- Spike: Dynamic applying of an ideal linter configuration against new code HOT 1
- Serverless: raised exceptions / failed invocations aren't reaching Errors Inbox HOT 1
- Serverless: confirm what is possible with log data HOT 1
- Serverless: when an exception is raised, the agent can spend too much time processing it HOT 2
- Serverless: NR Ruby layer's GEM_PATH and RUBYLIB paths might conflict with those of the observed function HOT 3
- Serverless: Lambda layer Ruby wrapper doesn't support proper module namespacing HOT 2
- Serverless: Ensure via the Serverless UI that no blue banner warnings about CloudWatch log data appear HOT 3
- Cloud GUIDS: Instrument AWS SDK's Seahorse HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from newrelic-ruby-agent.